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