NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
crypt_gpgme.c
Go to the documentation of this file.
1 
35 #include "config.h"
36 #include <errno.h>
37 #include <gpg-error.h>
38 #include <gpgme.h>
39 #include <langinfo.h>
40 #include <locale.h>
41 #include <stdbool.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <strings.h>
46 #include <sys/stat.h>
47 #include <time.h>
48 #include <unistd.h>
49 #include "private.h"
50 #include "mutt/lib.h"
51 #include "address/lib.h"
52 #include "config/lib.h"
53 #include "email/lib.h"
54 #include "core/lib.h"
55 #include "alias/lib.h"
56 #include "gui/lib.h"
57 #include "mutt.h"
58 #include "crypt_gpgme.h"
59 #include "lib.h"
60 #include "question/lib.h"
61 #include "send/lib.h"
62 #include "crypt.h"
63 #include "handler.h"
64 #include "hook.h"
65 #include "mutt_attach.h"
66 #include "mutt_logging.h"
67 #include "muttlib.h"
68 #include "options.h"
69 #ifdef USE_AUTOCRYPT
70 #include "autocrypt/lib.h"
71 #endif
72 
73 // clang-format off
74 /* Values used for comparing addresses. */
75 #define CRYPT_KV_VALID (1 << 0)
76 #define CRYPT_KV_ADDR (1 << 1)
77 #define CRYPT_KV_STRING (1 << 2)
78 #define CRYPT_KV_STRONGID (1 << 3)
79 #define CRYPT_KV_MATCH (CRYPT_KV_ADDR | CRYPT_KV_STRING)
80 // clang-format on
81 
85 struct CryptCache
86 {
87  char *what;
88  char *dflt;
89  struct CryptCache *next;
90 };
91 
92 static struct CryptCache *id_defaults = NULL;
93 static gpgme_key_t signature_key = NULL;
94 static char *current_sender = NULL;
95 
96 #define PKA_NOTATION_NAME "pka-address@gnupg.org"
97 
98 #define _LINE_COMPARE(_x, _y) line_compare(_x, sizeof(_x) - 1, _y)
99 #define MESSAGE(_y) _LINE_COMPARE("MESSAGE-----", _y)
100 #define SIGNED_MESSAGE(_y) _LINE_COMPARE("SIGNED MESSAGE-----", _y)
101 #define PUBLIC_KEY_BLOCK(_y) _LINE_COMPARE("PUBLIC KEY BLOCK-----", _y)
102 #define BEGIN_PGP_SIGNATURE(_y) \
103  _LINE_COMPARE("-----BEGIN PGP SIGNATURE-----", _y)
104 
110 static bool is_pka_notation(gpgme_sig_notation_t notation)
111 {
112  return mutt_str_equal(notation->name, PKA_NOTATION_NAME);
113 }
114 
119 static void redraw_if_needed(gpgme_ctx_t ctx)
120 {
121 #if (GPGME_VERSION_NUMBER < 0x010800)
122  /* gpgme_get_ctx_flag is not available in GPGME < 1.8.0. In this case, stay
123  * on the safe side and always redraw. */
124  (void) ctx;
126 #else
127  const char *s = gpgme_get_ctx_flag(ctx, "redraw");
128  if (!s /* flag not known */ || *s /* flag true */)
129  {
131  }
132 #endif
133 }
134 
135 #if GPGRT_VERSION_NUMBER >= 0x012100 /* libgpg-error >= 1.33 */
136 
154 static int cmp_version_strings(const char *a, const char *b, int level)
155 {
156  return gpgrt_cmp_version(a, b, level);
157 }
158 #elif (GPGME_VERSION_NUMBER >= 0x010900) /* GPGME >= 1.9.0 */
159 
172 static const char *parse_version_number(const char *s, int *number)
173 {
174  int val = 0;
175 
176  if ((*s == '0') && isdigit(s[1]))
177  return NULL; /* Leading zeros are not allowed. */
178  for (; isdigit(s[0]); s++)
179  {
180  val *= 10;
181  val += *s - '0';
182  }
183  *number = val;
184  return (val < 0) ? NULL : s;
185 }
186 
205 static const char *parse_version_string(const char *s, int *major, int *minor, int *micro)
206 {
207  s = parse_version_number(s, major);
208  if (!s)
209  return NULL;
210  if (minor)
211  {
212  if (*s != '.')
213  return NULL;
214  s++;
215  s = parse_version_number(s, minor);
216  if (!s)
217  return NULL;
218  if (micro)
219  {
220  if (*s != '.')
221  return NULL;
222  s++;
223  s = parse_version_number(s, micro);
224  if (!s)
225  return NULL;
226  }
227  else
228  {
229  if (*s == '.')
230  s++;
231  }
232  }
233  else
234  {
235  if (*s == '.')
236  s++;
237  }
238  return s; /* patchlevel */
239 }
240 
250 static int cmp_version_strings(const char *a, const char *b, int level)
251 {
252  int a_major, a_minor, a_micro;
253  int b_major, b_minor, b_micro;
254  const char *a_plvl = NULL, *b_plvl = NULL;
255  int r;
256  int ignore_plvl;
257  int positive, negative;
258 
259  if (level < 0)
260  {
261  positive = -1;
262  negative = 1;
263  level = 0 - level;
264  }
265  else
266  {
267  positive = 1;
268  negative = -1;
269  }
270  if ((ignore_plvl = (level > 9)))
271  level %= 10;
272 
273  a_major = a_minor = a_micro = 0;
274  a_plvl = parse_version_string(a, &a_major, (level > 1) ? &a_minor : NULL,
275  (level > 2) ? &a_micro : NULL);
276  if (!a_plvl)
277  a_major = a_minor = a_micro = 0; /* Error. */
278 
279  b_major = b_minor = b_micro = 0;
280  b_plvl = parse_version_string(b, &b_major, (level > 1) ? &b_minor : NULL,
281  (level > 2) ? &b_micro : NULL);
282  if (!b_plvl)
283  b_major = b_minor = b_micro = 0;
284 
285  if (!ignore_plvl)
286  {
287  if (!a_plvl && !b_plvl)
288  return negative; /* Put invalid strings at the end. */
289  if (a_plvl && !b_plvl)
290  return positive;
291  if (!a_plvl && b_plvl)
292  return negative;
293  }
294 
295  if (a_major > b_major)
296  return positive;
297  if (a_major < b_major)
298  return negative;
299 
300  if (a_minor > b_minor)
301  return positive;
302  if (a_minor < b_minor)
303  return negative;
304 
305  if (a_micro > b_micro)
306  return positive;
307  if (a_micro < b_micro)
308  return negative;
309 
310  if (ignore_plvl)
311  return 0;
312 
313  for (; *a_plvl && *b_plvl; a_plvl++, b_plvl++)
314  {
315  if ((*a_plvl == '.') && (*b_plvl == '.'))
316  {
317  r = strcmp(a_plvl, b_plvl);
318  if (!r)
319  return 0;
320  if (r > 0)
321  return positive;
322  return negative;
323  }
324  if (*a_plvl == '.')
325  return negative; /* B is larger. */
326  if (*b_plvl == '.')
327  return positive; /* A is larger. */
328  if (*a_plvl != *b_plvl)
329  break;
330  }
331  if (*a_plvl == *b_plvl)
332  return 0;
333  if ((*(signed char *) a_plvl - *(signed char *) b_plvl) > 0)
334  return positive;
335  return negative;
336 }
337 #endif /* GPGME >= 1.9.0 */
338 
347 const char *crypt_keyid(struct CryptKeyInfo *k)
348 {
349  const char *s = "????????";
350 
351  if (k->kobj && k->kobj->subkeys)
352  {
353  s = k->kobj->subkeys->keyid;
354  const bool c_pgp_long_ids = cs_subset_bool(NeoMutt->sub, "pgp_long_ids");
355  if ((!c_pgp_long_ids) && (strlen(s) == 16))
356  {
357  /* Return only the short keyID. */
358  s += 8;
359  }
360  }
361 
362  return s;
363 }
364 
372 static const char *crypt_long_keyid(struct CryptKeyInfo *k)
373 {
374  const char *s = "????????????????";
375 
376  if (k->kobj && k->kobj->subkeys)
377  {
378  s = k->kobj->subkeys->keyid;
379  }
380 
381  return s;
382 }
383 
389 static const char *crypt_short_keyid(struct CryptKeyInfo *k)
390 {
391  const char *s = "????????";
392 
393  if (k->kobj && k->kobj->subkeys)
394  {
395  s = k->kobj->subkeys->keyid;
396  if (strlen(s) == 16)
397  s += 8;
398  }
399 
400  return s;
401 }
402 
408 static const char *crypt_fpr(struct CryptKeyInfo *k)
409 {
410  const char *s = "";
411 
412  if (k->kobj && k->kobj->subkeys)
413  s = k->kobj->subkeys->fpr;
414 
415  return s;
416 }
417 
423 const char *crypt_fpr_or_lkeyid(struct CryptKeyInfo *k)
424 {
425  const char *s = "????????????????";
426 
427  if (k->kobj && k->kobj->subkeys)
428  {
429  if (k->kobj->subkeys->fpr)
430  s = k->kobj->subkeys->fpr;
431  else
432  s = k->kobj->subkeys->keyid;
433  }
434 
435  return s;
436 }
437 
444 {
445  struct CryptKeyInfo *k = NULL;
446 
447  k = mutt_mem_calloc(1, sizeof(*k));
448  k->kobj = key->kobj;
449  gpgme_key_ref(key->kobj);
450  k->idx = key->idx;
451  k->uid = key->uid;
452  k->flags = key->flags;
453  k->validity = key->validity;
454 
455  return k;
456 }
457 
462 static void crypt_key_free(struct CryptKeyInfo **keylist)
463 {
464  if (!keylist)
465  return;
466 
467  struct CryptKeyInfo *k = NULL;
468 
469  while (*keylist)
470  {
471  k = *keylist;
472  *keylist = (*keylist)->next;
473 
474  gpgme_key_unref(k->kobj);
475  FREE(&k);
476  }
477 }
478 
485 {
486  if (!key)
487  return false;
488 
489  bool is_strong = false;
490 
491  if ((key->flags & KEYFLAG_ISX509))
492  return true;
493 
494  switch (key->validity)
495  {
496  case GPGME_VALIDITY_MARGINAL:
497  case GPGME_VALIDITY_NEVER:
498  case GPGME_VALIDITY_UNDEFINED:
499  case GPGME_VALIDITY_UNKNOWN:
500  is_strong = false;
501  break;
502 
503  case GPGME_VALIDITY_FULL:
504  case GPGME_VALIDITY_ULTIMATE:
505  is_strong = true;
506  break;
507  }
508 
509  return is_strong;
510 }
511 
520 {
521  if (!key)
522  return 0;
523 
524  return !(key->flags & KEYFLAG_CANTUSE);
525 }
526 
537 static int crypt_id_matches_addr(struct Address *addr, struct Address *u_addr,
538  struct CryptKeyInfo *key)
539 {
540  int rc = 0;
541 
542  if (crypt_id_is_valid(key))
543  rc |= CRYPT_KV_VALID;
544 
545  if (crypt_id_is_strong(key))
546  rc |= CRYPT_KV_STRONGID;
547 
548  if (addr && u_addr)
549  {
550  if (addr->mailbox && u_addr->mailbox &&
551  mutt_istr_equal(addr->mailbox, u_addr->mailbox))
552  {
553  rc |= CRYPT_KV_ADDR;
554  }
555 
556  if (addr->personal && u_addr->personal &&
557  mutt_istr_equal(addr->personal, u_addr->personal))
558  {
559  rc |= CRYPT_KV_STRING;
560  }
561  }
562 
563  return rc;
564 }
565 
571 gpgme_ctx_t create_gpgme_context(bool for_smime)
572 {
573  gpgme_ctx_t ctx = NULL;
574 
575  gpgme_error_t err = gpgme_new(&ctx);
576 
577 #ifdef USE_AUTOCRYPT
578  const char *const c_autocrypt_dir =
579  cs_subset_path(NeoMutt->sub, "autocrypt_dir");
580  if (!err && OptAutocryptGpgme)
581  err = gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_OpenPGP, NULL, c_autocrypt_dir);
582 #endif
583 
584  if (err != 0)
585  {
586  mutt_error(_("error creating GPGME context: %s"), gpgme_strerror(err));
587  mutt_exit(1);
588  }
589 
590  if (for_smime)
591  {
592  err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS);
593  if (err != 0)
594  {
595  mutt_error(_("error enabling CMS protocol: %s"), gpgme_strerror(err));
596  mutt_exit(1);
597  }
598  }
599 
600  return ctx;
601 }
602 
611 static gpgme_data_t create_gpgme_data(void)
612 {
613  gpgme_data_t data = NULL;
614 
615  gpgme_error_t err = gpgme_data_new(&data);
616  if (err != 0)
617  {
618  mutt_error(_("error creating GPGME data object: %s"), gpgme_strerror(err));
619  mutt_exit(1);
620  }
621  return data;
622 }
623 
624 #if GPGME_VERSION_NUMBER >= 0x010900 /* GPGME >= 1.9.0 */
625 
632 static bool have_gpg_version(const char *version)
633 {
634  static char *engine_version = NULL;
635 
636  if (!engine_version)
637  {
638  gpgme_ctx_t ctx = NULL;
639  gpgme_engine_info_t engineinfo = NULL;
640 
641  ctx = create_gpgme_context(false);
642  engineinfo = gpgme_ctx_get_engine_info(ctx);
643  while (engineinfo && (engineinfo->protocol != GPGME_PROTOCOL_OpenPGP))
644  engineinfo = engineinfo->next;
645  if (engineinfo)
646  {
647  engine_version = mutt_str_dup(engineinfo->version);
648  }
649  else
650  {
651  mutt_debug(LL_DEBUG1, "Error finding GPGME PGP engine\n");
652  engine_version = mutt_str_dup("0.0.0");
653  }
654  gpgme_release(ctx);
655  }
656 
657  return cmp_version_strings(engine_version, version, 3) >= 0;
658 }
659 #endif
660 
667 static gpgme_data_t body_to_data_object(struct Body *a, bool convert)
668 {
669  int err = 0;
670  gpgme_data_t data = NULL;
671 
672  struct Buffer *tempfile = mutt_buffer_pool_get();
673  mutt_buffer_mktemp(tempfile);
674  FILE *fp_tmp = mutt_file_fopen(mutt_buffer_string(tempfile), "w+");
675  if (!fp_tmp)
676  {
677  mutt_perror(mutt_buffer_string(tempfile));
678  goto cleanup;
679  }
680 
681  mutt_write_mime_header(a, fp_tmp, NeoMutt->sub);
682  fputc('\n', fp_tmp);
683  mutt_write_mime_body(a, fp_tmp, NeoMutt->sub);
684 
685  if (convert)
686  {
687  int c, hadcr = 0;
688  unsigned char buf[1];
689 
690  data = create_gpgme_data();
691  rewind(fp_tmp);
692  while ((c = fgetc(fp_tmp)) != EOF)
693  {
694  if (c == '\r')
695  hadcr = 1;
696  else
697  {
698  if ((c == '\n') && !hadcr)
699  {
700  buf[0] = '\r';
701  gpgme_data_write(data, buf, 1);
702  }
703 
704  hadcr = 0;
705  }
706  /* FIXME: This is quite suboptimal */
707  buf[0] = c;
708  gpgme_data_write(data, buf, 1);
709  }
710  mutt_file_fclose(&fp_tmp);
711  gpgme_data_seek(data, 0, SEEK_SET);
712  }
713  else
714  {
715  mutt_file_fclose(&fp_tmp);
716  err = gpgme_data_new_from_file(&data, mutt_buffer_string(tempfile), 1);
717  if (err != 0)
718  {
719  mutt_error(_("error allocating data object: %s"), gpgme_strerror(err));
720  gpgme_data_release(data);
721  data = NULL;
722  /* fall through to unlink the tempfile */
723  }
724  }
725  unlink(mutt_buffer_string(tempfile));
726 
727 cleanup:
728  mutt_buffer_pool_release(&tempfile);
729  return data;
730 }
731 
739 static gpgme_data_t file_to_data_object(FILE *fp, long offset, size_t length)
740 {
741  gpgme_data_t data = NULL;
742 
743  int err = gpgme_data_new_from_filepart(&data, NULL, fp, offset, length);
744  if (err != 0)
745  {
746  mutt_error(_("error allocating data object: %s"), gpgme_strerror(err));
747  return NULL;
748  }
749 
750  return data;
751 }
752 
760 static int data_object_to_stream(gpgme_data_t data, FILE *fp)
761 {
762  char buf[4096];
763  ssize_t nread;
764 
765  int err = ((gpgme_data_seek(data, 0, SEEK_SET) == -1) ? gpgme_error_from_errno(errno) : 0);
766  if (err != 0)
767  {
768  mutt_error(_("error rewinding data object: %s"), gpgme_strerror(err));
769  return -1;
770  }
771 
772  while ((nread = gpgme_data_read(data, buf, sizeof(buf))) > 0)
773  {
774  /* fixme: we are not really converting CRLF to LF but just
775  * skipping CR. Doing it correctly needs a more complex logic */
776  for (char *p = buf; nread; p++, nread--)
777  {
778  if (*p != '\r')
779  putc(*p, fp);
780  }
781 
782  if (ferror(fp))
783  {
784  mutt_perror(_("[tempfile]"));
785  return -1;
786  }
787  }
788  if (nread == -1)
789  {
790  mutt_error(_("error reading data object: %s"), strerror(errno));
791  return -1;
792  }
793  return 0;
794 }
795 
807 static char *data_object_to_tempfile(gpgme_data_t data, FILE **fp_ret)
808 {
809  ssize_t nread = 0;
810  char *rv = NULL;
811  struct Buffer *tempf = mutt_buffer_pool_get();
812 
813  mutt_buffer_mktemp(tempf);
814 
815  FILE *fp = mutt_file_fopen(mutt_buffer_string(tempf), "w+");
816  if (!fp)
817  {
818  mutt_perror(_("Can't create temporary file"));
819  goto cleanup;
820  }
821 
822  int err = ((gpgme_data_seek(data, 0, SEEK_SET) == -1) ? gpgme_error_from_errno(errno) : 0);
823  if (err == 0)
824  {
825  char buf[4096];
826 
827  while ((nread = gpgme_data_read(data, buf, sizeof(buf))) > 0)
828  {
829  if (fwrite(buf, nread, 1, fp) != 1)
830  {
832  mutt_file_fclose(&fp);
833  unlink(mutt_buffer_string(tempf));
834  goto cleanup;
835  }
836  }
837  }
838  if (fp_ret)
839  rewind(fp);
840  else
841  mutt_file_fclose(&fp);
842  if (nread == -1)
843  {
844  mutt_error(_("error reading data object: %s"), gpgme_strerror(err));
845  unlink(mutt_buffer_string(tempf));
846  mutt_file_fclose(&fp);
847  goto cleanup;
848  }
849  if (fp_ret)
850  *fp_ret = fp;
851  rv = mutt_buffer_strdup(tempf);
852 
853 cleanup:
854  mutt_buffer_pool_release(&tempf);
855  return rv;
856 }
857 
858 #if (GPGME_VERSION_NUMBER >= 0x010b00) /* GPGME >= 1.11.0 */
859 
865 static void create_recipient_string(const char *keylist, struct Buffer *recpstring, int use_smime)
866 {
867  unsigned int n = 0;
868 
869  const char *s = keylist;
870  do
871  {
872  while (*s == ' ')
873  s++;
874  if (*s != '\0')
875  {
876  if (n == 0)
877  {
878  if (!use_smime)
879  mutt_buffer_addstr(recpstring, "--\n");
880  }
881  else
882  mutt_buffer_addch(recpstring, '\n');
883  n++;
884 
885  while ((*s != '\0') && (*s != ' '))
886  mutt_buffer_addch(recpstring, *s++);
887  }
888  } while (*s != '\0');
889 }
890 
891 #else
892 
896 static void recipient_set_free(gpgme_key_t **p_rset)
897 {
898  gpgme_key_t *rset = NULL;
899 
900  if (!p_rset)
901  return;
902 
903  rset = *p_rset;
904  if (!rset)
905  return;
906 
907  while (*rset)
908  {
909  gpgme_key_t k = *rset;
910  gpgme_key_unref(k);
911  rset++;
912  }
913 
914  FREE(p_rset);
915 }
916 
923 static gpgme_key_t *create_recipient_set(const char *keylist, bool use_smime)
924 {
925  int err;
926  const char *s = NULL;
927  char buf[100];
928  gpgme_key_t *rset = NULL;
929  unsigned int rset_n = 0;
930  gpgme_key_t key = NULL;
931 
932  gpgme_ctx_t context = create_gpgme_context(use_smime);
933  s = keylist;
934  do
935  {
936  while (*s == ' ')
937  s++;
938  int i;
939  for (i = 0; *s && *s != ' ' && i < sizeof(buf) - 1;)
940  buf[i++] = *s++;
941  buf[i] = '\0';
942  if (*buf != '\0')
943  {
944  if ((i > 1) && (buf[i - 1] == '!'))
945  {
946  /* The user selected to override the validity of that key. */
947  buf[i - 1] = '\0';
948 
949  err = gpgme_get_key(context, buf, &key, 0);
950  if (err == 0)
951  key->uids->validity = GPGME_VALIDITY_FULL;
952  buf[i - 1] = '!';
953  }
954  else
955  err = gpgme_get_key(context, buf, &key, 0);
956  mutt_mem_realloc(&rset, sizeof(*rset) * (rset_n + 1));
957  if (err == 0)
958  rset[rset_n++] = key;
959  else
960  {
961  mutt_error(_("error adding recipient '%s': %s"), buf, gpgme_strerror(err));
962  rset[rset_n] = NULL;
963  recipient_set_free(&rset);
964  gpgme_release(context);
965  return NULL;
966  }
967  }
968  } while (*s);
969 
970  /* NULL terminate. */
971  mutt_mem_realloc(&rset, sizeof(*rset) * (rset_n + 1));
972  rset[rset_n++] = NULL;
973 
974  gpgme_release(context);
975 
976  return rset;
977 }
978 #endif /* GPGME_VERSION_NUMBER >= 0x010b00 */
979 
988 static bool set_signer_from_address(gpgme_ctx_t ctx, const char *address, bool for_smime)
989 {
990  gpgme_error_t err;
991  gpgme_key_t key = NULL, key2 = NULL;
992  gpgme_ctx_t listctx = create_gpgme_context(for_smime);
993  err = gpgme_op_keylist_start(listctx, address, 1);
994  if (err == 0)
995  err = gpgme_op_keylist_next(listctx, &key);
996  if (err)
997  {
998  gpgme_release(listctx);
999  mutt_error(_("secret key '%s' not found: %s"), address, gpgme_strerror(err));
1000  return false;
1001  }
1002 
1003  char *fpr = "fpr1";
1004  if (key->subkeys)
1005  fpr = key->subkeys->fpr ? key->subkeys->fpr : key->subkeys->keyid;
1006  while (gpgme_op_keylist_next(listctx, &key2) == 0)
1007  {
1008  char *fpr2 = "fpr2";
1009  if (key2->subkeys)
1010  fpr2 = key2->subkeys->fpr ? key2->subkeys->fpr : key2->subkeys->keyid;
1011  if (!mutt_str_equal(fpr, fpr2))
1012  {
1013  gpgme_key_unref(key);
1014  gpgme_key_unref(key2);
1015  gpgme_release(listctx);
1016  mutt_error(_("ambiguous specification of secret key '%s'\n"), address);
1017  return false;
1018  }
1019  else
1020  {
1021  gpgme_key_unref(key2);
1022  }
1023  }
1024  gpgme_op_keylist_end(listctx);
1025  gpgme_release(listctx);
1026 
1027  gpgme_signers_clear(ctx);
1028  err = gpgme_signers_add(ctx, key);
1029  gpgme_key_unref(key);
1030  if (err)
1031  {
1032  mutt_error(_("error setting secret key '%s': %s"), address, gpgme_strerror(err));
1033  return false;
1034  }
1035  return true;
1036 }
1037 
1046 static int set_signer(gpgme_ctx_t ctx, const struct AddressList *al, bool for_smime)
1047 {
1048  const char *signid = NULL;
1049 
1050  const char *const c_smime_sign_as =
1051  cs_subset_string(NeoMutt->sub, "smime_sign_as");
1052  const char *const c_pgp_sign_as =
1053  cs_subset_string(NeoMutt->sub, "pgp_sign_as");
1054  const char *const c_pgp_default_key =
1055  cs_subset_string(NeoMutt->sub, "pgp_default_key");
1056  const char *const c_smime_default_key =
1057  cs_subset_string(NeoMutt->sub, "smime_default_key");
1058  if (for_smime)
1059  signid = c_smime_sign_as ? c_smime_sign_as : c_smime_default_key;
1060 #ifdef USE_AUTOCRYPT
1061  else if (OptAutocryptGpgme)
1062  signid = AutocryptSignAs;
1063 #endif
1064  else
1065  signid = c_pgp_sign_as ? c_pgp_sign_as : c_pgp_default_key;
1066 
1067  /* Try getting the signing key from config entries */
1068  if (signid && set_signer_from_address(ctx, signid, for_smime))
1069  {
1070  return 0;
1071  }
1072 
1073  /* Try getting the signing key from the From line */
1074  if (al)
1075  {
1076  struct Address *a;
1077  TAILQ_FOREACH(a, al, entries)
1078  {
1079  if (a->mailbox && set_signer_from_address(ctx, a->mailbox, for_smime))
1080  {
1081  return 0;
1082  }
1083  }
1084  }
1085 
1086  return (!signid && !al) ? 0 : -1;
1087 }
1088 
1094 static gpgme_error_t set_pka_sig_notation(gpgme_ctx_t ctx)
1095 {
1096  gpgme_error_t err = gpgme_sig_notation_add(ctx, PKA_NOTATION_NAME, current_sender, 0);
1097  if (err)
1098  {
1099  mutt_error(_("error setting PKA signature notation: %s"), gpgme_strerror(err));
1100  }
1101 
1102  return err;
1103 }
1104 
1114 static char *encrypt_gpgme_object(gpgme_data_t plaintext, char *keylist, bool use_smime,
1115  bool combined_signed, const struct AddressList *from)
1116 {
1117  gpgme_error_t err;
1118  gpgme_ctx_t ctx = NULL;
1119  gpgme_data_t ciphertext = NULL;
1120  char *outfile = NULL;
1121 
1122 #if GPGME_VERSION_NUMBER >= 0x010b00 /* GPGME >= 1.11.0 */
1123  struct Buffer *recpstring = mutt_buffer_pool_get();
1124  create_recipient_string(keylist, recpstring, use_smime);
1125  if (mutt_buffer_is_empty(recpstring))
1126  {
1127  mutt_buffer_pool_release(&recpstring);
1128  return NULL;
1129  }
1130 #else
1131  gpgme_key_t *rset = create_recipient_set(keylist, use_smime);
1132  if (!rset)
1133  return NULL;
1134 #endif /* GPGME_VERSION_NUMBER >= 0x010b00 */
1135 
1136  ctx = create_gpgme_context(use_smime);
1137  if (!use_smime)
1138  gpgme_set_armor(ctx, 1);
1139 
1140  ciphertext = create_gpgme_data();
1141 
1142  if (combined_signed)
1143  {
1144  if (set_signer(ctx, from, use_smime))
1145  goto cleanup;
1146 
1147  const bool c_crypt_use_pka = cs_subset_bool(NeoMutt->sub, "crypt_use_pka");
1148  if (c_crypt_use_pka)
1149  {
1150  err = set_pka_sig_notation(ctx);
1151  if (err != 0)
1152  goto cleanup;
1153  }
1154 
1155 #if (GPGME_VERSION_NUMBER >= 0x010b00) /* GPGME >= 1.11.0 */
1156  err = gpgme_op_encrypt_sign_ext(ctx, NULL, mutt_buffer_string(recpstring),
1157  GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
1158 #else
1159  err = gpgme_op_encrypt_sign(ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
1160 #endif
1161  }
1162  else
1163  {
1164 #if (GPGME_VERSION_NUMBER >= 0x010b00) /* GPGME >= 1.11.0 */
1165  err = gpgme_op_encrypt_ext(ctx, NULL, mutt_buffer_string(recpstring),
1166  GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
1167 #else
1168  err = gpgme_op_encrypt(ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
1169 #endif
1170  }
1171 
1172  redraw_if_needed(ctx);
1173  if (err != 0)
1174  {
1175  mutt_error(_("error encrypting data: %s"), gpgme_strerror(err));
1176  goto cleanup;
1177  }
1178 
1179  outfile = data_object_to_tempfile(ciphertext, NULL);
1180 
1181 cleanup:
1182 #if (GPGME_VERSION_NUMBER >= 0x010b00) /* GPGME >= 1.11.0 */
1183  mutt_buffer_pool_release(&recpstring);
1184 #else
1185  recipient_set_free(&rset);
1186 #endif
1187  gpgme_release(ctx);
1188  gpgme_data_release(ciphertext);
1189  return outfile;
1190 }
1191 
1204 static int get_micalg(gpgme_ctx_t ctx, int use_smime, char *buf, size_t buflen)
1205 {
1206  gpgme_sign_result_t result = NULL;
1207  const char *algorithm_name = NULL;
1208 
1209  if (buflen < 5)
1210  return -1;
1211 
1212  *buf = '\0';
1213  result = gpgme_op_sign_result(ctx);
1214  if (result && result->signatures)
1215  {
1216  algorithm_name = gpgme_hash_algo_name(result->signatures->hash_algo);
1217  if (algorithm_name)
1218  {
1219  if (use_smime)
1220  {
1221  /* convert GPGME raw hash name to RFC2633 format */
1222  snprintf(buf, buflen, "%s", algorithm_name);
1223  mutt_str_lower(buf);
1224  }
1225  else
1226  {
1227  /* convert GPGME raw hash name to RFC3156 format */
1228  snprintf(buf, buflen, "pgp-%s", algorithm_name);
1229  mutt_str_lower(buf + 4);
1230  }
1231  }
1232  }
1233 
1234  return (buf[0] != '\0') ? 0 : -1;
1235 }
1236 
1242 static void print_time(time_t t, struct State *s)
1243 {
1244  char p[256];
1245  mutt_date_localtime_format(p, sizeof(p), nl_langinfo(D_T_FMT), t);
1246  state_puts(s, p);
1247 }
1248 
1257 static struct Body *sign_message(struct Body *a, const struct AddressList *from, bool use_smime)
1258 {
1259  struct Body *t = NULL;
1260  char *sigfile = NULL;
1261  int err = 0;
1262  char buf[100];
1263  gpgme_ctx_t ctx = NULL;
1264  gpgme_data_t message = NULL, signature = NULL;
1265  gpgme_sign_result_t sigres = NULL;
1266 
1267  crypt_convert_to_7bit(a); /* Signed data _must_ be in 7-bit format. */
1268 
1269  message = body_to_data_object(a, true);
1270  if (!message)
1271  return NULL;
1272  signature = create_gpgme_data();
1273 
1274  ctx = create_gpgme_context(use_smime);
1275  if (!use_smime)
1276  gpgme_set_armor(ctx, 1);
1277 
1278  if (set_signer(ctx, from, use_smime))
1279  {
1280  gpgme_data_release(signature);
1281  gpgme_data_release(message);
1282  gpgme_release(ctx);
1283  return NULL;
1284  }
1285 
1286  const bool c_crypt_use_pka = cs_subset_bool(NeoMutt->sub, "crypt_use_pka");
1287  if (c_crypt_use_pka)
1288  {
1289  err = set_pka_sig_notation(ctx);
1290  if (err != 0)
1291  {
1292  gpgme_data_release(signature);
1293  gpgme_data_release(message);
1294  gpgme_release(ctx);
1295  return NULL;
1296  }
1297  }
1298 
1299  err = gpgme_op_sign(ctx, message, signature, GPGME_SIG_MODE_DETACH);
1300  redraw_if_needed(ctx);
1301  gpgme_data_release(message);
1302  if (err != 0)
1303  {
1304  gpgme_data_release(signature);
1305  gpgme_release(ctx);
1306  mutt_error(_("error signing data: %s"), gpgme_strerror(err));
1307  return NULL;
1308  }
1309  /* Check for zero signatures generated. This can occur when $pgp_sign_as is
1310  * unset and there is no default key specified in ~/.gnupg/gpg.conf */
1311  sigres = gpgme_op_sign_result(ctx);
1312  if (!sigres->signatures)
1313  {
1314  gpgme_data_release(signature);
1315  gpgme_release(ctx);
1316  mutt_error(_("$pgp_sign_as unset and no default key specified in "
1317  "~/.gnupg/gpg.conf"));
1318  return NULL;
1319  }
1320 
1321  sigfile = data_object_to_tempfile(signature, NULL);
1322  gpgme_data_release(signature);
1323  if (!sigfile)
1324  {
1325  gpgme_release(ctx);
1326  return NULL;
1327  }
1328 
1329  t = mutt_body_new();
1330  t->type = TYPE_MULTIPART;
1331  t->subtype = mutt_str_dup("signed");
1332  t->encoding = ENC_7BIT;
1333  t->use_disp = false;
1334  t->disposition = DISP_INLINE;
1335 
1337  mutt_param_set(&t->parameter, "protocol",
1338  use_smime ? "application/pkcs7-signature" : "application/pgp-signature");
1339  /* Get the micalg from GPGME. Old gpgme versions don't support this
1340  * for S/MIME so we assume sha-1 in this case. */
1341  if (get_micalg(ctx, use_smime, buf, sizeof(buf)) == 0)
1342  mutt_param_set(&t->parameter, "micalg", buf);
1343  else if (use_smime)
1344  mutt_param_set(&t->parameter, "micalg", "sha1");
1345  gpgme_release(ctx);
1346 
1347  t->parts = a;
1348  a = t;
1349 
1350  t->parts->next = mutt_body_new();
1351  t = t->parts->next;
1352  t->type = TYPE_APPLICATION;
1353  if (use_smime)
1354  {
1355  t->subtype = mutt_str_dup("pkcs7-signature");
1356  mutt_param_set(&t->parameter, "name", "smime.p7s");
1357  t->encoding = ENC_BASE64;
1358  t->use_disp = true;
1359  t->disposition = DISP_ATTACH;
1360  t->d_filename = mutt_str_dup("smime.p7s");
1361  }
1362  else
1363  {
1364  t->subtype = mutt_str_dup("pgp-signature");
1365  mutt_param_set(&t->parameter, "name", "signature.asc");
1366  t->use_disp = false;
1367  t->disposition = DISP_NONE;
1368  t->encoding = ENC_7BIT;
1369  }
1370  t->filename = sigfile;
1371  t->unlink = true; /* ok to remove this file after sending. */
1372 
1373  return a;
1374 }
1375 
1379 struct Body *pgp_gpgme_sign_message(struct Body *a, const struct AddressList *from)
1380 {
1381  return sign_message(a, from, false);
1382 }
1383 
1387 struct Body *smime_gpgme_sign_message(struct Body *a, const struct AddressList *from)
1388 {
1389  return sign_message(a, from, true);
1390 }
1391 
1395 struct Body *pgp_gpgme_encrypt_message(struct Body *a, char *keylist, bool sign,
1396  const struct AddressList *from)
1397 {
1398  if (sign)
1400  gpgme_data_t plaintext = body_to_data_object(a, false);
1401  if (!plaintext)
1402  return NULL;
1403 
1404  char *outfile = encrypt_gpgme_object(plaintext, keylist, false, sign, from);
1405  gpgme_data_release(plaintext);
1406  if (!outfile)
1407  return NULL;
1408 
1409  struct Body *t = mutt_body_new();
1410  t->type = TYPE_MULTIPART;
1411  t->subtype = mutt_str_dup("encrypted");
1412  t->encoding = ENC_7BIT;
1413  t->use_disp = false;
1414  t->disposition = DISP_INLINE;
1415 
1417  mutt_param_set(&t->parameter, "protocol", "application/pgp-encrypted");
1418 
1419  t->parts = mutt_body_new();
1420  t->parts->type = TYPE_APPLICATION;
1421  t->parts->subtype = mutt_str_dup("pgp-encrypted");
1422  t->parts->encoding = ENC_7BIT;
1423 
1424  t->parts->next = mutt_body_new();
1426  t->parts->next->subtype = mutt_str_dup("octet-stream");
1427  t->parts->next->encoding = ENC_7BIT;
1428  t->parts->next->filename = outfile;
1429  t->parts->next->use_disp = true;
1431  t->parts->next->unlink = true; /* delete after sending the message */
1432  t->parts->next->d_filename = mutt_str_dup("msg.asc"); /* non pgp/mime
1433  can save */
1434 
1435  return t;
1436 }
1437 
1441 struct Body *smime_gpgme_build_smime_entity(struct Body *a, char *keylist)
1442 {
1443  /* OpenSSL converts line endings to crlf when encrypting. Some clients
1444  * depend on this for signed+encrypted messages: they do not convert line
1445  * endings between decrypting and checking the signature. */
1446  gpgme_data_t plaintext = body_to_data_object(a, true);
1447  if (!plaintext)
1448  return NULL;
1449 
1450  char *outfile = encrypt_gpgme_object(plaintext, keylist, true, false, NULL);
1451  gpgme_data_release(plaintext);
1452  if (!outfile)
1453  return NULL;
1454 
1455  struct Body *t = mutt_body_new();
1456  t->type = TYPE_APPLICATION;
1457  t->subtype = mutt_str_dup("pkcs7-mime");
1458  mutt_param_set(&t->parameter, "name", "smime.p7m");
1459  mutt_param_set(&t->parameter, "smime-type", "enveloped-data");
1460  t->encoding = ENC_BASE64; /* The output of OpenSSL SHOULD be binary */
1461  t->use_disp = true;
1462  t->disposition = DISP_ATTACH;
1463  t->d_filename = mutt_str_dup("smime.p7m");
1464  t->filename = outfile;
1465  t->unlink = true; /* delete after sending the message */
1466  t->parts = 0;
1467  t->next = 0;
1468 
1469  return t;
1470 }
1471 
1485 static int show_sig_summary(unsigned long sum, gpgme_ctx_t ctx, gpgme_key_t key,
1486  int idx, struct State *s, gpgme_signature_t sig)
1487 {
1488  if (!key)
1489  return 1;
1490 
1491  bool severe = false;
1492 
1493  if ((sum & GPGME_SIGSUM_KEY_REVOKED))
1494  {
1495  state_puts(s, _("Warning: One of the keys has been revoked\n"));
1496  severe = true;
1497  }
1498 
1499  if ((sum & GPGME_SIGSUM_KEY_EXPIRED))
1500  {
1501  time_t at = key->subkeys->expires ? key->subkeys->expires : 0;
1502  if (at)
1503  {
1504  state_puts(
1505  s, _("Warning: The key used to create the signature expired at: "));
1506  print_time(at, s);
1507  state_puts(s, "\n");
1508  }
1509  else
1510  {
1511  state_puts(s, _("Warning: At least one certification key has expired\n"));
1512  }
1513  }
1514 
1515  if ((sum & GPGME_SIGSUM_SIG_EXPIRED))
1516  {
1517  gpgme_signature_t sig2 = NULL;
1518  unsigned int i;
1519 
1520  gpgme_verify_result_t result = gpgme_op_verify_result(ctx);
1521 
1522  for (sig2 = result->signatures, i = 0; sig2 && (i < idx); sig2 = sig2->next, i++)
1523  ; // do nothing
1524 
1525  state_puts(s, _("Warning: The signature expired at: "));
1526  print_time(sig2 ? sig2->exp_timestamp : 0, s);
1527  state_puts(s, "\n");
1528  }
1529 
1530  if ((sum & GPGME_SIGSUM_KEY_MISSING))
1531  {
1532  state_puts(s, _("Can't verify due to a missing key or certificate\n"));
1533  }
1534 
1535  if ((sum & GPGME_SIGSUM_CRL_MISSING))
1536  {
1537  state_puts(s, _("The CRL is not available\n"));
1538  severe = true;
1539  }
1540 
1541  if ((sum & GPGME_SIGSUM_CRL_TOO_OLD))
1542  {
1543  state_puts(s, _("Available CRL is too old\n"));
1544  severe = true;
1545  }
1546 
1547  if ((sum & GPGME_SIGSUM_BAD_POLICY))
1548  state_puts(s, _("A policy requirement was not met\n"));
1549 
1550  if ((sum & GPGME_SIGSUM_SYS_ERROR))
1551  {
1552  const char *t0 = NULL, *t1 = NULL;
1553  gpgme_verify_result_t result = NULL;
1554  gpgme_signature_t sig2 = NULL;
1555  unsigned int i;
1556 
1557  state_puts(s, _("A system error occurred"));
1558 
1559  /* Try to figure out some more detailed system error information. */
1560  result = gpgme_op_verify_result(ctx);
1561  for (sig2 = result->signatures, i = 0; sig2 && (i < idx); sig2 = sig2->next, i++)
1562  ; // do nothing
1563 
1564  if (sig2)
1565  {
1566  t0 = "";
1567  t1 = sig2->wrong_key_usage ? "Wrong_Key_Usage" : "";
1568  }
1569 
1570  if (t0 || t1)
1571  {
1572  state_puts(s, ": ");
1573  if (t0)
1574  state_puts(s, t0);
1575  if (t1 && !(t0 && (strcmp(t0, t1) == 0)))
1576  {
1577  if (t0)
1578  state_puts(s, ",");
1579  state_puts(s, t1);
1580  }
1581  }
1582  state_puts(s, "\n");
1583  }
1584 
1585  const bool c_crypt_use_pka = cs_subset_bool(NeoMutt->sub, "crypt_use_pka");
1586  if (c_crypt_use_pka)
1587  {
1588  if ((sig->pka_trust == 1) && sig->pka_address)
1589  {
1590  state_puts(s, _("WARNING: PKA entry does not match signer's address: "));
1591  state_puts(s, sig->pka_address);
1592  state_puts(s, "\n");
1593  }
1594  else if ((sig->pka_trust == 2) && sig->pka_address)
1595  {
1596  state_puts(s, _("PKA verified signer's address is: "));
1597  state_puts(s, sig->pka_address);
1598  state_puts(s, "\n");
1599  }
1600  }
1601 
1602  return severe;
1603 }
1604 
1610 static void show_fingerprint(gpgme_key_t key, struct State *state)
1611 {
1612  if (!key)
1613  return;
1614 
1615  const char *prefix = _("Fingerprint: ");
1616 
1617  const char *s = key->subkeys ? key->subkeys->fpr : NULL;
1618  if (!s)
1619  return;
1620  bool is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
1621 
1622  char *buf = mutt_mem_malloc(strlen(prefix) + strlen(s) * 4 + 2);
1623  strcpy(buf, prefix);
1624  char *p = buf + strlen(buf);
1625  if (is_pgp && (strlen(s) == 40))
1626  { /* PGP v4 style formatted. */
1627  for (int i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++)
1628  {
1629  *p++ = s[0];
1630  *p++ = s[1];
1631  *p++ = s[2];
1632  *p++ = s[3];
1633  *p++ = ' ';
1634  if (i == 4)
1635  *p++ = ' ';
1636  }
1637  }
1638  else
1639  {
1640  for (int i = 0; *s && s[1] && s[2]; s += 2, i++)
1641  {
1642  *p++ = s[0];
1643  *p++ = s[1];
1644  *p++ = is_pgp ? ' ' : ':';
1645  if (is_pgp && (i == 7))
1646  *p++ = ' ';
1647  }
1648  }
1649 
1650  /* just in case print remaining odd digits */
1651  for (; *s; s++)
1652  *p++ = *s;
1653  *p++ = '\n';
1654  *p = '\0';
1655  state_puts(state, buf);
1656  FREE(&buf);
1657 }
1658 
1665 static void show_one_sig_validity(gpgme_ctx_t ctx, int idx, struct State *s)
1666 {
1667  gpgme_signature_t sig = NULL;
1668  const char *txt = NULL;
1669 
1670  gpgme_verify_result_t result = gpgme_op_verify_result(ctx);
1671  if (result)
1672  for (sig = result->signatures; sig && (idx > 0); sig = sig->next, idx--)
1673  ; // do nothing
1674 
1675  switch (sig ? sig->validity : 0)
1676  {
1677  case GPGME_VALIDITY_UNKNOWN:
1678  txt = _("WARNING: We have NO indication whether "
1679  "the key belongs to the person named "
1680  "as shown above\n");
1681  break;
1682  case GPGME_VALIDITY_UNDEFINED:
1683  break;
1684  case GPGME_VALIDITY_NEVER:
1685  txt = _("WARNING: The key does NOT BELONG to "
1686  "the person named as shown above\n");
1687  break;
1688  case GPGME_VALIDITY_MARGINAL:
1689  txt = _("WARNING: It is NOT certain that the key "
1690  "belongs to the person named as shown above\n");
1691  break;
1692  case GPGME_VALIDITY_FULL:
1693  case GPGME_VALIDITY_ULTIMATE:
1694  txt = NULL;
1695  break;
1696  }
1697  if (txt)
1698  state_puts(s, txt);
1699 }
1700 
1708 static void print_smime_keyinfo(const char *msg, gpgme_signature_t sig,
1709  gpgme_key_t key, struct State *s)
1710 {
1711  int msgwid;
1712 
1713  state_puts(s, msg);
1714  state_puts(s, " ");
1715  /* key is NULL when not present in the user's keyring */
1716  if (key)
1717  {
1718  bool aka = false;
1719  for (gpgme_user_id_t uids = key->uids; uids; uids = uids->next)
1720  {
1721  if (uids->revoked)
1722  continue;
1723  if (aka)
1724  {
1725  msgwid = mutt_strwidth(msg) - mutt_strwidth(_("aka: ")) + 1;
1726  if (msgwid < 0)
1727  msgwid = 0;
1728  for (int i = 0; i < msgwid; i++)
1729  state_puts(s, " ");
1730  state_puts(s, _("aka: "));
1731  }
1732  state_puts(s, uids->uid);
1733  state_puts(s, "\n");
1734 
1735  aka = true;
1736  }
1737  }
1738  else
1739  {
1740  if (sig->fpr)
1741  {
1742  state_puts(s, _("KeyID "));
1743  state_puts(s, sig->fpr);
1744  }
1745  else
1746  {
1747  /* L10N: You will see this message in place of "KeyID "
1748  if the S/MIME key has no ID. This is quite an error. */
1749  state_puts(s, _("no signature fingerprint available"));
1750  }
1751  state_puts(s, "\n");
1752  }
1753 
1754  /* timestamp is 0 when verification failed.
1755  * "Jan 1 1970" is not the created date. */
1756  if (sig->timestamp)
1757  {
1758  msgwid = mutt_strwidth(msg) - mutt_strwidth(_("created: ")) + 1;
1759  if (msgwid < 0)
1760  msgwid = 0;
1761  for (int i = 0; i < msgwid; i++)
1762  state_puts(s, " ");
1763  state_puts(s, _("created: "));
1764  print_time(sig->timestamp, s);
1765  state_puts(s, "\n");
1766  }
1767 }
1768 
1781 static int show_one_sig_status(gpgme_ctx_t ctx, int idx, struct State *s)
1782 {
1783  const char *fpr = NULL;
1784  gpgme_key_t key = NULL;
1785  bool anybad = false, anywarn = false;
1786  gpgme_signature_t sig = NULL;
1787  gpgme_error_t err = GPG_ERR_NO_ERROR;
1788 
1789  gpgme_verify_result_t result = gpgme_op_verify_result(ctx);
1790  if (result)
1791  {
1792  /* FIXME: this code should use a static variable and remember
1793  * the current position in the list of signatures, IMHO.
1794  * -moritz. */
1795  int i;
1796  for (i = 0, sig = result->signatures; sig && (i < idx); i++, sig = sig->next)
1797  ; // do nothing
1798 
1799  if (!sig)
1800  return -1; /* Signature not found. */
1801 
1802  if (signature_key)
1803  {
1804  gpgme_key_unref(signature_key);
1805  signature_key = NULL;
1806  }
1807 
1808  fpr = sig->fpr;
1809  const unsigned int sum = sig->summary;
1810 
1811  if (gpg_err_code(sig->status) != GPG_ERR_NO_ERROR)
1812  anybad = true;
1813 
1814  if (gpg_err_code(sig->status) != GPG_ERR_NO_PUBKEY)
1815  {
1816  err = gpgme_get_key(ctx, fpr, &key, 0); /* secret key? */
1817  if (err == 0)
1818  {
1819  if (!signature_key)
1820  signature_key = key;
1821  }
1822  else
1823  {
1824  key = NULL; /* Old GPGME versions did not set KEY to NULL on
1825  error. Do it here to avoid a double free. */
1826  }
1827  }
1828  else
1829  {
1830  /* pubkey not present */
1831  }
1832 
1833  if (!s || !s->fp_out || !(s->flags & MUTT_DISPLAY))
1834  ; /* No state information so no way to print anything. */
1835  else if (err != 0)
1836  {
1837  char buf[1024];
1838  snprintf(buf, sizeof(buf), _("Error getting key information for KeyID %s: %s\n"),
1839  fpr, gpgme_strerror(err));
1840  state_puts(s, buf);
1841  anybad = true;
1842  }
1843  else if ((sum & GPGME_SIGSUM_GREEN))
1844  {
1845  print_smime_keyinfo(_("Good signature from:"), sig, key, s);
1846  if (show_sig_summary(sum, ctx, key, idx, s, sig))
1847  anywarn = true;
1848  show_one_sig_validity(ctx, idx, s);
1849  }
1850  else if ((sum & GPGME_SIGSUM_RED))
1851  {
1852  print_smime_keyinfo(_("*BAD* signature from:"), sig, key, s);
1853  show_sig_summary(sum, ctx, key, idx, s, sig);
1854  }
1855  else if (!anybad && key && (key->protocol == GPGME_PROTOCOL_OpenPGP))
1856  { /* We can't decide (yellow) but this is a PGP key with a good
1857  signature, so we display what a PGP user expects: The name,
1858  fingerprint and the key validity (which is neither fully or
1859  ultimate). */
1860  print_smime_keyinfo(_("Good signature from:"), sig, key, s);
1861  show_one_sig_validity(ctx, idx, s);
1862  show_fingerprint(key, s);
1863  if (show_sig_summary(sum, ctx, key, idx, s, sig))
1864  anywarn = true;
1865  }
1866  else /* can't decide (yellow) */
1867  {
1868  print_smime_keyinfo(_("Problem signature from:"), sig, key, s);
1869  /* 0 indicates no expiration */
1870  if (sig->exp_timestamp)
1871  {
1872  /* L10N: This is trying to match the width of the
1873  "Problem signature from:" translation just above. */
1874  state_puts(s, _(" expires: "));
1875  print_time(sig->exp_timestamp, s);
1876  state_puts(s, "\n");
1877  }
1878  show_sig_summary(sum, ctx, key, idx, s, sig);
1879  anywarn = true;
1880  }
1881 
1882  if (key != signature_key)
1883  gpgme_key_unref(key);
1884  }
1885 
1886  return anybad ? 1 : anywarn ? 2 : 0;
1887 }
1888 
1902 static int verify_one(struct Body *sigbdy, struct State *s, const char *tempfile, bool is_smime)
1903 {
1904  int badsig = -1;
1905  int anywarn = 0;
1906  gpgme_ctx_t ctx = NULL;
1907  gpgme_data_t message = NULL;
1908 
1909  gpgme_data_t signature = file_to_data_object(s->fp_in, sigbdy->offset, sigbdy->length);
1910  if (!signature)
1911  return -1;
1912 
1913  /* We need to tell GPGME about the encoding because the backend can't
1914  * auto-detect plain base-64 encoding which is used by S/MIME. */
1915  if (is_smime)
1916  gpgme_data_set_encoding(signature, GPGME_DATA_ENCODING_BASE64);
1917 
1918  int err = gpgme_data_new_from_file(&message, tempfile, 1);
1919  if (err != 0)
1920  {
1921  gpgme_data_release(signature);
1922  mutt_error(_("error allocating data object: %s"), gpgme_strerror(err));
1923  return -1;
1924  }
1925  ctx = create_gpgme_context(is_smime);
1926 
1927  /* Note: We don't need a current time output because GPGME avoids
1928  * such an attack by separating the meta information from the data. */
1929  state_attach_puts(s, _("[-- Begin signature information --]\n"));
1930 
1931  err = gpgme_op_verify(ctx, signature, message, NULL);
1932  gpgme_data_release(message);
1933  gpgme_data_release(signature);
1934 
1935  redraw_if_needed(ctx);
1936  if (err != 0)
1937  {
1938  char buf[200];
1939 
1940  snprintf(buf, sizeof(buf) - 1, _("Error: verification failed: %s\n"),
1941  gpgme_strerror(err));
1942  state_puts(s, buf);
1943  }
1944  else
1945  { /* Verification succeeded, see what the result is. */
1946  gpgme_verify_result_t verify_result = NULL;
1947 
1948  if (signature_key)
1949  {
1950  gpgme_key_unref(signature_key);
1951  signature_key = NULL;
1952  }
1953 
1954  verify_result = gpgme_op_verify_result(ctx);
1955  if (verify_result && verify_result->signatures)
1956  {
1957  bool anybad = false;
1958  int res;
1959  for (int idx = 0; (res = show_one_sig_status(ctx, idx, s)) != -1; idx++)
1960  {
1961  if (res == 1)
1962  anybad = true;
1963  else if (res == 2)
1964  anywarn = 2;
1965  }
1966  if (!anybad)
1967  badsig = 0;
1968  }
1969  }
1970 
1971  if (badsig == 0)
1972  {
1973  gpgme_verify_result_t result = NULL;
1974  gpgme_sig_notation_t notation = NULL;
1975  gpgme_signature_t sig = NULL;
1976 
1977  result = gpgme_op_verify_result(ctx);
1978  if (result)
1979  {
1980  for (sig = result->signatures; sig; sig = sig->next)
1981  {
1982  int non_pka_notations = 0;
1983  for (notation = sig->notations; notation; notation = notation->next)
1984  if (!is_pka_notation(notation))
1985  non_pka_notations++;
1986 
1987  if (non_pka_notations)
1988  {
1989  char buf[128];
1990  snprintf(buf, sizeof(buf),
1991  _("*** Begin Notation (signature by: %s) ***\n"), sig->fpr);
1992  state_puts(s, buf);
1993  for (notation = sig->notations; notation; notation = notation->next)
1994  {
1995  if (is_pka_notation(notation))
1996  continue;
1997 
1998  if (notation->name)
1999  {
2000  state_puts(s, notation->name);
2001  state_puts(s, "=");
2002  }
2003  if (notation->value)
2004  {
2005  state_puts(s, notation->value);
2006  if (!(*notation->value && (notation->value[strlen(notation->value) - 1] == '\n')))
2007  state_puts(s, "\n");
2008  }
2009  }
2010  state_puts(s, _("*** End Notation ***\n"));
2011  }
2012  }
2013  }
2014  }
2015 
2016  gpgme_release(ctx);
2017 
2018  state_attach_puts(s, _("[-- End signature information --]\n\n"));
2019  mutt_debug(LL_DEBUG1, "returning %d\n", badsig);
2020 
2021  return badsig ? 1 : anywarn ? 2 : 0;
2022 }
2023 
2027 int pgp_gpgme_verify_one(struct Body *sigbdy, struct State *s, const char *tempfile)
2028 {
2029  return verify_one(sigbdy, s, tempfile, false);
2030 }
2031 
2035 int smime_gpgme_verify_one(struct Body *sigbdy, struct State *s, const char *tempfile)
2036 {
2037  return verify_one(sigbdy, s, tempfile, true);
2038 }
2039 
2053 static struct Body *decrypt_part(struct Body *a, struct State *s, FILE *fp_out,
2054  bool is_smime, int *r_is_signed)
2055 {
2056  if (!a || !s || !fp_out)
2057  return NULL;
2058 
2059  struct stat info;
2060  struct Body *tattach = NULL;
2061  int err = 0;
2062  gpgme_data_t ciphertext = NULL, plaintext = NULL;
2063  bool maybe_signed = false;
2064  bool anywarn = false;
2065  int sig_stat = 0;
2066 
2067  if (r_is_signed)
2068  *r_is_signed = 0;
2069 
2070  gpgme_ctx_t ctx = NULL;
2071 restart:
2072  ctx = create_gpgme_context(is_smime);
2073 
2074  if (a->length < 0)
2075  return NULL;
2076  /* Make a data object from the body, create context etc. */
2077  ciphertext = file_to_data_object(s->fp_in, a->offset, a->length);
2078  if (!ciphertext)
2079  goto cleanup;
2080  plaintext = create_gpgme_data();
2081 
2082  /* Do the decryption or the verification in case of the S/MIME hack. */
2083  if ((!is_smime) || maybe_signed)
2084  {
2085  if (!is_smime)
2086  err = gpgme_op_decrypt_verify(ctx, ciphertext, plaintext);
2087  else if (maybe_signed)
2088  err = gpgme_op_verify(ctx, ciphertext, NULL, plaintext);
2089 
2090  if (err == GPG_ERR_NO_ERROR)
2091  {
2092  /* Check whether signatures have been verified. */
2093  gpgme_verify_result_t verify_result = gpgme_op_verify_result(ctx);
2094  if (verify_result->signatures)
2095  sig_stat = 1;
2096  }
2097  }
2098  else
2099  err = gpgme_op_decrypt(ctx, ciphertext, plaintext);
2100  gpgme_data_release(ciphertext);
2101  ciphertext = NULL;
2102  if (err != 0)
2103  {
2104 #ifdef USE_AUTOCRYPT
2105  /* Abort right away and silently.
2106  * Autocrypt will retry on the normal keyring. */
2107  if (OptAutocryptGpgme)
2108  goto cleanup;
2109 #endif
2110  if (is_smime && !maybe_signed && (gpg_err_code(err) == GPG_ERR_NO_DATA))
2111  {
2112  /* Check whether this might be a signed message despite what the mime
2113  * header told us. Retry then. gpgsm returns the error information
2114  * "unsupported Algorithm '?'" but GPGME will not store this unknown
2115  * algorithm, thus we test that it has not been set. */
2116  gpgme_decrypt_result_t result;
2117 
2118  result = gpgme_op_decrypt_result(ctx);
2119  if (!result->unsupported_algorithm)
2120  {
2121  maybe_signed = true;
2122  gpgme_data_release(plaintext);
2123  plaintext = NULL;
2124  /* gpgsm ends the session after an error; restart it */
2125  gpgme_release(ctx);
2126  ctx = NULL;
2127  goto restart;
2128  }
2129  }
2130  redraw_if_needed(ctx);
2131  if ((s->flags & MUTT_DISPLAY))
2132  {
2133  char buf[200];
2134 
2135  snprintf(buf, sizeof(buf) - 1,
2136  _("[-- Error: decryption failed: %s --]\n\n"), gpgme_strerror(err));
2137  state_attach_puts(s, buf);
2138  }
2139  goto cleanup;
2140  }
2141  redraw_if_needed(ctx);
2142 
2143  /* Read the output from GPGME, and make sure to change CRLF to LF,
2144  * otherwise read_mime_header has a hard time parsing the message. */
2145  if (data_object_to_stream(plaintext, fp_out))
2146  {
2147  goto cleanup;
2148  }
2149  gpgme_data_release(plaintext);
2150  plaintext = NULL;
2151 
2152  if (sig_stat)
2153  {
2154  int res, idx;
2155  int anybad = 0;
2156 
2157  if (r_is_signed)
2158  *r_is_signed = -1; /* A signature exists. */
2159 
2160  if ((s->flags & MUTT_DISPLAY))
2161  {
2162  state_attach_puts(s, _("[-- Begin signature information --]\n"));
2163  }
2164  for (idx = 0; (res = show_one_sig_status(ctx, idx, s)) != -1; idx++)
2165  {
2166  if (res == 1)
2167  anybad = 1;
2168  else if (res == 2)
2169  anywarn = true;
2170  }
2171  if (!anybad && idx && r_is_signed && *r_is_signed)
2172  *r_is_signed = anywarn ? 2 : 1; /* Good signature. */
2173 
2174  if ((s->flags & MUTT_DISPLAY))
2175  {
2176  state_attach_puts(s, _("[-- End signature information --]\n\n"));
2177  }
2178  }
2179  gpgme_release(ctx);
2180  ctx = NULL;
2181 
2182  fflush(fp_out);
2183  rewind(fp_out);
2184  tattach = mutt_read_mime_header(fp_out, 0);
2185  if (tattach)
2186  {
2187  /* Need to set the length of this body part. */
2188  fstat(fileno(fp_out), &info);
2189  tattach->length = info.st_size - tattach->offset;
2190 
2191  tattach->warnsig = anywarn;
2192 
2193  /* See if we need to recurse on this MIME part. */
2194  mutt_parse_part(fp_out, tattach);
2195  }
2196 
2197 cleanup:
2198  gpgme_data_release(ciphertext);
2199  gpgme_data_release(plaintext);
2200  gpgme_release(ctx);
2201 
2202  return tattach;
2203 }
2204 
2208 int pgp_gpgme_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
2209 {
2210  struct State s = { 0 };
2211  struct Body *first_part = b;
2212  int is_signed = 0;
2213  bool need_decode = false;
2214  int saved_type = 0;
2215  LOFF_T saved_offset = 0;
2216  size_t saved_length = 0;
2217  FILE *fp_decoded = NULL;
2218  int rc = 0;
2219 
2220  first_part->goodsig = false;
2221  first_part->warnsig = false;
2222 
2224  {
2225  b = b->parts->next;
2226  /* Some clients improperly encode the octetstream part. */
2227  if (b->encoding != ENC_7BIT)
2228  need_decode = true;
2229  }
2231  {
2232  b = b->parts->next->next;
2233  need_decode = true;
2234  }
2235  else
2236  return -1;
2237 
2238  s.fp_in = fp_in;
2239 
2240  if (need_decode)
2241  {
2242  saved_type = b->type;
2243  saved_offset = b->offset;
2244  saved_length = b->length;
2245 
2246  fp_decoded = mutt_file_mkstemp();
2247  if (!fp_decoded)
2248  {
2249  mutt_perror(_("Can't create temporary file"));
2250  return -1;
2251  }
2252 
2253  fseeko(s.fp_in, b->offset, SEEK_SET);
2254  s.fp_out = fp_decoded;
2255 
2256  mutt_decode_attachment(b, &s);
2257 
2258  fflush(fp_decoded);
2259  b->length = ftello(fp_decoded);
2260  b->offset = 0;
2261  rewind(fp_decoded);
2262  s.fp_in = fp_decoded;
2263  s.fp_out = 0;
2264  }
2265 
2266  *fp_out = mutt_file_mkstemp();
2267  if (!*fp_out)
2268  {
2269  mutt_perror(_("Can't create temporary file"));
2270  rc = -1;
2271  goto bail;
2272  }
2273 
2274  *cur = decrypt_part(b, &s, *fp_out, false, &is_signed);
2275  if (*cur)
2276  {
2277  rewind(*fp_out);
2278  if (is_signed > 0)
2279  first_part->goodsig = true;
2280  }
2281  else
2282  {
2283  rc = -1;
2284  mutt_file_fclose(fp_out);
2285  }
2286 
2287 bail:
2288  if (need_decode)
2289  {
2290  b->type = saved_type;
2291  b->length = saved_length;
2292  b->offset = saved_offset;
2293  mutt_file_fclose(&fp_decoded);
2294  }
2295 
2296  return rc;
2297 }
2298 
2302 int smime_gpgme_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
2303 {
2304  struct State s = { 0 };
2305  int is_signed;
2306  LOFF_T saved_b_offset;
2307  size_t saved_b_length;
2308  int saved_b_type;
2309 
2311  return -1;
2312 
2313  if (b->parts)
2314  return -1;
2315 
2316  /* Decode the body - we need to pass binary CMS to the
2317  * backend. The backend allows for Base64 encoded data but it does
2318  * not allow for QP which I have seen in some messages. So better
2319  * do it here. */
2320  saved_b_type = b->type;
2321  saved_b_offset = b->offset;
2322  saved_b_length = b->length;
2323  s.fp_in = fp_in;
2324  fseeko(s.fp_in, b->offset, SEEK_SET);
2325  FILE *fp_tmp = mutt_file_mkstemp();
2326  if (!fp_tmp)
2327  {
2328  mutt_perror(_("Can't create temporary file"));
2329  return -1;
2330  }
2331 
2332  s.fp_out = fp_tmp;
2333  mutt_decode_attachment(b, &s);
2334  fflush(fp_tmp);
2335  b->length = ftello(s.fp_out);
2336  b->offset = 0;
2337  rewind(fp_tmp);
2338 
2339  memset(&s, 0, sizeof(s));
2340  s.fp_in = fp_tmp;
2341  s.fp_out = 0;
2342  *fp_out = mutt_file_mkstemp();
2343  if (!*fp_out)
2344  {
2345  mutt_perror(_("Can't create temporary file"));
2346  return -1;
2347  }
2348 
2349  *cur = decrypt_part(b, &s, *fp_out, true, &is_signed);
2350  if (*cur)
2351  (*cur)->goodsig = is_signed > 0;
2352  b->type = saved_b_type;
2353  b->length = saved_b_length;
2354  b->offset = saved_b_offset;
2355  mutt_file_fclose(&fp_tmp);
2356  rewind(*fp_out);
2357  if (*cur && !is_signed && !(*cur)->parts && mutt_is_application_smime(*cur))
2358  {
2359  /* Assume that this is a opaque signed s/mime message. This is an ugly way
2360  * of doing it but we have anyway a problem with arbitrary encoded S/MIME
2361  * messages: Only the outer part may be encrypted. The entire mime parsing
2362  * should be revamped, probably by keeping the temporary files so that we
2363  * don't need to decrypt them all the time. Inner parts of an encrypted
2364  * part can then point into this file and there won't ever be a need to
2365  * decrypt again. This needs a partial rewrite of the MIME engine. */
2366  struct Body *bb = *cur;
2367 
2368  saved_b_type = bb->type;
2369  saved_b_offset = bb->offset;
2370  saved_b_length = bb->length;
2371  memset(&s, 0, sizeof(s));
2372  s.fp_in = *fp_out;
2373  fseeko(s.fp_in, bb->offset, SEEK_SET);
2374  FILE *fp_tmp2 = mutt_file_mkstemp();
2375  if (!fp_tmp2)
2376  {
2377  mutt_perror(_("Can't create temporary file"));
2378  return -1;
2379  }
2380 
2381  s.fp_out = fp_tmp2;
2382  mutt_decode_attachment(bb, &s);
2383  fflush(fp_tmp2);
2384  bb->length = ftello(s.fp_out);
2385  bb->offset = 0;
2386  rewind(fp_tmp2);
2387  mutt_file_fclose(fp_out);
2388 
2389  memset(&s, 0, sizeof(s));
2390  s.fp_in = fp_tmp2;
2391  s.fp_out = 0;
2392  *fp_out = mutt_file_mkstemp();
2393  if (!*fp_out)
2394  {
2395  mutt_perror(_("Can't create temporary file"));
2396  return -1;
2397  }
2398 
2399  struct Body *b_tmp = decrypt_part(bb, &s, *fp_out, true, &is_signed);
2400  if (b_tmp)
2401  b_tmp->goodsig = is_signed > 0;
2402  bb->type = saved_b_type;
2403  bb->length = saved_b_length;
2404  bb->offset = saved_b_offset;
2405  mutt_file_fclose(&fp_tmp2);
2406  rewind(*fp_out);
2407  mutt_body_free(cur);
2408  *cur = b_tmp;
2409  }
2410  return *cur ? 0 : -1;
2411 }
2412 
2420 static int pgp_gpgme_extract_keys(gpgme_data_t keydata, FILE **fp)
2421 {
2422  /* Before GPGME 1.9.0 and gpg 2.1.14 there was no side-effect free
2423  * way to view key data in GPGME, so we import the key into a
2424  * temporary keyring if we detect an older system. */
2425  bool legacy_api;
2426  struct Buffer *tmpdir = NULL;
2427  gpgme_ctx_t tmpctx = NULL;
2428  gpgme_error_t err;
2429  gpgme_engine_info_t engineinfo = NULL;
2430  gpgme_key_t key = NULL;
2431  gpgme_user_id_t uid = NULL;
2432  gpgme_subkey_t subkey = NULL;
2433  const char *shortid = NULL;
2434  size_t len;
2435  char date[256];
2436  bool more;
2437  int rc = -1;
2438  time_t tt;
2439 
2440 #if (GPGME_VERSION_NUMBER >= 0x010900) /* GPGME >= 1.9.0 */
2441  legacy_api = !have_gpg_version("2.1.14");
2442 #else /* GPGME < 1.9.0 */
2443  legacy_api = true;
2444 #endif
2445 
2446  tmpctx = create_gpgme_context(false);
2447 
2448  if (legacy_api)
2449  {
2450  tmpdir = mutt_buffer_pool_get();
2451  const char *const c_tmpdir = cs_subset_path(NeoMutt->sub, "tmpdir");
2452  mutt_buffer_printf(tmpdir, "%s/neomutt-gpgme-XXXXXX", NONULL(c_tmpdir));
2453  if (!mkdtemp(tmpdir->data))
2454  {
2455  mutt_debug(LL_DEBUG1, "Error creating temporary GPGME home\n");
2456  goto err_ctx;
2457  }
2458 
2459  engineinfo = gpgme_ctx_get_engine_info(tmpctx);
2460  while (engineinfo && (engineinfo->protocol != GPGME_PROTOCOL_OpenPGP))
2461  engineinfo = engineinfo->next;
2462  if (!engineinfo)
2463  {
2464  mutt_debug(LL_DEBUG1, "Error finding GPGME PGP engine\n");
2465  goto err_tmpdir;
2466  }
2467 
2468  err = gpgme_ctx_set_engine_info(tmpctx, GPGME_PROTOCOL_OpenPGP, engineinfo->file_name,
2469  mutt_buffer_string(tmpdir));
2470  if (err != GPG_ERR_NO_ERROR)
2471  {
2472  mutt_debug(LL_DEBUG1, "Error setting GPGME context home\n");
2473  goto err_tmpdir;
2474  }
2475  }
2476 
2477  *fp = mutt_file_mkstemp();
2478  if (!*fp)
2479  {
2480  mutt_perror(_("Can't create temporary file"));
2481  goto err_tmpdir;
2482  }
2483 
2484 #if GPGME_VERSION_NUMBER >= 0x010900 /* 1.9.0 */
2485  if (!legacy_api)
2486  err = gpgme_op_keylist_from_data_start(tmpctx, keydata, 0);
2487  else
2488 #endif /* GPGME >= 1.9.0 */
2489  {
2490  err = gpgme_op_keylist_start(tmpctx, NULL, 0);
2491  }
2492  while (err == 0)
2493  {
2494  err = gpgme_op_keylist_next(tmpctx, &key);
2495  if (err != 0)
2496  break;
2497  uid = key->uids;
2498  subkey = key->subkeys;
2499  more = false;
2500  while (subkey)
2501  {
2502  shortid = subkey->keyid;
2503  len = mutt_str_len(subkey->keyid);
2504  if (len > 8)
2505  shortid += len - 8;
2506  tt = subkey->timestamp;
2507  mutt_date_localtime_format(date, sizeof(date), "%Y-%m-%d", tt);
2508 
2509  if (more)
2510  {
2511  fprintf(*fp, "sub %5.5s %u/%8s %s\n", gpgme_pubkey_algo_name(subkey->pubkey_algo),
2512  subkey->length, shortid, date);
2513  }
2514  else
2515  {
2516  fprintf(*fp, "pub %5.5s %u/%8s %s %s\n", gpgme_pubkey_algo_name(subkey->pubkey_algo),
2517  subkey->length, shortid, date, uid->uid);
2518  }
2519  subkey = subkey->next;
2520  more = true;
2521  }
2522  gpgme_key_unref(key);
2523  }
2524  if (gpg_err_code(err) != GPG_ERR_EOF)
2525  {
2526  mutt_debug(LL_DEBUG1, "Error listing keys\n");
2527  goto err_fp;
2528  }
2529 
2530  rc = 0;
2531 
2532 err_fp:
2533  if (rc)
2534  mutt_file_fclose(fp);
2535 err_tmpdir:
2536  if (legacy_api)
2538 err_ctx:
2539  gpgme_release(tmpctx);
2540 
2541  mutt_buffer_pool_release(&tmpdir);
2542 
2543  return rc;
2544 }
2545 
2557 static int line_compare(const char *a, size_t n, const char *b)
2558 {
2559  if (mutt_strn_equal(a, b, n))
2560  {
2561  /* at this point we know that 'b' is at least 'n' chars long */
2562  if ((b[n] == '\n') || ((b[n] == '\r') && (b[n + 1] == '\n')))
2563  return true;
2564  }
2565  return false;
2566 }
2567 
2575 static int pgp_check_traditional_one_body(FILE *fp, struct Body *b)
2576 {
2577  char buf[8192];
2578  bool rc = false;
2579 
2580  bool sgn = false;
2581  bool enc = false;
2582 
2583  if (b->type != TYPE_TEXT)
2584  return 0;
2585 
2586  struct Buffer *tempfile = mutt_buffer_pool_get();
2587  mutt_buffer_mktemp(tempfile);
2588  if (mutt_decode_save_attachment(fp, b, mutt_buffer_string(tempfile), 0,
2589  MUTT_SAVE_NO_FLAGS) != 0)
2590  {
2591  unlink(mutt_buffer_string(tempfile));
2592  goto cleanup;
2593  }
2594 
2595  FILE *fp_tmp = fopen(mutt_buffer_string(tempfile), "r");
2596  if (!fp_tmp)
2597  {
2598  unlink(mutt_buffer_string(tempfile));
2599  goto cleanup;
2600  }
2601 
2602  while (fgets(buf, sizeof(buf), fp_tmp))
2603  {
2604  size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
2605  if (plen != 0)
2606  {
2607  if (MESSAGE(buf + plen))
2608  {
2609  enc = true;
2610  break;
2611  }
2612  else if (SIGNED_MESSAGE(buf + plen))
2613  {
2614  sgn = true;
2615  break;
2616  }
2617  }
2618  }
2619  mutt_file_fclose(&fp_tmp);
2620  unlink(mutt_buffer_string(tempfile));
2621 
2622  if (!enc && !sgn)
2623  goto cleanup;
2624 
2625  /* fix the content type */
2626 
2627  mutt_param_set(&b->parameter, "format", "fixed");
2628  mutt_param_set(&b->parameter, "x-action", enc ? "pgp-encrypted" : "pgp-signed");
2629 
2630  rc = true;
2631 
2632 cleanup:
2633  mutt_buffer_pool_release(&tempfile);
2634  return rc;
2635 }
2636 
2640 bool pgp_gpgme_check_traditional(FILE *fp, struct Body *b, bool just_one)
2641 {
2642  bool rc = false;
2643  for (; b; b = b->next)
2644  {
2645  if (!just_one && is_multipart(b))
2646  rc = (pgp_gpgme_check_traditional(fp, b->parts, false) || rc);
2647  else if (b->type == TYPE_TEXT)
2648  {
2650  if (r)
2651  rc = (rc || r);
2652  else
2653  rc = (pgp_check_traditional_one_body(fp, b) || rc);
2654  }
2655 
2656  if (just_one)
2657  break;
2658  }
2659  return rc;
2660 }
2661 
2665 void pgp_gpgme_invoke_import(const char *fname)
2666 {
2667  gpgme_ctx_t ctx = create_gpgme_context(false);
2668  gpgme_data_t keydata = NULL;
2669  gpgme_import_result_t impres;
2670  gpgme_import_status_t st;
2671  bool any;
2672 
2673  FILE *fp_in = mutt_file_fopen(fname, "r");
2674  if (!fp_in)
2675  {
2676  mutt_perror(fname);
2677  goto leave;
2678  }
2679  /* Note that the stream, "fp_in", needs to be kept open while the keydata
2680  * is used. */
2681  gpgme_error_t err = gpgme_data_new_from_stream(&keydata, fp_in);
2682  if (err != GPG_ERR_NO_ERROR)
2683  {
2684  mutt_error(_("error allocating data object: %s"), gpgme_strerror(err));
2685  goto leave;
2686  }
2687 
2688  err = gpgme_op_import(ctx, keydata);
2689  if (err != 0)
2690  {
2691  mutt_error(_("Error importing key: %s"), gpgme_strerror(err));
2692  goto leave;
2693  }
2694 
2695  /* Print infos about the imported keys to stdout. */
2696  impres = gpgme_op_import_result(ctx);
2697  if (!impres)
2698  {
2699  fputs("oops: no import result returned\n", stdout);
2700  goto leave;
2701  }
2702 
2703  for (st = impres->imports; st; st = st->next)
2704  {
2705  if (st->result)
2706  continue;
2707  printf("key %s imported (", NONULL(st->fpr));
2708  /* Note that we use the singular even if it is possible that
2709  * several uids etc are new. This simply looks better. */
2710  any = false;
2711  if (st->status & GPGME_IMPORT_SECRET)
2712  {
2713  printf("secret parts");
2714  any = true;
2715  }
2716  if ((st->status & GPGME_IMPORT_NEW))
2717  {
2718  printf("%snew key", any ? ", " : "");
2719  any = true;
2720  }
2721  if ((st->status & GPGME_IMPORT_UID))
2722  {
2723  printf("%snew uid", any ? ", " : "");
2724  any = true;
2725  }
2726  if ((st->status & GPGME_IMPORT_SIG))
2727  {
2728  printf("%snew sig", any ? ", " : "");
2729  any = true;
2730  }
2731  if ((st->status & GPGME_IMPORT_SUBKEY))
2732  {
2733  printf("%snew subkey", any ? ", " : "");
2734  any = true;
2735  }
2736  printf("%s)\n", any ? "" : "not changed");
2737  /* Fixme: Should we lookup each imported key and print more infos? */
2738  }
2739  /* Now print keys which failed the import. Unfortunately in most
2740  * cases gpg will bail out early and not tell GPGME about. */
2741  /* FIXME: We could instead use the new GPGME_AUDITLOG_DIAG to show
2742  * the actual gpg diagnostics. But I fear that would clutter the
2743  * output too much. Maybe a dedicated prompt or option to do this
2744  * would be helpful. */
2745  for (st = impres->imports; st; st = st->next)
2746  {
2747  if (st->result == 0)
2748  continue;
2749  printf("key %s import failed: %s\n", NONULL(st->fpr), gpgme_strerror(st->result));
2750  }
2751  fflush(stdout);
2752 
2753 leave:
2754  gpgme_release(ctx);
2755  gpgme_data_release(keydata);
2756  mutt_file_fclose(&fp_in);
2757 }
2758 
2774 static void copy_clearsigned(gpgme_data_t data, struct State *s, char *charset)
2775 {
2776  char buf[8192];
2777  bool complete, armor_header;
2778  FILE *fp = NULL;
2779 
2780  char *fname = data_object_to_tempfile(data, &fp);
2781  if (!fname)
2782  {
2783  mutt_file_fclose(&fp);
2784  return;
2785  }
2786  unlink(fname);
2787  FREE(&fname);
2788 
2789  /* fromcode comes from the MIME Content-Type charset label. It might
2790  * be a wrong label, so we want the ability to do corrections via
2791  * charset-hooks. Therefore we set flags to MUTT_ICONV_HOOK_FROM. */
2792  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
2793  struct FgetConv *fc = mutt_ch_fgetconv_open(fp, charset, c_charset, MUTT_ICONV_HOOK_FROM);
2794 
2795  for (complete = true, armor_header = true;
2796  mutt_ch_fgetconvs(buf, sizeof(buf), fc); complete = (strchr(buf, '\n')))
2797  {
2798  if (!complete)
2799  {
2800  if (!armor_header)
2801  state_puts(s, buf);
2802  continue;
2803  }
2804 
2805  if (BEGIN_PGP_SIGNATURE(buf))
2806  break;
2807 
2808  if (armor_header)
2809  {
2810  if (buf[0] == '\n')
2811  armor_header = false;
2812  continue;
2813  }
2814 
2815  if (s->prefix)
2816  state_puts(s, s->prefix);
2817 
2818  if ((buf[0] == '-') && (buf[1] == ' '))
2819  state_puts(s, buf + 2);
2820  else
2821  state_puts(s, buf);
2822  }
2823 
2825  mutt_file_fclose(&fp);
2826 }
2827 
2831 int pgp_gpgme_application_handler(struct Body *m, struct State *s)
2832 {
2833  int needpass = -1;
2834  bool pgp_keyblock = false;
2835  bool clearsign = false;
2836  long bytes;
2837  LOFF_T last_pos;
2838  char buf[8192];
2839  FILE *fp_out = NULL;
2840 
2841  gpgme_error_t err = 0;
2842  gpgme_data_t armored_data = NULL;
2843 
2844  bool maybe_goodsig = true;
2845  bool have_any_sigs = false;
2846 
2847  char body_charset[256]; /* Only used for clearsigned messages. */
2848 
2849  mutt_debug(LL_DEBUG2, "Entering handler\n");
2850 
2851  /* For clearsigned messages we won't be able to get a character set
2852  * but we know that this may only be text thus we assume Latin-1 here. */
2853  if (!mutt_body_get_charset(m, body_charset, sizeof(body_charset)))
2854  mutt_str_copy(body_charset, "iso-8859-1", sizeof(body_charset));
2855 
2856  fseeko(s->fp_in, m->offset, SEEK_SET);
2857  last_pos = m->offset;
2858 
2859  for (bytes = m->length; bytes > 0;)
2860  {
2861  if (!fgets(buf, sizeof(buf), s->fp_in))
2862  break;
2863 
2864  LOFF_T offset = ftello(s->fp_in);
2865  bytes -= (offset - last_pos); /* don't rely on mutt_str_len(buf) */
2866  last_pos = offset;
2867 
2868  size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
2869  if (plen != 0)
2870  {
2871  clearsign = false;
2872 
2873  if (MESSAGE(buf + plen))
2874  needpass = 1;
2875  else if (SIGNED_MESSAGE(buf + plen))
2876  {
2877  clearsign = true;
2878  needpass = 0;
2879  }
2880  else if (PUBLIC_KEY_BLOCK(buf + plen))
2881  {
2882  needpass = 0;
2883  pgp_keyblock = true;
2884  }
2885  else
2886  {
2887  /* XXX we may wish to recode here */
2888  if (s->prefix)
2889  state_puts(s, s->prefix);
2890  state_puts(s, buf);
2891  continue;
2892  }
2893 
2894  have_any_sigs = (have_any_sigs || (clearsign && (s->flags & MUTT_VERIFY)));
2895 
2896  /* Copy PGP material to an data container */
2897  armored_data = file_to_data_object(s->fp_in, m->offset, m->length);
2898  /* Invoke PGP if needed */
2899  if (pgp_keyblock)
2900  {
2901  pgp_gpgme_extract_keys(armored_data, &fp_out);
2902  }
2903  else if (!clearsign || (s->flags & MUTT_VERIFY))
2904  {
2905  gpgme_data_t plaintext = create_gpgme_data();
2906  gpgme_ctx_t ctx = create_gpgme_context(false);
2907 
2908  if (clearsign)
2909  err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
2910  else
2911  {
2912  err = gpgme_op_decrypt_verify(ctx, armored_data, plaintext);
2913  if (gpg_err_code(err) == GPG_ERR_NO_DATA)
2914  {
2915  /* Decrypt verify can't handle signed only messages. */
2916  gpgme_data_seek(armored_data, 0, SEEK_SET);
2917  /* Must release plaintext so that we supply an uninitialized object. */
2918  gpgme_data_release(plaintext);
2919  plaintext = create_gpgme_data();
2920  err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
2921  }
2922  }
2923  redraw_if_needed(ctx);
2924 
2925  if (err != 0)
2926  {
2927  char errbuf[200];
2928 
2929  snprintf(errbuf, sizeof(errbuf) - 1,
2930  _("Error: decryption/verification failed: %s\n"), gpgme_strerror(err));
2931  state_puts(s, errbuf);
2932  }
2933  else
2934  {
2935  /* Decryption/Verification succeeded */
2936 
2937  mutt_message(_("PGP message successfully decrypted"));
2938 
2939  bool sig_stat = false;
2940  char *tmpfname = NULL;
2941 
2942  {
2943  /* Check whether signatures have been verified. */
2944  gpgme_verify_result_t verify_result = gpgme_op_verify_result(ctx);
2945  if (verify_result->signatures)
2946  sig_stat = true;
2947  }
2948 
2949  have_any_sigs = false;
2950  maybe_goodsig = false;
2951  if ((s->flags & MUTT_DISPLAY) && sig_stat)
2952  {
2953  int res, idx;
2954  bool anybad = false;
2955 
2956  state_attach_puts(s, _("[-- Begin signature information --]\n"));
2957  have_any_sigs = true;
2958  for (idx = 0; (res = show_one_sig_status(ctx, idx, s)) != -1; idx++)
2959  {
2960  if (res == 1)
2961  anybad = true;
2962  }
2963  if (!anybad && idx)
2964  maybe_goodsig = true;
2965 
2966  state_attach_puts(s, _("[-- End signature information --]\n\n"));
2967  }
2968 
2969  tmpfname = data_object_to_tempfile(plaintext, &fp_out);
2970  if (tmpfname)
2971  {
2972  unlink(tmpfname);
2973  FREE(&tmpfname);
2974  }
2975  else
2976  {
2977  mutt_file_fclose(&fp_out);
2978  state_puts(s, _("Error: copy data failed\n"));
2979  }
2980  }
2981  gpgme_data_release(plaintext);
2982  gpgme_release(ctx);
2983  }
2984 
2985  /* Now, copy cleartext to the screen. NOTE - we expect that PGP
2986  * outputs utf-8 cleartext. This may not always be true, but it
2987  * seems to be a reasonable guess. */
2988  if (s->flags & MUTT_DISPLAY)
2989  {
2990  if (needpass)
2991  state_attach_puts(s, _("[-- BEGIN PGP MESSAGE --]\n\n"));
2992  else if (pgp_keyblock)
2993  state_attach_puts(s, _("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"));
2994  else
2995  state_attach_puts(s, _("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"));
2996  }
2997 
2998  if (clearsign)
2999  {
3000  copy_clearsigned(armored_data, s, body_charset);
3001  }
3002  else if (fp_out)
3003  {
3004  int c;
3005  rewind(fp_out);
3006  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
3007  struct FgetConv *fc =
3008  mutt_ch_fgetconv_open(fp_out, "utf-8", c_charset, MUTT_ICONV_NO_FLAGS);
3009  while ((c = mutt_ch_fgetconv(fc)) != EOF)
3010  {
3011  state_putc(s, c);
3012  if ((c == '\n') && s->prefix)
3013  state_puts(s, s->prefix);
3014  }
3016  }
3017 
3018  if (s->flags & MUTT_DISPLAY)
3019  {
3020  state_putc(s, '\n');
3021  if (needpass)
3022  state_attach_puts(s, _("[-- END PGP MESSAGE --]\n"));
3023  else if (pgp_keyblock)
3024  state_attach_puts(s, _("[-- END PGP PUBLIC KEY BLOCK --]\n"));
3025  else
3026  state_attach_puts(s, _("[-- END PGP SIGNED MESSAGE --]\n"));
3027  }
3028 
3029  gpgme_data_release(armored_data);
3030  mutt_file_fclose(&fp_out);
3031  }
3032  else
3033  {
3034  /* A traditional PGP part may mix signed and unsigned content */
3035  /* XXX we may wish to recode here */
3036  if (s->prefix)
3037  state_puts(s, s->prefix);
3038  state_puts(s, buf);
3039  }
3040  }
3041 
3042  m->goodsig = (maybe_goodsig && have_any_sigs);
3043 
3044  if (needpass == -1)
3045  {
3047  s, _("[-- Error: could not find beginning of PGP message --]\n\n"));
3048  return 1;
3049  }
3050  mutt_debug(LL_DEBUG2, "Leaving handler\n");
3051 
3052  return err;
3053 }
3054 
3061 int pgp_gpgme_encrypted_handler(struct Body *a, struct State *s)
3062 {
3063  int is_signed;
3064  int rc = 0;
3065 
3066  mutt_debug(LL_DEBUG2, "Entering handler\n");
3067 
3068  FILE *fp_out = mutt_file_mkstemp();
3069  if (!fp_out)
3070  {
3071  mutt_perror(_("Can't create temporary file"));
3072  if (s->flags & MUTT_DISPLAY)
3073  {
3075  _("[-- Error: could not create temporary file --]\n"));
3076  }
3077  return -1;
3078  }
3079 
3080  struct Body *tattach = decrypt_part(a, s, fp_out, false, &is_signed);
3081  if (tattach)
3082  {
3083  tattach->goodsig = is_signed > 0;
3084 
3085  if (s->flags & MUTT_DISPLAY)
3086  {
3088  s, is_signed ?
3089  _("[-- The following data is PGP/MIME signed and encrypted "
3090  "--]\n\n") :
3091  _("[-- The following data is PGP/MIME encrypted --]\n\n"));
3092  mutt_protected_headers_handler(tattach, s);
3093  }
3094 
3095  /* Store any protected headers in the parent so they can be
3096  * accessed for index updates after the handler recursion is done.
3097  * This is done before the handler to prevent a nested encrypted
3098  * handler from freeing the headers. */
3100  a->mime_headers = tattach->mime_headers;
3101  tattach->mime_headers = NULL;
3102 
3103  {
3104  FILE *fp_save = s->fp_in;
3105  s->fp_in = fp_out;
3106  rc = mutt_body_handler(tattach, s);
3107  s->fp_in = fp_save;
3108  }
3109 
3110  /* Embedded multipart signed protected headers override the
3111  * encrypted headers. We need to do this after the handler so
3112  * they can be printed in the pager. */
3113  if (mutt_is_multipart_signed(tattach) && tattach->parts && tattach->parts->mime_headers)
3114  {
3116  a->mime_headers = tattach->parts->mime_headers;
3117  tattach->parts->mime_headers = NULL;
3118  }
3119 
3120  /* if a multipart/signed is the _only_ sub-part of a
3121  * multipart/encrypted, cache signature verification
3122  * status. */
3123  if (mutt_is_multipart_signed(tattach) && !tattach->next)
3124  a->goodsig |= tattach->goodsig;
3125 
3126  if (s->flags & MUTT_DISPLAY)
3127  {
3128  state_puts(s, "\n");
3130  s, is_signed ?
3131  _("[-- End of PGP/MIME signed and encrypted data --]\n") :
3132  _("[-- End of PGP/MIME encrypted data --]\n"));
3133  }
3134 
3135  mutt_body_free(&tattach);
3136  mutt_message(_("PGP message successfully decrypted"));
3137  }
3138  else
3139  {
3140 #ifdef USE_AUTOCRYPT
3141  if (!OptAutocryptGpgme)
3142 #endif
3143  {
3144  mutt_error(_("Could not decrypt PGP message"));
3145  }
3146  rc = -1;
3147  }
3148 
3149  mutt_file_fclose(&fp_out);
3150  mutt_debug(LL_DEBUG2, "Leaving handler\n");
3151 
3152  return rc;
3153 }
3154 
3158 int smime_gpgme_application_handler(struct Body *a, struct State *s)
3159 {
3160  int is_signed = 0;
3161  int rc = 0;
3162 
3163  mutt_debug(LL_DEBUG2, "Entering handler\n");
3164 
3165  /* clear out any mime headers before the handler, so they can't be spoofed. */
3167  a->warnsig = false;
3168  FILE *fp_out = mutt_file_mkstemp();
3169  if (!fp_out)
3170  {
3171  mutt_perror(_("Can't create temporary file"));
3172  if (s->flags & MUTT_DISPLAY)
3173  {
3175  _("[-- Error: could not create temporary file --]\n"));
3176  }
3177  return -1;
3178  }
3179 
3180  struct Body *tattach = decrypt_part(a, s, fp_out, true, &is_signed);
3181  if (tattach)
3182  {
3183  tattach->goodsig = is_signed > 0;
3184 
3185  if (s->flags & MUTT_DISPLAY)
3186  {
3188  s, is_signed ?
3189  _("[-- The following data is S/MIME signed --]\n\n") :
3190  _("[-- The following data is S/MIME encrypted --]\n\n"));
3191  mutt_protected_headers_handler(tattach, s);
3192  }
3193 
3194  /* Store any protected headers in the parent so they can be
3195  * accessed for index updates after the handler recursion is done.
3196  * This is done before the handler to prevent a nested encrypted
3197  * handler from freeing the headers. */
3199  a->mime_headers = tattach->mime_headers;
3200  tattach->mime_headers = NULL;
3201 
3202  {
3203  FILE *fp_save = s->fp_in;
3204  s->fp_in = fp_out;
3205  rc = mutt_body_handler(tattach, s);
3206  s->fp_in = fp_save;
3207  }
3208 
3209  /* Embedded multipart signed protected headers override the
3210  * encrypted headers. We need to do this after the handler so
3211  * they can be printed in the pager. */
3212  if (mutt_is_multipart_signed(tattach) && tattach->parts && tattach->parts->mime_headers)
3213  {
3215  a->mime_headers = tattach->parts->mime_headers;
3216  tattach->parts->mime_headers = NULL;
3217  }
3218 
3219  /* if a multipart/signed is the _only_ sub-part of a multipart/encrypted,
3220  * cache signature verification status. */
3221  if (mutt_is_multipart_signed(tattach) && !tattach->next)
3222  {
3223  a->goodsig = tattach->goodsig;
3224  if (!a->goodsig)
3225  a->warnsig = tattach->warnsig;
3226  }
3227  else if (tattach->goodsig)
3228  {
3229  a->goodsig = true;
3230  a->warnsig = tattach->warnsig;
3231  }
3232 
3233  if (s->flags & MUTT_DISPLAY)
3234  {
3235  state_puts(s, "\n");
3236  state_attach_puts(s, is_signed ?
3237  _("[-- End of S/MIME signed data --]\n") :
3238  _("[-- End of S/MIME encrypted data --]\n"));
3239  }
3240 
3241  mutt_body_free(&tattach);
3242  }
3243 
3244  mutt_file_fclose(&fp_out);
3245  mutt_debug(LL_DEBUG2, "Leaving handler\n");
3246 
3247  return rc;
3248 }
3249 
3256 unsigned int key_check_cap(gpgme_key_t key, enum KeyCap cap)
3257 {
3258  unsigned int ret = 0;
3259 
3260  switch (cap)
3261  {
3262  case KEY_CAP_CAN_ENCRYPT:
3263  ret = key->can_encrypt;
3264  if (ret == 0)
3265  {
3266  for (gpgme_subkey_t subkey = key->subkeys; subkey; subkey = subkey->next)
3267  {
3268  ret = subkey->can_encrypt;
3269  if (ret != 0)
3270  break;
3271  }
3272  }
3273  break;
3274  case KEY_CAP_CAN_SIGN:
3275  ret = key->can_sign;
3276  if (ret == 0)
3277  {
3278  for (gpgme_subkey_t subkey = key->subkeys; subkey; subkey = subkey->next)
3279  {
3280  ret = subkey->can_sign;
3281  if (ret != 0)
3282  break;
3283  }
3284  }
3285  break;
3286  case KEY_CAP_CAN_CERTIFY:
3287  ret = key->can_certify;
3288  if (ret == 0)
3289  {
3290  for (gpgme_subkey_t subkey = key->subkeys; subkey; subkey = subkey->next)
3291  {
3292  ret = subkey->can_certify;
3293  if (ret != 0)
3294  break;
3295  }
3296  }
3297  break;
3298  }
3299 
3300  return ret;
3301 }
3302 
3312 static char *list_to_pattern(struct ListHead *list)
3313 {
3314  char *pattern = NULL, *p = NULL;
3315  const char *s = NULL;
3316  size_t n;
3317 
3318  n = 0;
3319  struct ListNode *np = NULL;
3320  STAILQ_FOREACH(np, list, entries)
3321  {
3322  for (s = np->data; *s; s++)
3323  {
3324  if ((*s == '%') || (*s == '+'))
3325  n += 2;
3326  n++;
3327  }
3328  n++; /* delimiter or end of string */
3329  }
3330  n++; /* make sure to allocate at least one byte */
3331  p = mutt_mem_calloc(1, n);
3332  pattern = p;
3333  STAILQ_FOREACH(np, list, entries)
3334  {
3335  s = np->data;
3336  if (*s)
3337  {
3338  if (np != STAILQ_FIRST(list))
3339  *p++ = ' ';
3340  for (s = np->data; *s; s++)
3341  {
3342  if (*s == '%')
3343  {
3344  *p++ = '%';
3345  *p++ = '2';
3346  *p++ = '5';
3347  }
3348  else if (*s == '+')
3349  {
3350  *p++ = '%';
3351  *p++ = '2';
3352  *p++ = 'B';
3353  }
3354  else if (*s == ' ')
3355  *p++ = '+';
3356  else
3357  *p++ = *s;
3358  }
3359  }
3360  }
3361  *p = '\0';
3362  return pattern;
3363 }
3364 
3375 static struct CryptKeyInfo *get_candidates(struct ListHead *hints, SecurityFlags app, int secret)
3376 {
3377  struct CryptKeyInfo *db = NULL, *k = NULL, **kend = NULL;
3378  gpgme_error_t err;
3379  gpgme_ctx_t ctx = NULL;
3380  gpgme_key_t key = NULL;
3381  int idx;
3382  gpgme_user_id_t uid = NULL;
3383 
3384  char *pattern = list_to_pattern(hints);
3385  if (!pattern)
3386  return NULL;
3387 
3388  ctx = create_gpgme_context(0);
3389  db = NULL;
3390  kend = &db;
3391 
3392  if ((app & APPLICATION_PGP))
3393  {
3394  /* It's all a mess. That old GPGME expects different things depending on
3395  * the protocol. For gpg we don't need percent escaped pappert but simple
3396  * strings passed in an array to the keylist_ext_start function. */
3397  size_t n = 0;
3398  struct ListNode *np = NULL;
3399  STAILQ_FOREACH(np, hints, entries)
3400  {
3401  if (np->data && *np->data)
3402  n++;
3403  }
3404  if (n == 0)
3405  goto no_pgphints;
3406 
3407  char **patarr = mutt_mem_calloc(n + 1, sizeof(*patarr));
3408  n = 0;
3409  STAILQ_FOREACH(np, hints, entries)
3410  {
3411  if (np->data && *np->data)
3412  patarr[n++] = mutt_str_dup(np->data);
3413  }
3414  patarr[n] = NULL;
3415  err = gpgme_op_keylist_ext_start(ctx, (const char **) patarr, secret, 0);
3416  for (n = 0; patarr[n]; n++)
3417  FREE(&patarr[n]);
3418  FREE(&patarr);
3419  if (err != 0)
3420  {
3421  mutt_error(_("gpgme_op_keylist_start failed: %s"), gpgme_strerror(err));
3422  gpgme_release(ctx);
3423  FREE(&pattern);
3424  return NULL;
3425  }
3426 
3427  while ((err = gpgme_op_keylist_next(ctx, &key)) == 0)
3428  {
3429  KeyFlags flags = KEYFLAG_NO_FLAGS;
3430 
3432  flags |= KEYFLAG_CANENCRYPT;
3433  if (key_check_cap(key, KEY_CAP_CAN_SIGN))
3434  flags |= KEYFLAG_CANSIGN;
3435 
3436  if (key->revoked)
3437  flags |= KEYFLAG_REVOKED;
3438  if (key->expired)
3439  flags |= KEYFLAG_EXPIRED;
3440  if (key->disabled)
3441  flags |= KEYFLAG_DISABLED;
3442 
3443  for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3444  {
3445  k = mutt_mem_calloc(1, sizeof(*k));
3446  k->kobj = key;
3447  gpgme_key_ref(k->kobj);
3448  k->idx = idx;
3449  k->uid = uid->uid;
3450  k->flags = flags;
3451  if (uid->revoked)
3452  k->flags |= KEYFLAG_REVOKED;
3453  k->validity = uid->validity;
3454  *kend = k;
3455  kend = &k->next;
3456  }
3457  gpgme_key_unref(key);
3458  }
3459  if (gpg_err_code(err) != GPG_ERR_EOF)
3460  mutt_error(_("gpgme_op_keylist_next failed: %s"), gpgme_strerror(err));
3461  gpgme_op_keylist_end(ctx);
3462  no_pgphints:;
3463  }
3464 
3465  if ((app & APPLICATION_SMIME))
3466  {
3467  /* and now look for x509 certificates */
3468  gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS);
3469  err = gpgme_op_keylist_start(ctx, pattern, 0);
3470  if (err != 0)
3471  {
3472  mutt_error(_("gpgme_op_keylist_start failed: %s"), gpgme_strerror(err));
3473  gpgme_release(ctx);
3474  FREE(&pattern);
3475  return NULL;
3476  }
3477 
3478  while ((err = gpgme_op_keylist_next(ctx, &key)) == 0)
3479  {
3480  KeyFlags flags = KEYFLAG_ISX509;
3481 
3483  flags |= KEYFLAG_CANENCRYPT;
3484  if (key_check_cap(key, KEY_CAP_CAN_SIGN))
3485  flags |= KEYFLAG_CANSIGN;
3486 
3487  if (key->revoked)
3488  flags |= KEYFLAG_REVOKED;
3489  if (key->expired)
3490  flags |= KEYFLAG_EXPIRED;
3491  if (key->disabled)
3492  flags |= KEYFLAG_DISABLED;
3493 
3494  for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3495  {
3496  k = mutt_mem_calloc(1, sizeof(*k));
3497  k->kobj = key;
3498  gpgme_key_ref(k->kobj);
3499  k->idx = idx;
3500  k->uid = uid->uid;
3501  k->flags = flags;
3502  if (uid->revoked)
3503  k->flags |= KEYFLAG_REVOKED;
3504  k->validity = uid->validity;
3505  *kend = k;
3506  kend = &k->next;
3507  }
3508  gpgme_key_unref(key);
3509  }
3510  if (gpg_err_code(err) != GPG_ERR_EOF)
3511  mutt_error(_("gpgme_op_keylist_next failed: %s"), gpgme_strerror(err));
3512  gpgme_op_keylist_end(ctx);
3513  }
3514 
3515  gpgme_release(ctx);
3516  FREE(&pattern);
3517  return db;
3518 }
3519 
3528 static void crypt_add_string_to_hints(const char *str, struct ListHead *hints)
3529 {
3530  char *scratch = mutt_str_dup(str);
3531  if (!scratch)
3532  return;
3533 
3534  for (char *t = strtok(scratch, " ,.:\"()<>\n"); t;
3535  t = strtok(NULL, " ,.:\"()<>\n"))
3536  {
3537  if (strlen(t) > 3)
3539  }
3540 
3541  FREE(&scratch);
3542 }
3543 
3553 static struct CryptKeyInfo *crypt_getkeybyaddr(struct Address *a,
3554  KeyFlags abilities, unsigned int app,
3555  int *forced_valid, bool oppenc_mode)
3556 {
3557  struct ListHead hints = STAILQ_HEAD_INITIALIZER(hints);
3558 
3559  int multi = false;
3560  int this_key_has_strong = false;
3561  int this_key_has_addr_match = false;
3562  int match = false;
3563 
3564  struct CryptKeyInfo *keys = NULL, *k = NULL;
3565  struct CryptKeyInfo *the_strong_valid_key = NULL;
3566  struct CryptKeyInfo *a_valid_addrmatch_key = NULL;
3567  struct CryptKeyInfo *matches = NULL;
3568  struct CryptKeyInfo **matches_endp = &matches;
3569 
3570  *forced_valid = 0;
3571 
3572  if (a && a->mailbox)
3573  crypt_add_string_to_hints(a->mailbox, &hints);
3574  if (a && a->personal)
3575  crypt_add_string_to_hints(a->personal, &hints);
3576 
3577  if (!oppenc_mode)
3578  mutt_message(_("Looking for keys matching \"%s\"..."), a ? a->mailbox : "");
3579  keys = get_candidates(&hints, app, (abilities & KEYFLAG_CANSIGN));
3580 
3581  mutt_list_free(&hints);
3582 
3583  if (!keys)
3584  return NULL;
3585 
3586  mutt_debug(LL_DEBUG5, "looking for %s <%s>\n", a ? a->personal : "", a ? a->mailbox : "");
3587 
3588  for (k = keys; k; k = k->next)
3589  {
3590  mutt_debug(LL_DEBUG5, " looking at key: %s '%.15s'\n", crypt_keyid(k), k->uid);
3591 
3592  if (abilities && !(k->flags & abilities))
3593  {
3594  mutt_debug(LL_DEBUG2, " insufficient abilities: Has %x, want %x\n", k->flags, abilities);
3595  continue;
3596  }
3597 
3598  this_key_has_strong = false; /* strong and valid match */
3599  this_key_has_addr_match = false;
3600  match = false; /* any match */
3601 
3602  struct AddressList alist = TAILQ_HEAD_INITIALIZER(alist);
3603  mutt_addrlist_parse(&alist, k->uid);
3604  struct Address *ka = NULL;
3605  TAILQ_FOREACH(ka, &alist, entries)
3606  {
3607  int validity = crypt_id_matches_addr(a, ka, k);
3608 
3609  if (validity & CRYPT_KV_MATCH) /* something matches */
3610  {
3611  match = true;
3612 
3613  if ((validity & CRYPT_KV_VALID) && (validity & CRYPT_KV_ADDR))
3614  {
3615  if (validity & CRYPT_KV_STRONGID)
3616  {
3617  if (the_strong_valid_key && (the_strong_valid_key->kobj != k->kobj))
3618  multi = true;
3619  this_key_has_strong = true;
3620  }
3621  else
3622  this_key_has_addr_match = true;
3623  }
3624  }
3625  }
3626  mutt_addrlist_clear(&alist);
3627 
3628  if (match)
3629  {
3630  struct CryptKeyInfo *tmp = crypt_copy_key(k);
3631  *matches_endp = tmp;
3632  matches_endp = &tmp->next;
3633 
3634  if (this_key_has_strong)
3635  the_strong_valid_key = tmp;
3636  else if (this_key_has_addr_match)
3637  a_valid_addrmatch_key = tmp;
3638  }
3639  }
3640 
3641  crypt_key_free(&keys);
3642 
3643  if (matches)
3644  {
3645  if (oppenc_mode)
3646  {
3647  const bool c_crypt_opportunistic_encrypt_strong_keys = cs_subset_bool(
3648  NeoMutt->sub, "crypt_opportunistic_encrypt_strong_keys");
3649  if (the_strong_valid_key)
3650  k = crypt_copy_key(the_strong_valid_key);
3651  else if (a_valid_addrmatch_key && !c_crypt_opportunistic_encrypt_strong_keys)
3652  k = crypt_copy_key(a_valid_addrmatch_key);
3653  else
3654  k = NULL;
3655  }
3656  else if (the_strong_valid_key && !multi)
3657  {
3658  /* There was precisely one strong match on a valid ID.
3659  * Proceed without asking the user. */
3660  k = crypt_copy_key(the_strong_valid_key);
3661  }
3662  else
3663  {
3664  /* Else: Ask the user. */
3665  k = dlg_select_gpgme_key(matches, a, NULL, app, forced_valid);
3666  }
3667 
3668  crypt_key_free(&matches);
3669  }
3670  else
3671  k = NULL;
3672 
3673  return k;
3674 }
3675 
3684 static struct CryptKeyInfo *crypt_getkeybystr(const char *p, KeyFlags abilities,
3685  unsigned int app, int *forced_valid)
3686 {
3687  struct ListHead hints = STAILQ_HEAD_INITIALIZER(hints);
3688  struct CryptKeyInfo *matches = NULL;
3689  struct CryptKeyInfo **matches_endp = &matches;
3690  struct CryptKeyInfo *k = NULL;
3691  const char *ps = NULL, *pl = NULL, *phint = NULL;
3692 
3693  mutt_message(_("Looking for keys matching \"%s\"..."), p);
3694 
3695  *forced_valid = 0;
3696 
3697  const char *pfcopy = crypt_get_fingerprint_or_id(p, &phint, &pl, &ps);
3698  crypt_add_string_to_hints(phint, &hints);
3699  struct CryptKeyInfo *keys = get_candidates(&hints, app, (abilities & KEYFLAG_CANSIGN));
3700  mutt_list_free(&hints);
3701 
3702  if (!keys)
3703  {
3704  FREE(&pfcopy);
3705  return NULL;
3706  }
3707 
3708  for (k = keys; k; k = k->next)
3709  {
3710  if (abilities && !(k->flags & abilities))
3711  continue;
3712 
3713  mutt_debug(LL_DEBUG5, "matching \"%s\" against key %s, \"%s\": ", p,
3714  crypt_long_keyid(k), k->uid);
3715 
3716  if ((*p == '\0') || (pfcopy && mutt_istr_equal(pfcopy, crypt_fpr(k))) ||
3717  (pl && mutt_istr_equal(pl, crypt_long_keyid(k))) ||
3718  (ps && mutt_istr_equal(ps, crypt_short_keyid(k))) || mutt_istr_find(k->uid, p))
3719  {
3720  mutt_debug(LL_DEBUG5, "match\n");
3721 
3722  struct CryptKeyInfo *tmp = crypt_copy_key(k);
3723  *matches_endp = tmp;
3724  matches_endp = &tmp->next;
3725  }
3726  else
3727  {
3728  mutt_debug(LL_DEBUG5, "no match\n");
3729  }
3730  }
3731 
3732  FREE(&pfcopy);
3733  crypt_key_free(&keys);
3734 
3735  if (matches)
3736  {
3737  k = dlg_select_gpgme_key(matches, NULL, p, app, forced_valid);
3738  crypt_key_free(&matches);
3739  return k;
3740  }
3741 
3742  return NULL;
3743 }
3744 
3757 static struct CryptKeyInfo *crypt_ask_for_key(char *tag, char *whatfor, KeyFlags abilities,
3758  unsigned int app, int *forced_valid)
3759 {
3760  struct CryptKeyInfo *key = NULL;
3761  char resp[128];
3762  struct CryptCache *l = NULL;
3763  int dummy;
3764 
3765  if (!forced_valid)
3766  forced_valid = &dummy;
3767 
3768  mutt_clear_error();
3769 
3770  *forced_valid = 0;
3771  resp[0] = '\0';
3772  if (whatfor)
3773  {
3774  for (l = id_defaults; l; l = l->next)
3775  {
3776  if (mutt_istr_equal(whatfor, l->what))
3777  {
3778  mutt_str_copy(resp, l->dflt, sizeof(resp));
3779  break;
3780  }
3781  }
3782  }
3783 
3784  while (true)
3785  {
3786  resp[0] = '\0';
3787  if (mutt_get_field(tag, resp, sizeof(resp), MUTT_COMP_NO_FLAGS, false, NULL, NULL) != 0)
3788  {
3789  return NULL;
3790  }
3791 
3792  if (whatfor)
3793  {
3794  if (l)
3795  mutt_str_replace(&l->dflt, resp);
3796  else
3797  {
3798  l = mutt_mem_malloc(sizeof(struct CryptCache));
3799  l->next = id_defaults;
3800  id_defaults = l;
3801  l->what = mutt_str_dup(whatfor);
3802  l->dflt = mutt_str_dup(resp);
3803  }
3804  }
3805 
3806  key = crypt_getkeybystr(resp, abilities, app, forced_valid);
3807  if (key)
3808  return key;
3809 
3810  mutt_error(_("No matching keys found for \"%s\""), resp);
3811  }
3812  /* not reached */
3813 }
3814 
3826 static char *find_keys(struct AddressList *addrlist, unsigned int app, bool oppenc_mode)
3827 {
3828  struct ListHead crypt_hook_list = STAILQ_HEAD_INITIALIZER(crypt_hook_list);
3829  struct ListNode *crypt_hook = NULL;
3830  const char *keyid = NULL;
3831  char *keylist = NULL;
3832  size_t keylist_size = 0;
3833  size_t keylist_used = 0;
3834  struct Address *p = NULL;
3835  struct CryptKeyInfo *k_info = NULL;
3836  const char *fqdn = mutt_fqdn(true, NeoMutt->sub);
3837  char buf[1024];
3838  int forced_valid;
3839  bool key_selected;
3840  struct AddressList hookal = TAILQ_HEAD_INITIALIZER(hookal);
3841 
3842  struct Address *a = NULL;
3843  TAILQ_FOREACH(a, addrlist, entries)
3844  {
3845  key_selected = false;
3846  mutt_crypt_hook(&crypt_hook_list, a);
3847  crypt_hook = STAILQ_FIRST(&crypt_hook_list);
3848  do
3849  {
3850  p = a;
3851  forced_valid = 0;
3852  k_info = NULL;
3853 
3854  if (crypt_hook)
3855  {
3856  keyid = crypt_hook->data;
3857  enum QuadOption ans = MUTT_YES;
3858  const bool c_crypt_confirm_hook =
3859  cs_subset_bool(NeoMutt->sub, "crypt_confirm_hook");
3860  if (!oppenc_mode && c_crypt_confirm_hook)
3861  {
3862  snprintf(buf, sizeof(buf), _("Use keyID = \"%s\" for %s?"), keyid, p->mailbox);
3863  ans = mutt_yesorno(buf, MUTT_YES);
3864  }
3865  if (ans == MUTT_YES)
3866  {
3867  if (crypt_is_numerical_keyid(keyid))
3868  {
3869  if (mutt_strn_equal(keyid, "0x", 2))
3870  keyid += 2;
3871  goto bypass_selection; /* you don't see this. */
3872  }
3873 
3874  /* check for e-mail address */
3875  mutt_addrlist_clear(&hookal);
3876  if (strchr(keyid, '@') && (mutt_addrlist_parse(&hookal, keyid) != 0))
3877  {
3878  mutt_addrlist_qualify(&hookal, fqdn);
3879  p = TAILQ_FIRST(&hookal);
3880  }
3881  else if (!oppenc_mode)
3882  {
3883  k_info = crypt_getkeybystr(keyid, KEYFLAG_CANENCRYPT, app, &forced_valid);
3884  }
3885  }
3886  else if (ans == MUTT_NO)
3887  {
3888  if (key_selected || STAILQ_NEXT(crypt_hook, entries))
3889  {
3890  crypt_hook = STAILQ_NEXT(crypt_hook, entries);
3891  continue;
3892  }
3893  }
3894  else if (ans == MUTT_ABORT)
3895  {
3896  FREE(&keylist);
3897  mutt_addrlist_clear(&hookal);
3898  mutt_list_free(&crypt_hook_list);
3899  return NULL;
3900  }
3901  }
3902 
3903  if (!k_info)
3904  {
3905  k_info = crypt_getkeybyaddr(p, KEYFLAG_CANENCRYPT, app, &forced_valid, oppenc_mode);
3906  }
3907 
3908  if (!k_info && !oppenc_mode)
3909  {
3910  snprintf(buf, sizeof(buf), _("Enter keyID for %s: "), p->mailbox);
3911 
3912  k_info = crypt_ask_for_key(buf, p->mailbox, KEYFLAG_CANENCRYPT, app, &forced_valid);
3913  }
3914 
3915  if (!k_info)
3916  {
3917  FREE(&keylist);
3918  mutt_addrlist_clear(&hookal);
3919  mutt_list_free(&crypt_hook_list);
3920  return NULL;
3921  }
3922 
3923  keyid = crypt_fpr_or_lkeyid(k_info);
3924 
3925  bypass_selection:
3926  keylist_size += mutt_str_len(keyid) + 4 + 1;
3927  mutt_mem_realloc(&keylist, keylist_size);
3928  sprintf(keylist + keylist_used, "%s0x%s%s", keylist_used ? " " : "",
3929  keyid, forced_valid ? "!" : "");
3930  keylist_used = mutt_str_len(keylist);
3931 
3932  key_selected = true;
3933 
3934  crypt_key_free(&k_info);
3935  mutt_addrlist_clear(&hookal);
3936 
3937  if (crypt_hook)
3938  crypt_hook = STAILQ_NEXT(crypt_hook, entries);
3939 
3940  } while (crypt_hook);
3941 
3942  mutt_list_free(&crypt_hook_list);
3943  }
3944  return keylist;
3945 }
3946 
3950 char *pgp_gpgme_find_keys(struct AddressList *addrlist, bool oppenc_mode)
3951 {
3952  return find_keys(addrlist, APPLICATION_PGP, oppenc_mode);
3953 }
3954 
3958 char *smime_gpgme_find_keys(struct AddressList *addrlist, bool oppenc_mode)
3959 {
3960  return find_keys(addrlist, APPLICATION_SMIME, oppenc_mode);
3961 }
3962 
3963 #ifdef USE_AUTOCRYPT
3964 
3977 {
3978  int rc = -1, junk;
3979  gpgme_error_t err;
3980  gpgme_key_t key = NULL;
3981  gpgme_user_id_t uid = NULL;
3982  struct CryptKeyInfo *results = NULL, *k = NULL;
3983  struct CryptKeyInfo **kend = NULL;
3984  struct CryptKeyInfo *choice = NULL;
3985 
3986  gpgme_ctx_t ctx = create_gpgme_context(false);
3987 
3988  /* list all secret keys */
3989  if (gpgme_op_keylist_start(ctx, NULL, 1))
3990  goto cleanup;
3991 
3992  kend = &results;
3993 
3994  while (!(err = gpgme_op_keylist_next(ctx, &key)))
3995  {
3997 
3999  flags |= KEYFLAG_CANENCRYPT;
4000  if (key_check_cap(key, KEY_CAP_CAN_SIGN))
4001  flags |= KEYFLAG_CANSIGN;
4002 
4003  if (key->revoked)
4004  flags |= KEYFLAG_REVOKED;
4005  if (key->expired)
4006  flags |= KEYFLAG_EXPIRED;
4007  if (key->disabled)
4008  flags |= KEYFLAG_DISABLED;
4009 
4010  int idx;
4011  for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
4012  {
4013  k = mutt_mem_calloc(1, sizeof(*k));
4014  k->kobj = key;
4015  gpgme_key_ref(k->kobj);
4016  k->idx = idx;
4017  k->uid = uid->uid;
4018  k->flags = flags;
4019  if (uid->revoked)
4020  k->flags |= KEYFLAG_REVOKED;
4021  k->validity = uid->validity;
4022  *kend = k;
4023  kend = &k->next;
4024  }
4025  gpgme_key_unref(key);
4026  }
4027  if (gpg_err_code(err) != GPG_ERR_EOF)
4028  mutt_error(_("gpgme_op_keylist_next failed: %s"), gpgme_strerror(err));
4029  gpgme_op_keylist_end(ctx);
4030 
4031  if (!results)
4032  {
4033  /* L10N: mutt_gpgme_select_secret_key() tries to list all secret keys to choose
4034  from. This error is displayed if no results were found. */
4035  mutt_error(_("No secret keys found"));
4036  goto cleanup;
4037  }
4038 
4039  choice = dlg_select_gpgme_key(results, NULL, "*", APPLICATION_PGP, &junk);
4040  if (!(choice && choice->kobj && choice->kobj->subkeys && choice->kobj->subkeys->fpr))
4041  goto cleanup;
4042  mutt_buffer_strcpy(keyid, choice->kobj->subkeys->fpr);
4043 
4044  rc = 0;
4045 
4046 cleanup:
4047  crypt_key_free(&choice);
4048  crypt_key_free(&results);
4049  gpgme_release(ctx);
4050  return rc;
4051 }
4052 #endif
4053 
4058 {
4059 #ifdef HAVE_GPGME_OP_EXPORT_KEYS
4060  gpgme_ctx_t context = NULL;
4061  gpgme_key_t export_keys[2] = { 0 };
4062  gpgme_data_t keydata = NULL;
4063  gpgme_error_t err;
4064  struct Body *att = NULL;
4065  char buf[1024];
4066  struct stat sb;
4067 
4068  OptPgpCheckTrust = false;
4069 
4070  struct CryptKeyInfo *key = crypt_ask_for_key(_("Please enter the key ID: "), NULL,
4072  if (!key)
4073  goto bail;
4074  export_keys[0] = key->kobj;
4075  export_keys[1] = NULL;
4076 
4077  context = create_gpgme_context(false);
4078  gpgme_set_armor(context, 1);
4079  keydata = create_gpgme_data();
4080  err = gpgme_op_export_keys(context, export_keys, 0, keydata);
4081  if (err != GPG_ERR_NO_ERROR)
4082  {
4083  mutt_error(_("Error exporting key: %s"), gpgme_strerror(err));
4084  goto bail;
4085  }
4086 
4087  char *tempf = data_object_to_tempfile(keydata, NULL);
4088  if (!tempf)
4089  goto bail;
4090 
4091  att = mutt_body_new();
4092  /* tempf is a newly allocated string, so this is correct: */
4093  att->filename = tempf;
4094  att->unlink = true;
4095  att->use_disp = false;
4096  att->type = TYPE_APPLICATION;
4097  att->subtype = mutt_str_dup("pgp-keys");
4098  /* L10N: MIME description for exported (attached) keys.
4099  You can translate this entry to a non-ASCII string (it will be encoded),
4100  but it may be safer to keep it untranslated. */
4101  snprintf(buf, sizeof(buf), _("PGP Key 0x%s"), crypt_keyid(key));
4102  att->description = mutt_str_dup(buf);
4104 
4105  stat(tempf, &sb);
4106  att->length = sb.st_size;
4107 
4108 bail:
4109  crypt_key_free(&key);
4110  gpgme_data_release(keydata);
4111  gpgme_release(context);
4112 
4113  return att;
4114 #else
4115  mutt_error("gpgme_op_export_keys not supported");
4116  return NULL;
4117 #endif
4118 }
4119 
4123 static void init_common(void)
4124 {
4125  /* this initialization should only run one time, but it may be called by
4126  * either pgp_gpgme_init or smime_gpgme_init */
4127  static bool has_run = false;
4128  if (has_run)
4129  return;
4130 
4131  gpgme_check_version(NULL);
4132  gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
4133 #ifdef ENABLE_NLS
4134  gpgme_set_locale(NULL, LC_MESSAGES, setlocale(LC_MESSAGES, NULL));
4135 #endif
4136  has_run = true;
4137 }
4138 
4142 static void init_pgp(void)
4143 {
4144  if (gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP) != GPG_ERR_NO_ERROR)
4145  {
4146  mutt_error(_("GPGME: OpenPGP protocol not available"));
4147  }
4148 }
4149 
4153 static void init_smime(void)
4154 {
4155  if (gpgme_engine_check_version(GPGME_PROTOCOL_CMS) != GPG_ERR_NO_ERROR)
4156  {
4157  mutt_error(_("GPGME: CMS protocol not available"));
4158  }
4159 }
4160 
4164 void pgp_gpgme_init(void)
4165 {
4166  init_common();
4167  init_pgp();
4168 }
4169 
4174 {
4175  init_common();
4176  init_smime();
4177 }
4178 
4186 static SecurityFlags gpgme_send_menu(struct Mailbox *m, struct Email *e, bool is_smime)
4187 {
4188  struct CryptKeyInfo *p = NULL;
4189  const char *prompt = NULL;
4190  const char *letters = NULL;
4191  const char *choices = NULL;
4192  int choice;
4193 
4194  if (is_smime)
4196  else
4197  e->security |= APPLICATION_PGP;
4198 
4199  /* Opportunistic encrypt is controlling encryption.
4200  * NOTE: "Signing" and "Clearing" only adjust the sign bit, so we have different
4201  * letter choices for those.
4202  */
4203  const bool c_crypt_opportunistic_encrypt =
4204  cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt");
4205  if (c_crypt_opportunistic_encrypt && (e->security & SEC_OPPENCRYPT))
4206  {
4207  if (is_smime)
4208  {
4209  /* L10N: S/MIME options (opportunistic encryption is on) */
4210  prompt =
4211  _("S/MIME (s)ign, sign (a)s, (p)gp, (c)lear, or (o)ppenc mode off?");
4212  /* L10N: S/MIME options (opportunistic encryption is on) */
4213  letters = _("sapco");
4214  choices = "SapCo";
4215  }
4216  else
4217  {
4218  /* L10N: PGP options (opportunistic encryption is on) */
4219  prompt =
4220  _("PGP (s)ign, sign (a)s, s/(m)ime, (c)lear, or (o)ppenc mode off?");
4221  /* L10N: PGP options (opportunistic encryption is on) */
4222  letters = _("samco");
4223  choices = "SamCo";
4224  }
4225  }
4226  /* Opportunistic encryption option is set, but is toggled off for this message. */
4227  else if (c_crypt_opportunistic_encrypt)
4228  {
4229  if (is_smime)
4230  {
4231  /* L10N: S/MIME options (opportunistic encryption is off) */
4232  prompt = _("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp, (c)lear, "
4233  "or (o)ppenc mode?");
4234  /* L10N: S/MIME options (opportunistic encryption is off) */
4235  letters = _("esabpco");
4236  choices = "esabpcO";
4237  }
4238  else
4239  {
4240  /* L10N: PGP options (opportunistic encryption is off) */
4241  prompt = _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime, (c)lear, "
4242  "or (o)ppenc mode?");
4243  /* L10N: PGP options (opportunistic encryption is off) */
4244  letters = _("esabmco");
4245  choices = "esabmcO";
4246  }
4247  }
4248  /* Opportunistic encryption is unset */
4249  else
4250  {
4251  if (is_smime)
4252  {
4253  /* L10N: S/MIME options */
4254  prompt =
4255  _("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?");
4256  /* L10N: S/MIME options */
4257  letters = _("esabpc");
4258  choices = "esabpc";
4259  }
4260  else
4261  {
4262  /* L10N: PGP options */
4263  prompt =
4264  _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?");
4265  /* L10N: PGP options */
4266  letters = _("esabmc");
4267  choices = "esabmc";
4268  }
4269  }
4270 
4271  choice = mutt_multi_choice(prompt, letters);
4272  if (choice > 0)
4273  {
4274  switch (choices[choice - 1])
4275  {
4276  case 'a': /* sign (a)s */
4277  p = crypt_ask_for_key(_("Sign as: "), NULL, KEYFLAG_CANSIGN,
4278  is_smime ? APPLICATION_SMIME : APPLICATION_PGP, NULL);
4279  if (p)
4280  {
4281  char input_signas[128];
4282  snprintf(input_signas, sizeof(input_signas), "0x%s", crypt_fpr_or_lkeyid(p));
4283 
4284  if (is_smime)
4285  cs_subset_str_string_set(NeoMutt->sub, "smime_default_key", input_signas, NULL);
4286  else
4287  cs_subset_str_string_set(NeoMutt->sub, "pgp_sign_as", input_signas, NULL);
4288 
4289  crypt_key_free(&p);
4290 
4291  e->security |= SEC_SIGN;
4292  }
4293  break;
4294 
4295  case 'b': /* (b)oth */
4296  e->security |= (SEC_ENCRYPT | SEC_SIGN);
4297  break;
4298 
4299  case 'C':
4300  e->security &= ~SEC_SIGN;
4301  break;
4302 
4303  case 'c': /* (c)lear */
4304  e->security &= ~(SEC_ENCRYPT | SEC_SIGN);
4305  break;
4306 
4307  case 'e': /* (e)ncrypt */
4308  e->security |= SEC_ENCRYPT;
4309  e->security &= ~SEC_SIGN;
4310  break;
4311 
4312  case 'm': /* (p)gp or s/(m)ime */
4313  case 'p':
4314  is_smime = !is_smime;
4315  if (is_smime)
4316  {
4317  e->security &= ~APPLICATION_PGP;
4319  }
4320  else
4321  {
4322  e->security &= ~APPLICATION_SMIME;
4323  e->security |= APPLICATION_PGP;
4324  }
4326  break;
4327 
4328  case 'O': /* oppenc mode on */
4329  e->security |= SEC_OPPENCRYPT;
4331  break;
4332 
4333  case 'o': /* oppenc mode off */
4334  e->security &= ~SEC_OPPENCRYPT;
4335  break;
4336 
4337  case 'S': /* (s)ign in oppenc mode */
4338  e->security |= SEC_SIGN;
4339  break;
4340 
4341  case 's': /* (s)ign */
4342  e->security &= ~SEC_ENCRYPT;
4343  e->security |= SEC_SIGN;
4344  break;
4345  }
4346  }
4347 
4348  return e->security;
4349 }
4350 
4355 {
4356  return gpgme_send_menu(m, e, false);
4357 }
4358 
4363 {
4364  return gpgme_send_menu(m, e, true);
4365 }
4366 
4372 static bool verify_sender(struct Email *e)
4373 {
4374  struct Address *sender = NULL;
4375  bool rc = true;
4376 
4377  if (!TAILQ_EMPTY(&e->env->from))
4378  {
4380  sender = TAILQ_FIRST(&e->env->from);
4381  }
4382  else if (!TAILQ_EMPTY(&e->env->sender))
4383  {
4385  sender = TAILQ_FIRST(&e->env->sender);
4386  }
4387 
4388  if (sender)
4389  {
4390  if (signature_key)
4391  {
4392  gpgme_key_t key = signature_key;
4393  gpgme_user_id_t uid = NULL;
4394  int sender_length = strlen(sender->mailbox);
4395  for (uid = key->uids; uid && rc; uid = uid->next)
4396  {
4397  int uid_length = strlen(uid->email);
4398  if ((uid->email[0] == '<') && (uid->email[uid_length - 1] == '>') &&
4399  (uid_length == (sender_length + 2)))
4400  {
4401  const char *at_sign = strchr(uid->email + 1, '@');
4402  if (at_sign)
4403  {
4404  /* Assume address is 'mailbox@domainname'.
4405  * The mailbox part is case-sensitive,
4406  * the domainname is not. (RFC2821) */
4407  const char *tmp_email = uid->email + 1;
4408  const char *tmp_sender = sender->mailbox;
4409  /* length of mailbox part including '@' */
4410  int mailbox_length = at_sign - tmp_email + 1;
4411  int domainname_length = sender_length - mailbox_length;
4412  int mailbox_match, domainname_match;
4413 
4414  mailbox_match = mutt_strn_equal(tmp_email, tmp_sender, mailbox_length);
4415  tmp_email += mailbox_length;
4416  tmp_sender += mailbox_length;
4417  domainname_match =
4418  (strncasecmp(tmp_email, tmp_sender, domainname_length) == 0);
4419  if (mailbox_match && domainname_match)
4420  rc = false;
4421  }
4422  else
4423  {
4424  if (mutt_strn_equal(uid->email + 1, sender->mailbox, sender_length))
4425  rc = false;
4426  }
4427  }
4428  }
4429  }
4430  else
4431  mutt_any_key_to_continue(_("Failed to verify sender"));
4432  }
4433  else
4434  mutt_any_key_to_continue(_("Failed to figure out sender"));
4435 
4436  if (signature_key)
4437  {
4438  gpgme_key_unref(signature_key);
4439  signature_key = NULL;
4440  }
4441 
4442  return rc;
4443 }
4444 
4448 int smime_gpgme_verify_sender(struct Mailbox *m, struct Email *e, struct Message *msg)
4449 {
4450  return verify_sender(e);
4451 }
4452 
4456 void pgp_gpgme_set_sender(const char *sender)
4457 {
4458  mutt_debug(LL_DEBUG2, "setting to: %s\n", sender);
4459  FREE(&current_sender);
4460  current_sender = mutt_str_dup(sender);
4461 }
4462 
4467 const char *mutt_gpgme_print_version(void)
4468 {
4469  return GPGME_VERSION;
4470 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
Convenience wrapper for the gui headers.
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:1301
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1861
#define CRYPT_KV_STRONGID
Definition: crypt_gpgme.c:78
static void print_time(time_t t, struct State *s)
Print the date/time according to the locale.
Definition: crypt_gpgme.c:1242
int smime_gpgme_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
Implements CryptModuleSpecs::decrypt_mime() -.
Definition: crypt_gpgme.c:2302
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
static gpgme_data_t file_to_data_object(FILE *fp, long offset, size_t length)
Create GPGME data object from file.
Definition: crypt_gpgme.c:739
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
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
#define PKA_NOTATION_NAME
Definition: crypt_gpgme.c:96
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:300
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:691
The envelope/body of an email.
Definition: email.h:37
#define state_puts(STATE, STR)
Definition: state.h:55
static void show_one_sig_validity(gpgme_ctx_t ctx, int idx, struct State *s)
Show the validity of a key used for one signature.
Definition: crypt_gpgme.c:1665
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define TAILQ_FIRST(head)
Definition: queue.h:723
static char * data_object_to_tempfile(gpgme_data_t data, FILE **fp_ret)
Copy a data object to a temporary file.
Definition: crypt_gpgme.c:807
static void crypt_key_free(struct CryptKeyInfo **keylist)
Release all the keys in a list.
Definition: crypt_gpgme.c:462
void mutt_update_encoding(struct Body *a, struct ConfigSubset *sub)
Update the encoding type.
Definition: sendlib.c:904
static int data_object_to_stream(gpgme_data_t data, FILE *fp)
Write a GPGME data object to a file.
Definition: crypt_gpgme.c:760
Wrapper for PGP/SMIME calls to GPGME.
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
Structs that make up an email.
#define mutt_error(...)
Definition: logging.h:88
#define CRYPT_KV_ADDR
Definition: crypt_gpgme.c:76
#define is_multipart(body)
Definition: mime.h:82
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
static int line_compare(const char *a, size_t n, const char *b)
Compare two strings ignore line endings.
Definition: crypt_gpgme.c:2557
Autocrypt end-to-end encryption.
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:74
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
Convenience wrapper for the send headers.
struct Body * smime_gpgme_sign_message(struct Body *a, const struct AddressList *from)
Implements CryptModuleSpecs::sign_message() -.
Definition: crypt_gpgme.c:1387
#define SIGNED_MESSAGE(_y)
Definition: crypt_gpgme.c:100
7-bit text
Definition: mime.h:49
struct CryptKeyInfo * dlg_select_gpgme_key(struct CryptKeyInfo *keys, struct Address *p, const char *s, unsigned int app, int *forced_valid)
Get the user to select a key.
Definition: dlggpgme.c:1317
int pgp_gpgme_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
Implements CryptModuleSpecs::decrypt_mime() -.
Definition: crypt_gpgme.c:2208
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
int mutt_get_field(const char *field, char *buf, size_t buflen, CompletionFlags complete, bool multiple, char ***files, int *numfiles)
Ask the user for a string.
Definition: curs_lib.c:335
int mutt_write_mime_body(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:314
SecurityFlags pgp_gpgme_send_menu(struct Mailbox *m, struct Email *e)
Implements CryptModuleSpecs::send_menu() -.
Definition: crypt_gpgme.c:4354
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:75
void crypt_convert_to_7bit(struct Body *a)
Convert an email to 7bit encoding.
Definition: crypt.c:814
No flags set.
Definition: mutt_attach.h:57
size_t idx
Definition: mailbox.c:257
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
static struct CryptKeyInfo * crypt_getkeybystr(const char *p, KeyFlags abilities, unsigned int app, int *forced_valid)
Find a key by string.
Definition: crypt_gpgme.c:3684
#define PUBLIC_KEY_BLOCK(_y)
Definition: crypt_gpgme.c:101
const char * crypt_keyid(struct CryptKeyInfo *k)
Find the ID for the key.
Definition: crypt_gpgme.c:347
NeoMutt Logging.
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
int smime_gpgme_verify_one(struct Body *sigbdy, struct State *s, const char *tempfile)
Implements CryptModuleSpecs::verify_one() -.
Definition: crypt_gpgme.c:2035
bool crypt_is_numerical_keyid(const char *s)
Is this a numerical keyid.
Definition: crypt.c:1390
static void print_smime_keyinfo(const char *msg, gpgme_signature_t sig, gpgme_key_t key, struct State *s)
Print key info about an SMIME key.
Definition: crypt_gpgme.c:1708
static bool set_signer_from_address(gpgme_ctx_t ctx, const char *address, bool for_smime)
Try to set the context&#39;s signer from the address.
Definition: crypt_gpgme.c:988
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:623
int pgp_gpgme_encrypted_handler(struct Body *a, struct State *s)
Implements CryptModuleSpecs::encrypted_handler() -This handler is passed the application/octet-stream...
Definition: crypt_gpgme.c:3061
struct Body * smime_gpgme_build_smime_entity(struct Body *a, char *keylist)
Implements CryptModuleSpecs::smime_build_smime_entity() -.
Definition: crypt_gpgme.c:1441
int mutt_file_rmtree(const char *path)
Recursively remove a directory.
Definition: file.c:468
String manipulation buffer.
Definition: buffer.h:33
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
int mutt_is_valid_multipart_pgp_encrypted(struct Body *b)
Is this a valid multi-part encrypted message?
Definition: crypt.c:484
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
static char * encrypt_gpgme_object(gpgme_data_t plaintext, char *keylist, bool use_smime, bool combined_signed, const struct AddressList *from)
Encrypt the GPGPME data object.
Definition: crypt_gpgme.c:1114
#define _(a)
Definition: message.h:28
int smime_gpgme_application_handler(struct Body *a, struct State *s)
Implements CryptModuleSpecs::application_handler() -.
Definition: crypt_gpgme.c:3158
Key can be used for encryption.
Definition: crypt_gpgme.h:77
#define KEYFLAG_ISX509
Key is an X.509 key.
Definition: lib.h:126
struct Body * next
next attachment in the list
Definition: body.h:53
Internal cache for GPGME.
Definition: crypt_gpgme.c:85
An email address.
Definition: address.h:35
WHERE bool OptAutocryptGpgme
(pseudo) use Autocrypt context inside ncrypt/crypt_gpgme.c
Definition: options.h:33
Key can be used for signing.
Definition: crypt_gpgme.h:78
FILE * fp_out
File to write to.
Definition: state.h:47
char * mailbox
Mailbox and host address.
Definition: address.h:38
char * AutocryptSignAs
Autocrypt Key id to sign as.
Definition: config.c:35
static void recipient_set_free(gpgme_key_t **p_rset)
Free a set of recipients.
Definition: crypt_gpgme.c:896
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:71
static int show_sig_summary(unsigned long sum, gpgme_ctx_t ctx, gpgme_key_t key, int idx, struct State *s, gpgme_signature_t sig)
Show a signature summary.
Definition: crypt_gpgme.c:1485
static char * find_keys(struct AddressList *addrlist, unsigned int app, bool oppenc_mode)
Find keys of the recipients of the message.
Definition: crypt_gpgme.c:3826
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
struct CryptKeyInfo * next
Definition: crypt_gpgme.h:46
Shared constants/structs that are private to libconn.
static void init_smime(void)
Initialise the SMIME crypto backend.
Definition: crypt_gpgme.c:4153
char * pgp_gpgme_find_keys(struct AddressList *addrlist, bool oppenc_mode)
Implements CryptModuleSpecs::find_keys() -.
Definition: crypt_gpgme.c:3950
#define mutt_perror(...)
Definition: logging.h:89
Container for Accounts, Notifications.
Definition: neomutt.h:36
FILE * fp_in
File to read from.
Definition: state.h:46
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition: lib.h:125
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
#define CRYPT_KV_STRING
Definition: crypt_gpgme.c:77
The body of an email.
Definition: body.h:34
static struct CryptKeyInfo * crypt_getkeybyaddr(struct Address *a, KeyFlags abilities, unsigned int app, int *forced_valid, bool oppenc_mode)
Find a key by email address.
Definition: crypt_gpgme.c:3553
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
Convenience wrapper for the config headers.
static void crypt_add_string_to_hints(const char *str, struct ListHead *hints)
Split a string and add the parts to a List.
Definition: crypt_gpgme.c:3528
static int pgp_check_traditional_one_body(FILE *fp, struct Body *b)
Check one inline PGP body part.
Definition: crypt_gpgme.c:2575
Email Address Handling.
bool pgp_gpgme_check_traditional(FILE *fp, struct Body *b, bool just_one)
Implements CryptModuleSpecs::pgp_check_traditional() -.
Definition: crypt_gpgme.c:2640
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
Some miscellaneous functions.
int crypt_id_is_valid(struct CryptKeyInfo *key)
Is key ID valid.
Definition: crypt_gpgme.c:519
char * mutt_ch_fgetconvs(char *buf, size_t buflen, struct FgetConv *fc)
Convert a file&#39;s charset into a string buffer.
Definition: charset.c:974
A stored PGP key.
Definition: crypt_gpgme.h:44
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
static int crypt_id_matches_addr(struct Address *addr, struct Address *u_addr, struct CryptKeyInfo *key)
Does the key ID match the address.
Definition: crypt_gpgme.c:537
static void init_common(void)
Initialise code common to PGP and SMIME parts of GPGME.
Definition: crypt_gpgme.c:4123
#define MESSAGE(_y)
Definition: crypt_gpgme.c:99
int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: subset.c:408
Parse and execute user-defined hooks.
int idx
and the user ID at this index
Definition: crypt_gpgme.h:48
static void show_fingerprint(gpgme_key_t key, struct State *state)
Write a key&#39;s fingerprint.
Definition: crypt_gpgme.c:1610
static const char * crypt_fpr(struct CryptKeyInfo *k)
Get the hexstring fingerprint from a key.
Definition: crypt_gpgme.c:408
Many unsorted constants and some structs.
Log at debug level 2.
Definition: logging.h:41
static struct Body * decrypt_part(struct Body *a, struct State *s, FILE *fp_out, bool is_smime, int *r_is_signed)
Decrypt a PGP or SMIME message.
Definition: crypt_gpgme.c:2053
void crypt_opportunistic_encrypt(struct Mailbox *m, struct Email *e)
Can all recipients be determined.
Definition: crypt.c:1054
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:52
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 mutt_generate_boundary(struct ParameterList *pl)
Create a unique boundary id for a MIME part.
Definition: multipart.c:86
bool badsig
Bad cryptographic signature (needed to check encrypted s/mime-signatures)
Definition: body.h:78
void mutt_crypt_hook(struct ListHead *list, struct Address *addr)
Find crypto hooks for an Address.
Definition: hook.c:773
static void init_pgp(void)
Initialise the PGP crypto backend.
Definition: crypt_gpgme.c:4142
Content is attached.
Definition: mime.h:63
int mutt_write_mime_header(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition: header.c:764
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: body.c:131
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:420
static int get_micalg(gpgme_ctx_t ctx, int use_smime, char *buf, size_t buflen)
Find the "micalg" parameter from the last GPGME operation.
Definition: crypt_gpgme.c:1204
bool crypt_id_is_strong(struct CryptKeyInfo *key)
Is the key strong.
Definition: crypt_gpgme.c:484
Email Aliases.
char * smime_gpgme_find_keys(struct AddressList *addrlist, bool oppenc_mode)
Implements CryptModuleSpecs::find_keys() -.
Definition: crypt_gpgme.c:3958
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:112
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
User aborted the question (with Ctrl-G)
Definition: quad.h:37
Base-64 encoded text.
Definition: mime.h:52
#define KEYFLAG_EXPIRED
Key is expired.
Definition: lib.h:128
struct CryptKeyInfo * crypt_copy_key(struct CryptKeyInfo *key)
Return a copy of KEY.
Definition: crypt_gpgme.c:443
#define KEYFLAG_CANTUSE
Definition: lib.h:136
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
void pgp_gpgme_invoke_import(const char *fname)
Implements CryptModuleSpecs::pgp_invoke_import() -.
Definition: crypt_gpgme.c:2665
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
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 ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
int pgp_gpgme_application_handler(struct Body *m, struct State *s)
Implements CryptModuleSpecs::application_handler() -.
Definition: crypt_gpgme.c:2831
static gpgme_data_t body_to_data_object(struct Body *a, bool convert)
Create GPGME object from the mail body.
Definition: crypt_gpgme.c:667
int mutt_protected_headers_handler(struct Body *b, struct State *s)
Process a protected header - Implements handler_t.
Definition: crypt.c:1126
bool goodsig
Good cryptographic signature.
Definition: body.h:76
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:88
#define CRYPT_KV_MATCH
Definition: crypt_gpgme.c:79
const char * uid
and for convenience point to this user ID
Definition: crypt_gpgme.h:49
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
Signing/encryption multiplexor.
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
A local copy of an email.
Definition: mxapi.h:41
static SecurityFlags gpgme_send_menu(struct Mailbox *m, struct Email *e, bool is_smime)
Show the user the encryption/signing menu.
Definition: crypt_gpgme.c:4186
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
A mailbox.
Definition: mailbox.h:81
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:983
const char * crypt_fpr_or_lkeyid(struct CryptKeyInfo *k)
Find the fingerprint of a key.
Definition: crypt_gpgme.c:423
#define KEYFLAG_NO_FLAGS
No flags are set.
Definition: lib.h:123
static struct CryptCache * id_defaults
Definition: crypt_gpgme.c:92
struct Body * pgp_gpgme_sign_message(struct Body *a, const struct AddressList *from)
Implements CryptModuleSpecs::sign_message() -.
Definition: crypt_gpgme.c:1379
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:571
int mutt_gpgme_select_secret_key(struct Buffer *keyid)
Select a private Autocrypt key for a new account.
Definition: crypt_gpgme.c:3976
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
int mutt_decode_save_attachment(FILE *fp, struct Body *m, const char *path, int displaying, enum SaveAttach opt)
Decode, then save an attachment.
Definition: mutt_attach.c:1009
#define MUTT_VERIFY
Perform signature verification.
Definition: state.h:33
Type: &#39;text/*&#39;.
Definition: mime.h:38
uint16_t KeyFlags
Flags describing PGP/SMIME keys, e.g. KEYFLAG_CANSIGN.
Definition: lib.h:122
gpgme_key_t kobj
Definition: crypt_gpgme.h:47
char * data
Pointer to data.
Definition: buffer.h:35
Key can be used to certify.
Definition: crypt_gpgme.h:79
static struct CryptKeyInfo * crypt_ask_for_key(char *tag, char *whatfor, KeyFlags abilities, unsigned int app, int *forced_valid)
Ask the user for a key.
Definition: crypt_gpgme.c:3757
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
unsigned int key_check_cap(gpgme_key_t key, enum KeyCap cap)
Check the capabilities of a key.
Definition: crypt_gpgme.c:3256
struct Body * pgp_gpgme_encrypt_message(struct Body *a, char *keylist, bool sign, const struct AddressList *from)
Implements CryptModuleSpecs::pgp_encrypt_message() -.
Definition: crypt_gpgme.c:1395
static int pgp_gpgme_extract_keys(gpgme_data_t keydata, FILE **fp)
Write PGP keys to a file.
Definition: crypt_gpgme.c:2420
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define mutt_file_mkstemp()
Definition: file.h:108
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:521
static gpgme_key_t * create_recipient_set(const char *keylist, bool use_smime)
Create a GpgmeRecipientSet from a string of keys.
Definition: crypt_gpgme.c:923
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: question.c:49
static bool is_pka_notation(gpgme_sig_notation_t notation)
Is this the standard pka email address.
Definition: crypt_gpgme.c:110
Ask the user a question.
static char * list_to_pattern(struct ListHead *list)
Convert STailQ to GPGME-compatible pattern.
Definition: crypt_gpgme.c:3312
#define KEYFLAG_DISABLED
Key is marked disabled.
Definition: lib.h:130
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:48
Handling of email attachments.
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
char * description
content-description
Definition: body.h:40
static int set_signer(gpgme_ctx_t ctx, const struct AddressList *al, bool for_smime)
Make sure that the correct signer is set.
Definition: crypt_gpgme.c:1046
#define KEYFLAG_CANSIGN
Key is suitable for signing.
Definition: lib.h:124
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
static char * current_sender
Definition: crypt_gpgme.c:94
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:83
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:180
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
#define BEGIN_PGP_SIGNATURE(_y)
Definition: crypt_gpgme.c:102
static int verify_one(struct Body *sigbdy, struct State *s, const char *tempfile, bool is_smime)
Do the actual verification step.
Definition: crypt_gpgme.c:1902
#define SEC_SIGN
Email is signed.
Definition: lib.h:76
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:279
char * personal
Real name of address.
Definition: address.h:37
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:455
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:104
const char * mutt_gpgme_print_version(void)
Get version of GPGME.
Definition: crypt_gpgme.c:4467
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1678
SecurityFlags smime_gpgme_send_menu(struct Mailbox *m, struct Email *e)
Implements CryptModuleSpecs::send_menu() -.
Definition: crypt_gpgme.c:4362
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:650
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:689
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:1187
char * data
String.
Definition: list.h:36
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
static struct Body * sign_message(struct Body *a, const struct AddressList *from, bool use_smime)
Sign a message.
Definition: crypt_gpgme.c:1257
static const char * crypt_long_keyid(struct CryptKeyInfo *k)
Find the Long ID for the key.
Definition: crypt_gpgme.c:372
Log at debug level 1.
Definition: logging.h:40
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:749
No preferred disposition.
Definition: mime.h:65
char * mutt_str_lower(char *str)
Convert all characters in the string to lowercase.
Definition: string.c:504
void mutt_ch_fgetconv_close(struct FgetConv **fc)
Close an fgetconv handle.
Definition: charset.c:892
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
void smime_gpgme_init(void)
Implements CryptModuleSpecs::init() -.
Definition: crypt_gpgme.c:4173
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.h:50
static gpgme_data_t create_gpgme_data(void)
Create a new GPGME data object.
Definition: crypt_gpgme.c:611
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:565
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
static const char * crypt_short_keyid(struct CryptKeyInfo *k)
Get the short keyID for a key.
Definition: crypt_gpgme.c:389
#define mutt_message(...)
Definition: logging.h:87
static gpgme_error_t set_pka_sig_notation(gpgme_ctx_t ctx)
Set the signature notation.
Definition: crypt_gpgme.c:1094
#define FREE(x)
Definition: memory.h:40
#define CRYPT_KV_VALID
Definition: crypt_gpgme.c:75
static struct CryptKeyInfo * get_candidates(struct ListHead *hints, SecurityFlags app, int secret)
Get a list of keys which are candidates for the selection.
Definition: crypt_gpgme.c:3375
struct CryptCache * next
Definition: crypt_gpgme.c:89
Keep track when processing files.
Definition: state.h:44
gpgme_validity_t validity
uid validity (cached for convenience)
Definition: crypt_gpgme.h:51
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
struct AddressList sender
Email&#39;s sender.
Definition: envelope.h:61
KeyCap
PGP/SMIME Key Capabilities.
Definition: crypt_gpgme.h:75
void pgp_gpgme_init(void)
Implements CryptModuleSpecs::init() -.
Definition: crypt_gpgme.c:4164
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1604
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
Handling of global boolean variables.
#define state_putc(STATE, STR)
Definition: state.h:56
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define TAILQ_EMPTY(head)
Definition: queue.h:721
void pgp_gpgme_set_sender(const char *sender)
Implements CryptModuleSpecs::set_sender() -.
Definition: crypt_gpgme.c:4456
Log at debug level 5.
Definition: logging.h:44
Convenience wrapper for the library headers.
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
A List node for strings.
Definition: list.h:34
int smime_gpgme_verify_sender(struct Mailbox *m, struct Email *e, struct Message *msg)
Implements CryptModuleSpecs::smime_verify_sender() -.
Definition: crypt_gpgme.c:4448
static void redraw_if_needed(gpgme_ctx_t ctx)
accommodate for a redraw if needed
Definition: crypt_gpgme.c:119
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
Decide how to display email content.
Content is inline.
Definition: mime.h:62
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:137
static gpgme_key_t signature_key
Definition: crypt_gpgme.c:93
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
char * dflt
Definition: crypt_gpgme.c:88
#define STAILQ_FIRST(head)
Definition: queue.h:350
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file&#39;s character set.
Definition: charset.c:912
int pgp_gpgme_verify_one(struct Body *sigbdy, struct State *s, const char *tempfile)
Implements CryptModuleSpecs::verify_one() -.
Definition: crypt_gpgme.c:2027
#define KEYFLAG_REVOKED
Key is revoked.
Definition: lib.h:129
Cursor for converting a file&#39;s encoding.
Definition: charset.h:40
Type: &#39;application/*&#39;.
Definition: mime.h:33
struct FgetConv * mutt_ch_fgetconv_open(FILE *fp, const char *from, const char *to, uint8_t flags)
Prepare a file for charset conversion.
Definition: charset.c:862
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1286
static int show_one_sig_status(gpgme_ctx_t ctx, int idx, struct State *s)
Show information about one signature.
Definition: crypt_gpgme.c:1781
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
static void copy_clearsigned(gpgme_data_t data, struct State *s, char *charset)
Copy a clearsigned message.
Definition: crypt_gpgme.c:2774
char * what
Definition: crypt_gpgme.c:87
struct Body * pgp_gpgme_make_key_attachment(void)
Implements CryptModuleSpecs::pgp_make_key_attachment() -.
Definition: crypt_gpgme.c:4057
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
bool warnsig
Maybe good signature.
Definition: body.h:77
static bool verify_sender(struct Email *e)
Verify the sender of a message.
Definition: crypt_gpgme.c:4372