NeoMutt  2022-04-29-81-g9c5a59
Teaching an old dog new tricks
DOXYGEN
autocrypt.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <errno.h>
31 #include <stdbool.h>
32 #include <stdint.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <sys/stat.h>
36 #include "private.h"
37 #include "mutt/lib.h"
38 #include "address/lib.h"
39 #include "config/lib.h"
40 #include "email/lib.h"
41 #include "core/lib.h"
42 #include "gui/lib.h"
43 #include "lib.h"
44 #include "browser/lib.h"
45 #include "index/lib.h"
46 #include "ncrypt/lib.h"
47 #include "question/lib.h"
48 #include "send/lib.h"
49 #include "muttlib.h"
50 #include "mx.h"
51 #include "options.h"
52 
59 static int autocrypt_dir_init(bool can_create)
60 {
61  int rc = 0;
62  struct stat st = { 0 };
63 
64  const char *const c_autocrypt_dir = cs_subset_path(NeoMutt->sub, "autocrypt_dir");
65  if (stat(c_autocrypt_dir, &st) == 0)
66  return 0;
67 
68  if (!can_create)
69  return -1;
70 
71  struct Buffer *prompt = mutt_buffer_pool_get();
72  /* L10N: s is a directory. NeoMutt is looking for a directory it needs
73  for some reason (e.g. autocrypt, header cache, bcache), but it
74  doesn't exist. The prompt is asking whether to create the directory */
75  mutt_buffer_printf(prompt, _("%s does not exist. Create it?"), c_autocrypt_dir);
77  {
78  if (mutt_file_mkdir(c_autocrypt_dir, S_IRWXU) < 0)
79  {
80  /* L10N: mkdir() on the directory %s failed. The second %s is the
81  error message returned by libc */
82  mutt_error(_("Can't create %s: %s"), c_autocrypt_dir, strerror(errno));
83  rc = -1;
84  }
85  }
86 
87  mutt_buffer_pool_release(&prompt);
88  return rc;
89 }
90 
97 int mutt_autocrypt_init(bool can_create)
98 {
99  if (AutocryptDB)
100  return 0;
101 
102  const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
103  const char *const c_autocrypt_dir = cs_subset_path(NeoMutt->sub, "autocrypt_dir");
104  if (!c_autocrypt || !c_autocrypt_dir)
105  return -1;
106 
107  OptIgnoreMacroEvents = true;
108  /* The init process can display menus at various points
109  *(e.g. browser, pgp key selection). This allows the screen to be
110  * autocleared after each menu, so the subsequent prompts can be
111  * read. */
112  OptMenuPopClearScreen = true;
113 
114  if (autocrypt_dir_init(can_create))
115  goto bail;
116 
118  goto bail;
119 
120  if (mutt_autocrypt_db_init(can_create))
121  goto bail;
122 
123  OptIgnoreMacroEvents = false;
124  OptMenuPopClearScreen = false;
125 
126  return 0;
127 
128 bail:
129  OptIgnoreMacroEvents = false;
130  OptMenuPopClearScreen = false;
131  cs_subset_str_native_set(NeoMutt->sub, "autocrypt", false, NULL);
133  return -1;
134 }
135 
140 {
142 }
143 
154 {
155  struct Address *addr = NULL;
156  struct AutocryptAccount *account = NULL;
157  bool done = false;
158  int rc = -1;
159  bool prefer_encrypt = false;
160 
161  if (prompt)
162  {
163  /* L10N: The first time NeoMutt is started with $autocrypt set, it will
164  create $autocrypt_dir and then prompt to create an autocrypt account
165  with this message. */
166  if (mutt_yesorno(_("Create an initial autocrypt account?"), MUTT_YES) != MUTT_YES)
167  return 0;
168  }
169 
170  struct Buffer *keyid = mutt_buffer_pool_get();
171  struct Buffer *keydata = mutt_buffer_pool_get();
172 
173  const struct Address *c_from = cs_subset_address(NeoMutt->sub, "from");
174  if (c_from)
175  {
176  addr = mutt_addr_copy(c_from);
177  const char *const c_real_name = cs_subset_string(NeoMutt->sub, "real_name");
178  if (!addr->personal && c_real_name)
179  addr->personal = mutt_str_dup(c_real_name);
180  }
181 
182  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
183  mutt_addrlist_append(&al, addr);
184 
185  do
186  {
187  /* L10N: Autocrypt is asking for the email address to use for the
188  autocrypt account. This will generate a key and add a record
189  to the database for use in autocrypt operations. */
190  if (mutt_edit_address(&al, _("Autocrypt account address: "), false) != 0)
191  goto cleanup;
192 
193  addr = TAILQ_FIRST(&al);
194  if (!addr || !addr->mailbox || TAILQ_NEXT(addr, entries))
195  {
196  /* L10N: Autocrypt prompts for an account email address, and requires
197  a single address. This is shown if they entered something invalid,
198  nothing, or more than one address for some reason. */
199  mutt_error(_("Please enter a single email address"));
200  done = false;
201  }
202  else
203  done = true;
204  } while (!done);
205 
206  addr = TAILQ_FIRST(&al);
207  if (mutt_autocrypt_db_account_get(addr, &account) < 0)
208  goto cleanup;
209  if (account)
210  {
211  /* L10N: When creating an autocrypt account, this message will be displayed
212  if there is already an account in the database with the email address
213  they just entered. */
214  mutt_error(_("That email address already has an autocrypt account"));
215  goto cleanup;
216  }
217 
218  if (mutt_autocrypt_gpgme_select_or_create_key(addr, keyid, keydata))
219  goto cleanup;
220 
221  /* L10N: Autocrypt has a setting "prefer-encrypt".
222  When the recommendation algorithm returns "available" and BOTH sender and
223  recipient choose "prefer-encrypt", encryption will be automatically
224  enabled.
225  Otherwise the UI will show encryption is "available" but the user
226  will be required to enable encryption manually. */
227  if (mutt_yesorno(_("Prefer encryption?"), MUTT_NO) == MUTT_YES)
228  prefer_encrypt = true;
229 
231  mutt_buffer_string(keydata), prefer_encrypt))
232  {
233  goto cleanup;
234  }
235 
236  rc = 0;
237 
238 cleanup:
239  if (rc == 0)
240  {
241  /* L10N: Message displayed after an autocrypt account is successfully created. */
242  mutt_message(_("Autocrypt account creation succeeded"));
243  }
244  else
245  {
246  /* L10N: Error message displayed if creating an autocrypt account failed
247  or was aborted by the user. */
248  mutt_error(_("Autocrypt account creation aborted"));
249  }
250 
252  mutt_addrlist_clear(&al);
253  mutt_buffer_pool_release(&keyid);
254  mutt_buffer_pool_release(&keydata);
255  return rc;
256 }
257 
266 {
267  struct AutocryptHeader *valid_ac_hdr = NULL;
268  struct AutocryptPeer *peer = NULL;
269  struct AutocryptPeerHistory *peerhist = NULL;
270  struct Buffer *keyid = NULL;
271  bool update_db = false, insert_db = false, insert_db_history = false, import_gpg = false;
272  int rc = -1;
273 
274  const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
275  if (!c_autocrypt)
276  return 0;
277 
278  if (mutt_autocrypt_init(false))
279  return -1;
280 
281  if (!e || !e->body || !env)
282  return 0;
283 
284  /* 1.1 spec says to skip emails with more than one From header */
285  struct Address *from = TAILQ_FIRST(&env->from);
286  if (!from || TAILQ_NEXT(from, entries))
287  return 0;
288 
289  /* 1.1 spec also says to skip multipart/report emails */
290  if ((e->body->type == TYPE_MULTIPART) && mutt_istr_equal(e->body->subtype, "report"))
291  {
292  return 0;
293  }
294 
295  /* Ignore emails that appear to be more than a week in the future,
296  * since they can block all future updates during that time. */
297  if (e->date_sent > (mutt_date_epoch() + (7 * 24 * 60 * 60)))
298  return 0;
299 
300  for (struct AutocryptHeader *ac_hdr = env->autocrypt; ac_hdr; ac_hdr = ac_hdr->next)
301  {
302  if (ac_hdr->invalid)
303  continue;
304 
305  /* NOTE: this assumes the processing is occurring right after
306  * mutt_parse_rfc822_line() and the from ADDR is still in the same
307  * form (intl) as the autocrypt header addr field */
308  if (!mutt_istr_equal(from->mailbox, ac_hdr->addr))
309  continue;
310 
311  /* 1.1 spec says ignore all, if more than one valid header is found. */
312  if (valid_ac_hdr)
313  {
314  valid_ac_hdr = NULL;
315  break;
316  }
317  valid_ac_hdr = ac_hdr;
318  }
319 
320  if (mutt_autocrypt_db_peer_get(from, &peer) < 0)
321  goto cleanup;
322 
323  if (peer)
324  {
325  if (e->date_sent <= peer->autocrypt_timestamp)
326  {
327  rc = 0;
328  goto cleanup;
329  }
330 
331  if (e->date_sent > peer->last_seen)
332  {
333  update_db = true;
334  peer->last_seen = e->date_sent;
335  }
336 
337  if (valid_ac_hdr)
338  {
339  update_db = true;
340  peer->autocrypt_timestamp = e->date_sent;
341  peer->prefer_encrypt = valid_ac_hdr->prefer_encrypt;
342  if (!mutt_str_equal(peer->keydata, valid_ac_hdr->keydata))
343  {
344  import_gpg = true;
345  insert_db_history = true;
346  mutt_str_replace(&peer->keydata, valid_ac_hdr->keydata);
347  }
348  }
349  }
350  else if (valid_ac_hdr)
351  {
352  import_gpg = true;
353  insert_db = true;
354  insert_db_history = true;
355  }
356 
357  if (!(import_gpg || insert_db || update_db))
358  {
359  rc = 0;
360  goto cleanup;
361  }
362 
363  if (!peer)
364  {
366  peer->last_seen = e->date_sent;
367  peer->autocrypt_timestamp = e->date_sent;
368  peer->keydata = mutt_str_dup(valid_ac_hdr->keydata);
369  peer->prefer_encrypt = valid_ac_hdr->prefer_encrypt;
370  }
371 
372  if (import_gpg)
373  {
374  keyid = mutt_buffer_pool_get();
375  if (mutt_autocrypt_gpgme_import_key(peer->keydata, keyid))
376  goto cleanup;
377  mutt_str_replace(&peer->keyid, mutt_buffer_string(keyid));
378  }
379 
380  if (insert_db && mutt_autocrypt_db_peer_insert(from, peer))
381  goto cleanup;
382 
383  if (update_db && mutt_autocrypt_db_peer_update(peer))
384  goto cleanup;
385 
386  if (insert_db_history)
387  {
389  peerhist->email_msgid = mutt_str_dup(env->message_id);
390  peerhist->timestamp = e->date_sent;
391  peerhist->keydata = mutt_str_dup(peer->keydata);
392  if (mutt_autocrypt_db_peer_history_insert(from, peerhist))
393  goto cleanup;
394  }
395 
396  rc = 0;
397 
398 cleanup:
401  mutt_buffer_pool_release(&keyid);
402 
403  return rc;
404 }
405 
413 int mutt_autocrypt_process_gossip_header(struct Email *e, struct Envelope *prot_headers)
414 {
415  struct AutocryptPeer *peer = NULL;
416  struct AutocryptGossipHistory *gossip_hist = NULL;
417  struct Address *peer_addr = NULL;
418  struct Address ac_hdr_addr = { 0 };
419  bool update_db = false, insert_db = false, insert_db_history = false, import_gpg = false;
420  int rc = -1;
421 
422  const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
423  if (!c_autocrypt)
424  return 0;
425 
426  if (mutt_autocrypt_init(false))
427  return -1;
428 
429  if (!e || !e->env || !prot_headers)
430  return 0;
431 
432  struct Envelope *env = e->env;
433 
434  struct Address *from = TAILQ_FIRST(&env->from);
435  if (!from)
436  return 0;
437 
438  /* Ignore emails that appear to be more than a week in the future,
439  * since they can block all future updates during that time. */
440  if (e->date_sent > (mutt_date_epoch() + (7 * 24 * 60 * 60)))
441  return 0;
442 
443  struct Buffer *keyid = mutt_buffer_pool_get();
444 
445  struct AddressList recips = TAILQ_HEAD_INITIALIZER(recips);
446 
447  /* Normalize the recipient list for comparison */
448  mutt_addrlist_copy(&recips, &env->to, false);
449  mutt_addrlist_copy(&recips, &env->cc, false);
450  mutt_addrlist_copy(&recips, &env->reply_to, false);
452 
453  for (struct AutocryptHeader *ac_hdr = prot_headers->autocrypt_gossip; ac_hdr;
454  ac_hdr = ac_hdr->next)
455  {
456  if (ac_hdr->invalid)
457  continue;
458 
459  /* normalize for comparison against recipient list */
460  mutt_str_replace(&ac_hdr_addr.mailbox, ac_hdr->addr);
461  ac_hdr_addr.is_intl = true;
462  ac_hdr_addr.intl_checked = true;
463  mutt_autocrypt_db_normalize_addr(&ac_hdr_addr);
464 
465  /* Check to make sure the address is in the recipient list. */
466  TAILQ_FOREACH(peer_addr, &recips, entries)
467  {
468  if (mutt_str_equal(peer_addr->mailbox, ac_hdr_addr.mailbox))
469  break;
470  }
471 
472  if (!peer_addr)
473  continue;
474 
475  if (mutt_autocrypt_db_peer_get(peer_addr, &peer) < 0)
476  goto cleanup;
477 
478  if (peer)
479  {
480  if (e->date_sent <= peer->gossip_timestamp)
481  {
483  continue;
484  }
485 
486  update_db = true;
487  peer->gossip_timestamp = e->date_sent;
488  /* This is slightly different from the autocrypt 1.1 spec.
489  * Avoid setting an empty peer.gossip_keydata with a value that matches
490  * the current peer.keydata. */
491  if ((peer->gossip_keydata && !mutt_str_equal(peer->gossip_keydata, ac_hdr->keydata)) ||
492  (!peer->gossip_keydata && !mutt_str_equal(peer->keydata, ac_hdr->keydata)))
493  {
494  import_gpg = true;
495  insert_db_history = true;
496  mutt_str_replace(&peer->gossip_keydata, ac_hdr->keydata);
497  }
498  }
499  else
500  {
501  import_gpg = true;
502  insert_db = true;
503  insert_db_history = true;
504  }
505 
506  if (!peer)
507  {
509  peer->gossip_timestamp = e->date_sent;
510  peer->gossip_keydata = mutt_str_dup(ac_hdr->keydata);
511  }
512 
513  if (import_gpg)
514  {
516  goto cleanup;
518  }
519 
520  if (insert_db && mutt_autocrypt_db_peer_insert(peer_addr, peer))
521  goto cleanup;
522 
523  if (update_db && mutt_autocrypt_db_peer_update(peer))
524  goto cleanup;
525 
526  if (insert_db_history)
527  {
528  gossip_hist = mutt_autocrypt_db_gossip_history_new();
529  gossip_hist->sender_email_addr = mutt_str_dup(from->mailbox);
530  gossip_hist->email_msgid = mutt_str_dup(env->message_id);
531  gossip_hist->timestamp = e->date_sent;
532  gossip_hist->gossip_keydata = mutt_str_dup(peer->gossip_keydata);
533  if (mutt_autocrypt_db_gossip_history_insert(peer_addr, gossip_hist))
534  goto cleanup;
535  }
536 
539  mutt_buffer_reset(keyid);
540  update_db = false;
541  insert_db = false;
542  insert_db_history = false;
543  import_gpg = false;
544  }
545 
546  rc = 0;
547 
548 cleanup:
549  FREE(&ac_hdr_addr.mailbox);
550  mutt_addrlist_clear(&recips);
553  mutt_buffer_pool_release(&keyid);
554 
555  return rc;
556 }
557 
567 enum AutocryptRec mutt_autocrypt_ui_recommendation(const struct Email *e, char **keylist)
568 {
570  struct AutocryptAccount *account = NULL;
571  struct AutocryptPeer *peer = NULL;
572  struct Address *recip = NULL;
573  bool all_encrypt = true, has_discourage = false;
574  const char *matching_key = NULL;
575  struct AddressList recips = TAILQ_HEAD_INITIALIZER(recips);
576  struct Buffer *keylist_buf = NULL;
577 
578  const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
579  if (!c_autocrypt || mutt_autocrypt_init(false) || !e)
580  {
581  if (keylist)
582  {
583  /* L10N: Error displayed if the user tries to force sending an Autocrypt
584  email when the engine is not available. */
585  mutt_message(_("Autocrypt is not available"));
586  }
587  return AUTOCRYPT_REC_OFF;
588  }
589 
590  struct Address *from = TAILQ_FIRST(&e->env->from);
591  if (!from || TAILQ_NEXT(from, entries))
592  {
593  if (keylist)
594  mutt_message(_("Autocrypt is not available"));
595  return AUTOCRYPT_REC_OFF;
596  }
597 
598  if (e->security & APPLICATION_SMIME)
599  {
600  if (keylist)
601  mutt_message(_("Autocrypt is not available"));
602  return AUTOCRYPT_REC_OFF;
603  }
604 
605  if ((mutt_autocrypt_db_account_get(from, &account) <= 0) || !account->enabled)
606  {
607  if (keylist)
608  {
609  /* L10N: Error displayed if the user tries to force sending an Autocrypt
610  email when the account does not exist or is not enabled.
611  %s is the From email address used to look up the Autocrypt account.
612  */
613  mutt_message(_("Autocrypt is not enabled for %s"), NONULL(from->mailbox));
614  }
615  goto cleanup;
616  }
617 
618  keylist_buf = mutt_buffer_pool_get();
619  mutt_buffer_addstr(keylist_buf, account->keyid);
620 
621  mutt_addrlist_copy(&recips, &e->env->to, false);
622  mutt_addrlist_copy(&recips, &e->env->cc, false);
623  mutt_addrlist_copy(&recips, &e->env->bcc, false);
624 
625  rc = AUTOCRYPT_REC_NO;
626  if (TAILQ_EMPTY(&recips))
627  goto cleanup;
628 
629  TAILQ_FOREACH(recip, &recips, entries)
630  {
631  if (mutt_autocrypt_db_peer_get(recip, &peer) <= 0)
632  {
633  if (keylist)
634  {
635  /* L10N: s is an email address. Autocrypt is scanning for the keyids
636  to use to encrypt, but it can't find a valid keyid for this address.
637  The message is printed and they are returned to the compose menu. */
638  mutt_message(_("No (valid) autocrypt key found for %s"), recip->mailbox);
639  }
640  goto cleanup;
641  }
642 
644  {
645  matching_key = peer->keyid;
646 
647  if (!(peer->last_seen && peer->autocrypt_timestamp) ||
648  (peer->last_seen - peer->autocrypt_timestamp > (35 * 24 * 60 * 60)))
649  {
650  has_discourage = true;
651  all_encrypt = false;
652  }
653 
654  if (!account->prefer_encrypt || !peer->prefer_encrypt)
655  all_encrypt = false;
656  }
658  {
659  matching_key = peer->gossip_keyid;
660 
661  has_discourage = true;
662  all_encrypt = false;
663  }
664  else
665  {
666  if (keylist)
667  mutt_message(_("No (valid) autocrypt key found for %s"), recip->mailbox);
668  goto cleanup;
669  }
670 
671  if (!mutt_buffer_is_empty(keylist_buf))
672  mutt_buffer_addch(keylist_buf, ' ');
673  mutt_buffer_addstr(keylist_buf, matching_key);
674 
676  }
677 
678  if (all_encrypt)
679  rc = AUTOCRYPT_REC_YES;
680  else if (has_discourage)
682  else
684 
685  if (keylist)
686  mutt_str_replace(keylist, mutt_buffer_string(keylist_buf));
687 
688 cleanup:
690  mutt_addrlist_clear(&recips);
692  mutt_buffer_pool_release(&keylist_buf);
693  return rc;
694 }
695 
703 {
704  int rc = -1;
705  struct AutocryptAccount *account = NULL;
706 
707  const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
708  if (!c_autocrypt || mutt_autocrypt_init(false) || !e)
709  return -1;
710 
711  struct Address *from = TAILQ_FIRST(&e->env->from);
712  if (!from || TAILQ_NEXT(from, entries))
713  return -1;
714 
715  if (mutt_autocrypt_db_account_get(from, &account) <= 0)
716  goto cleanup;
717  if (!account->keyid)
718  goto cleanup;
719  if (!account->enabled)
720  goto cleanup;
721 
724 
725  rc = 0;
726 
727 cleanup:
729  return rc;
730 }
731 
739 static void write_autocrypt_header_line(FILE *fp, const char *addr,
740  bool prefer_encrypt, const char *keydata)
741 {
742  fprintf(fp, "addr=%s; ", addr);
743  if (prefer_encrypt)
744  fputs("prefer-encrypt=mutual; ", fp);
745  fputs("keydata=\n", fp);
746 
747  while (*keydata)
748  {
749  int count = 0;
750  fputs("\t", fp);
751  while (*keydata && count < 75)
752  {
753  fputc(*keydata, fp);
754  count++;
755  keydata++;
756  }
757  fputs("\n", fp);
758  }
759 }
760 
769 {
770  int rc = -1;
771  struct AutocryptAccount *account = NULL;
772 
773  const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
774  if (!c_autocrypt || mutt_autocrypt_init(false) || !env)
775  return -1;
776 
777  struct Address *from = TAILQ_FIRST(&env->from);
778  if (!from || TAILQ_NEXT(from, entries))
779  return -1;
780 
781  if (mutt_autocrypt_db_account_get(from, &account) <= 0)
782  goto cleanup;
783  if (!account->keydata)
784  goto cleanup;
785  if (!account->enabled)
786  goto cleanup;
787 
788  fputs("Autocrypt: ", fp);
790  account->keydata);
791 
792  rc = 0;
793 
794 cleanup:
796  return rc;
797 }
798 
807 {
808  const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
809  if (!c_autocrypt || mutt_autocrypt_init(false) || !env)
810  return -1;
811 
812  for (struct AutocryptHeader *gossip = env->autocrypt_gossip; gossip;
813  gossip = gossip->next)
814  {
815  fputs("Autocrypt-Gossip: ", fp);
816  write_autocrypt_header_line(fp, gossip->addr, 0, gossip->keydata);
817  }
818 
819  return 0;
820 }
821 
829 {
830  int rc = -1;
831  struct AutocryptPeer *peer = NULL;
832  struct AutocryptAccount *account = NULL;
833  struct Address *recip = NULL;
834 
835  const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
836  if (!c_autocrypt || mutt_autocrypt_init(false) || !e)
837  return -1;
838 
839  struct Envelope *mime_headers = e->body->mime_headers;
840  if (!mime_headers)
841  mime_headers = e->body->mime_headers = mutt_env_new();
843 
844  struct AddressList recips = TAILQ_HEAD_INITIALIZER(recips);
845 
846  mutt_addrlist_copy(&recips, &e->env->to, false);
847  mutt_addrlist_copy(&recips, &e->env->cc, false);
848 
849  TAILQ_FOREACH(recip, &recips, entries)
850  {
851  /* At this point, we just accept missing keys and include what we can. */
852  if (mutt_autocrypt_db_peer_get(recip, &peer) <= 0)
853  continue;
854 
855  const char *keydata = NULL;
857  keydata = peer->keydata;
859  keydata = peer->gossip_keydata;
860 
861  if (keydata)
862  {
863  struct AutocryptHeader *gossip = mutt_autocrypthdr_new();
864  gossip->addr = mutt_str_dup(peer->email_addr);
865  gossip->keydata = mutt_str_dup(keydata);
866  gossip->next = mime_headers->autocrypt_gossip;
867  mime_headers->autocrypt_gossip = gossip;
868  }
869 
871  }
872 
873  TAILQ_FOREACH(recip, &e->env->reply_to, entries)
874  {
875  const char *addr = NULL;
876  const char *keydata = NULL;
877  if (mutt_autocrypt_db_account_get(recip, &account) > 0)
878  {
879  addr = account->email_addr;
880  keydata = account->keydata;
881  }
882  else if (mutt_autocrypt_db_peer_get(recip, &peer) > 0)
883  {
884  addr = peer->email_addr;
886  keydata = peer->keydata;
888  keydata = peer->gossip_keydata;
889  }
890 
891  if (keydata)
892  {
893  struct AutocryptHeader *gossip = mutt_autocrypthdr_new();
894  gossip->addr = mutt_str_dup(addr);
895  gossip->keydata = mutt_str_dup(keydata);
896  gossip->next = mime_headers->autocrypt_gossip;
897  mime_headers->autocrypt_gossip = gossip;
898  }
901  }
902 
903  mutt_addrlist_clear(&recips);
906  return rc;
907 }
908 
920 {
921 #ifdef USE_HCACHE
922  const char *c_header_cache = cs_subset_path(NeoMutt->sub, "header_cache");
923  char *old_hdrcache = mutt_str_dup(c_header_cache);
924  c_header_cache = NULL;
925 #endif
926 
927  struct Buffer *folderbuf = mutt_buffer_pool_get();
928 
929  /* L10N: The first time autocrypt is enabled, NeoMutt will ask to scan
930  through one or more mailboxes for Autocrypt: headers. Those headers are
931  then captured in the database as peer records and used for encryption.
932  If this is answered yes, they will be prompted for a mailbox. */
933  enum QuadOption scan = mutt_yesorno(_("Scan a mailbox for autocrypt headers?"), MUTT_YES);
934  while (scan == MUTT_YES)
935  {
936  struct Mailbox *m_cur = get_current_mailbox();
937  // L10N: The prompt for a mailbox to scan for Autocrypt: headers
938  if ((!mutt_buffer_enter_fname(_("Scan mailbox"), folderbuf, true, m_cur,
939  false, NULL, NULL, MUTT_SEL_NO_FLAGS)) &&
940  (!mutt_buffer_is_empty(folderbuf)))
941  {
942  mutt_buffer_expand_path_regex(folderbuf, false);
943  struct Mailbox *m_ac = mx_path_resolve(mutt_buffer_string(folderbuf));
944  /* NOTE: I am purposely *not* executing folder hooks here,
945  * as they can do all sorts of things like push into the getch() buffer.
946  * Authentication should be in account-hooks. */
947  if (mx_mbox_open(m_ac, MUTT_READONLY))
948  {
949  mx_mbox_close(m_ac);
950  }
951  mutt_buffer_reset(folderbuf);
952  }
953 
954  /* L10N: This is the second prompt to see if the user would like
955  to scan more than one mailbox for Autocrypt headers.
956  I'm purposely being extra verbose; asking first then prompting
957  for a mailbox. This is because this is a one-time operation
958  and I don't want them to accidentally ctrl-g and abort it. */
959  scan = mutt_yesorno(_("Scan another mailbox for autocrypt headers?"), MUTT_YES);
960  }
961 
962 #ifdef USE_HCACHE
963  cs_subset_str_native_set(NeoMutt->sub, "header_cache", (intptr_t) old_hdrcache, NULL);
964  old_hdrcache = NULL;
965 #endif
966  mutt_buffer_pool_release(&folderbuf);
967 }
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:737
struct Address * mutt_addr_copy(const struct Address *addr)
Copy the real address.
Definition: address.c:716
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1490
Email Address Handling.
char * AutocryptSignAs
Autocrypt Key id to sign as.
Definition: config.c:35
char * AutocryptDefaultKey
Autocrypt default key id (used for postponing messages)
Definition: config.c:36
void mutt_autocrypt_db_normalize_addrlist(struct AddressList *al)
Normalise a list of Email Addresses.
Definition: db.c:176
int mutt_autocrypt_db_peer_insert(struct Address *addr, struct AutocryptPeer *peer)
Insert a peer into the Autocrypt database.
Definition: db.c:615
void mutt_autocrypt_db_close(void)
Close the Autocrypt SQLite database connection.
Definition: db.c:130
sqlite3 * AutocryptDB
Definition: db.c:52
int mutt_autocrypt_db_gossip_history_insert(struct Address *addr, struct AutocryptGossipHistory *gossip_hist)
Insert a gossip history into the Autocrypt database.
Definition: db.c:841
int mutt_autocrypt_db_account_get(struct Address *addr, struct AutocryptAccount **account)
Get Autocrypt Account data from the database.
Definition: db.c:263
int mutt_autocrypt_db_peer_get(struct Address *addr, struct AutocryptPeer **peer)
Get peer info from the Autocrypt database.
Definition: db.c:550
int mutt_autocrypt_db_peer_update(struct AutocryptPeer *peer)
Update the peer info in an Autocrypt database.
Definition: db.c:678
int mutt_autocrypt_db_account_insert(struct Address *addr, const char *keyid, const char *keydata, bool prefer_encrypt)
Insert an Account into the Autocrypt database.
Definition: db.c:322
void mutt_autocrypt_db_account_free(struct AutocryptAccount **ptr)
Free an AutocryptAccount.
Definition: db.c:244
void mutt_autocrypt_db_normalize_addr(struct Address *a)
Normalise an Email Address.
Definition: db.c:165
struct AutocryptGossipHistory * mutt_autocrypt_db_gossip_history_new(void)
Create a new AutocryptGossipHistory.
Definition: db.c:812
void mutt_autocrypt_db_peer_history_free(struct AutocryptPeerHistory **ptr)
Free an AutocryptPeerHistory.
Definition: db.c:743
void mutt_autocrypt_db_peer_free(struct AutocryptPeer **ptr)
Free an AutocryptPeer.
Definition: db.c:528
struct AutocryptPeer * mutt_autocrypt_db_peer_new(void)
Create a new AutocryptPeer.
Definition: db.c:519
void mutt_autocrypt_db_gossip_history_free(struct AutocryptGossipHistory **ptr)
Free an AutocryptGossipHistory.
Definition: db.c:821
int mutt_autocrypt_db_init(bool can_create)
Initialise the Autocrypt SQLite database.
Definition: db.c:79
struct AutocryptPeerHistory * mutt_autocrypt_db_peer_history_new(void)
Create a new AutocryptPeerHistory.
Definition: db.c:734
int mutt_autocrypt_db_peer_history_insert(struct Address *addr, struct AutocryptPeerHistory *peerhist)
Insert peer history into the Autocrypt database.
Definition: db.c:762
AutocryptRec
Recommendation.
Definition: lib.h:157
@ AUTOCRYPT_REC_DISCOURAGE
Prefer not to use Autocrypt.
Definition: lib.h:160
@ AUTOCRYPT_REC_NO
Do no use Autocrypt.
Definition: lib.h:159
@ AUTOCRYPT_REC_OFF
No recommendations.
Definition: lib.h:158
@ AUTOCRYPT_REC_AVAILABLE
Autocrypt is available.
Definition: lib.h:161
@ AUTOCRYPT_REC_YES
Autocrypt should be used.
Definition: lib.h:162
int mutt_autocrypt_process_autocrypt_header(struct Email *e, struct Envelope *env)
Parse an Autocrypt email header.
Definition: autocrypt.c:265
int mutt_autocrypt_generate_gossip_list(struct Email *e)
Create the gossip list headers.
Definition: autocrypt.c:828
static int autocrypt_dir_init(bool can_create)
Initialise an Autocrypt directory.
Definition: autocrypt.c:59
static void write_autocrypt_header_line(FILE *fp, const char *addr, bool prefer_encrypt, const char *keydata)
Write an Autocrypt header to a file.
Definition: autocrypt.c:739
void mutt_autocrypt_cleanup(void)
Shutdown Autocrypt.
Definition: autocrypt.c:139
int mutt_autocrypt_write_gossip_headers(struct Envelope *env, FILE *fp)
Write the Autocrypt gossip headers to a file.
Definition: autocrypt.c:806
enum AutocryptRec mutt_autocrypt_ui_recommendation(const struct Email *e, char **keylist)
Get the recommended action for an Email.
Definition: autocrypt.c:567
int mutt_autocrypt_account_init(bool prompt)
Create a new Autocrypt account.
Definition: autocrypt.c:153
int mutt_autocrypt_init(bool can_create)
Initialise Autocrypt.
Definition: autocrypt.c:97
int mutt_autocrypt_write_autocrypt_header(struct Envelope *env, FILE *fp)
Write the Autocrypt header to a file.
Definition: autocrypt.c:768
int mutt_autocrypt_set_sign_as_default_key(struct Email *e)
Set the Autocrypt default key for signing.
Definition: autocrypt.c:702
void mutt_autocrypt_scan_mailboxes(void)
Scan mailboxes for Autocrypt headers.
Definition: autocrypt.c:919
int mutt_autocrypt_process_gossip_header(struct Email *e, struct Envelope *prot_headers)
Parse an Autocrypt email gossip header.
Definition: autocrypt.c:413
Select a Mailbox from a list.
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: lib.h:55
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
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
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.
int mutt_buffer_enter_fname(const char *prompt, struct Buffer *fname, bool mailbox, struct Mailbox *m, bool multiple, char ***files, int *numfiles, SelectFileFlags flags)
Ask the user to select a file.
Definition: curs_lib.c:556
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:427
Structs that make up an email.
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:43
void mutt_autocrypthdr_free(struct AutocryptHeader **p)
Free an AutocryptHeader.
Definition: envelope.c:75
struct AutocryptHeader * mutt_autocrypthdr_new(void)
Create a new AutocryptHeader.
Definition: envelope.c:66
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:930
bool mutt_autocrypt_gpgme_is_valid_key(const char *keyid)
Is a key id valid?
Definition: gpgme.c:357
int mutt_autocrypt_gpgme_init(void)
Initialise GPGME.
Definition: gpgme.c:67
int mutt_autocrypt_gpgme_import_key(const char *keydata, struct Buffer *keyid)
Read a key from GPGME.
Definition: gpgme.c:316
int mutt_autocrypt_gpgme_select_or_create_key(struct Address *addr, struct Buffer *keyid, struct Buffer *keydata)
Ask the user to select or create an Autocrypt key.
Definition: gpgme.c:275
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
Convenience wrapper for the gui headers.
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
Definition: helpers.c:49
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
GUI manage the main index (list of emails)
struct Mailbox * get_current_mailbox(void)
Get the current Mailbox.
Definition: index.c:606
#define FREE(x)
Definition: memory.h:40
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:796
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
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
void mutt_buffer_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:134
Some miscellaneous functions.
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:304
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1677
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition: mx.c:615
API for mailboxes.
#define MUTT_READONLY
Open in read-only mode.
Definition: mxapi.h:64
API for encryption/signing of emails.
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:91
Handling of global boolean variables.
bool OptMenuPopClearScreen
(pseudo) clear the screen when popping the last menu
Definition: options.h:45
bool OptIgnoreMacroEvents
(pseudo) don't process macro/push/exec events while set
Definition: options.h:43
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_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
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
#define TAILQ_FIRST(head)
Definition: queue.h:723
#define TAILQ_NEXT(elm, field)
Definition: queue.h:832
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
#define TAILQ_EMPTY(head)
Definition: queue.h:721
Convenience wrapper for the send headers.
int mutt_edit_address(struct AddressList *al, const char *field, bool expand_aliases)
Edit an email address.
Definition: send.c:177
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
bool intl_checked
Checked for IDN?
Definition: address.h:41
char * mailbox
Mailbox and host address.
Definition: address.h:38
bool is_intl
International Domain Name.
Definition: address.h:40
char * personal
Real name of address.
Definition: address.h:37
Autocrypt account.
Definition: lib.h:106
char * email_addr
Email address.
Definition: lib.h:107
char * keydata
PGP Key data.
Definition: lib.h:109
char * keyid
PGP Key id.
Definition: lib.h:108
bool enabled
Is this account enabled.
Definition: lib.h:111
bool prefer_encrypt
false = nopref, true = mutual
Definition: lib.h:110
Autocrypt gossip history.
Definition: lib.h:145
char * email_msgid
Sender's email's message id.
Definition: lib.h:148
char * sender_email_addr
Sender's email address.
Definition: lib.h:147
char * gossip_keydata
Gossip Key data.
Definition: lib.h:150
sqlite3_int64 timestamp
Timestamp of sender's email.
Definition: lib.h:149
Parse Autocrypt header info.
Definition: envelope.h:44
struct AutocryptHeader * next
Linked list.
Definition: envelope.h:49
char * keydata
PGP Key data.
Definition: envelope.h:46
bool prefer_encrypt
User prefers encryption.
Definition: envelope.h:47
char * addr
Email address.
Definition: envelope.h:45
Autocrypt peer history.
Definition: lib.h:134
char * email_msgid
Message id of the email.
Definition: lib.h:136
char * keydata
PGP Key data.
Definition: lib.h:138
sqlite3_int64 timestamp
Timestamp of email.
Definition: lib.h:137
Autocrypt peer.
Definition: lib.h:118
sqlite3_int64 autocrypt_timestamp
When the email was sent.
Definition: lib.h:121
char * gossip_keydata
Gossip Key data.
Definition: lib.h:127
char * keyid
PGP Key id.
Definition: lib.h:122
char * gossip_keyid
Gossip Key id.
Definition: lib.h:126
char * keydata
PGP Key data.
Definition: lib.h:123
char * email_addr
Email address.
Definition: lib.h:119
sqlite3_int64 last_seen
When was the peer last seen.
Definition: lib.h:120
bool prefer_encrypt
false = nopref, true = mutual
Definition: lib.h:124
sqlite3_int64 gossip_timestamp
Timestamp of Gossip header.
Definition: lib.h:125
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:75
char * subtype
content-type subtype
Definition: body.h:60
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
String manipulation buffer.
Definition: buffer.h:34
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 Body * body
List of MIME parts.
Definition: email.h:67
time_t date_sent
Time when the message was sent (UTC)
Definition: email.h:58
The header of an Email.
Definition: envelope.h:57
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
struct AddressList reply_to
Email's 'reply-to'.
Definition: envelope.h:64
char * message_id
Message ID.
Definition: envelope.h:73
struct AutocryptHeader * autocrypt_gossip
Autocrypt Gossip header.
Definition: envelope.h:90
struct AddressList cc
Email's 'Cc' list.
Definition: envelope.h:61
struct AutocryptHeader * autocrypt
Autocrypt header.
Definition: envelope.h:89
struct AddressList bcc
Email's 'Bcc' list.
Definition: envelope.h:62
struct AddressList from
Email's 'From' list.
Definition: envelope.h:59
A mailbox.
Definition: mailbox.h:79
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:305