mutt stable branch with some hacks
at jcs 868 lines 24 kB view raw
1/* 2 * Copyright (C) 2019 Kevin J. McCarthy <kevin@8t8.us> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19#if HAVE_CONFIG_H 20# include "config.h" 21#endif 22 23#include "mutt.h" 24#include "mutt_curses.h" 25#include "mutt_crypt.h" 26#include "mime.h" 27#include "mutt_idna.h" 28#include "mailbox.h" 29#include "autocrypt.h" 30#include "autocrypt_private.h" 31 32#ifdef HAVE_SYS_TIME_H 33#include <sys/time.h> 34#endif 35#include <errno.h> 36 37static int autocrypt_dir_init (int can_create) 38{ 39 int rv = 0; 40 struct stat sb; 41 BUFFER *prompt = NULL; 42 43 if (!stat (AutocryptDir, &sb)) 44 return 0; 45 46 if (!can_create) 47 return -1; 48 49 prompt = mutt_buffer_pool_get (); 50 /* L10N: 51 %s is a directory. Mutt is looking for a directory it needs 52 for some reason (e.g. autocrypt, header cache, bcache), but it 53 doesn't exist. The prompt is asking whether to create the directory 54 */ 55 mutt_buffer_printf (prompt, _("%s does not exist. Create it?"), AutocryptDir); 56 if (mutt_yesorno (mutt_b2s (prompt), MUTT_YES) == MUTT_YES) 57 { 58 if (mutt_mkdir (AutocryptDir, 0700) < 0) 59 { 60 /* L10N: 61 mkdir() on the directory %s failed. The second %s is the 62 error message returned by libc 63 */ 64 mutt_error ( _("Can't create %s: %s."), AutocryptDir, strerror (errno)); 65 mutt_sleep (0); 66 rv = -1; 67 } 68 } 69 70 mutt_buffer_pool_release (&prompt); 71 return rv; 72} 73 74int mutt_autocrypt_init (int can_create) 75{ 76 if (AutocryptDB) 77 return 0; 78 79 if (!option (OPTAUTOCRYPT) || !AutocryptDir) 80 return -1; 81 82 set_option (OPTIGNOREMACROEVENTS); 83 /* The init process can display menus at various points 84 * (e.g. browser, pgp key selection). This allows the screen to be 85 * autocleared after each menu, so the subsequent prompts can be 86 * read. */ 87 set_option (OPTMENUPOPCLEARSCREEN); 88 89 if (autocrypt_dir_init (can_create)) 90 goto bail; 91 92 if (mutt_autocrypt_gpgme_init ()) 93 goto bail; 94 95 if (mutt_autocrypt_db_init (can_create)) 96 goto bail; 97 98 unset_option (OPTIGNOREMACROEVENTS); 99 unset_option (OPTMENUPOPCLEARSCREEN); 100 101 return 0; 102 103bail: 104 unset_option (OPTIGNOREMACROEVENTS); 105 unset_option (OPTMENUPOPCLEARSCREEN); 106 unset_option (OPTAUTOCRYPT); 107 mutt_autocrypt_db_close (); 108 return -1; 109} 110 111void mutt_autocrypt_cleanup (void) 112{ 113 mutt_autocrypt_db_close (); 114} 115 116/* Creates a brand new account. 117 * This is used the first time autocrypt is initialized, and 118 * in the account menu. */ 119int mutt_autocrypt_account_init (int prompt) 120{ 121 ADDRESS *addr = NULL; 122 BUFFER *keyid = NULL, *keydata = NULL; 123 AUTOCRYPT_ACCOUNT *account = NULL; 124 int done = 0, rv = -1, prefer_encrypt = 0; 125 126 if (prompt) 127 { 128 /* L10N: 129 The first time mutt is started with $autocrypt set, it will 130 create $autocrypt_dir and then prompt to create an autocrypt 131 account with this message. 132 */ 133 if (mutt_yesorno (_("Create an initial autocrypt account?"), 134 MUTT_YES) != MUTT_YES) 135 return 0; 136 } 137 138 keyid = mutt_buffer_pool_get (); 139 keydata = mutt_buffer_pool_get (); 140 141 if (From) 142 { 143 addr = rfc822_cpy_adr_real (From); 144 if (!addr->personal && Realname) 145 addr->personal = safe_strdup (Realname); 146 } 147 148 do 149 { 150 /* L10N: 151 Autocrypt is asking for the email address to use for the 152 autocrypt account. This will generate a key and add a record 153 to the database for use in autocrypt operations. 154 */ 155 if (mutt_edit_address (&addr, _("Autocrypt account address: "), 0)) 156 goto cleanup; 157 if (!addr || !addr->mailbox || addr->next) 158 { 159 /* L10N: 160 Autocrypt prompts for an account email address, and requires 161 a single address. This is shown if they entered something invalid, 162 nothing, or more than one address for some reason. 163 */ 164 mutt_error (_("Please enter a single email address")); 165 mutt_sleep (2); 166 done = 0; 167 } 168 else 169 done = 1; 170 } while (!done); 171 172 if (mutt_autocrypt_db_account_get (addr, &account) < 0) 173 goto cleanup; 174 if (account) 175 { 176 /* L10N: 177 When creating an autocrypt account, this message will be displayed 178 if there is already an account in the database with the email address 179 they just entered. 180 */ 181 mutt_error _("That email address already has an autocrypt account"); 182 mutt_sleep (1); 183 goto cleanup; 184 } 185 186 if (mutt_autocrypt_gpgme_select_or_create_key (addr, keyid, keydata)) 187 goto cleanup; 188 189 /* L10N: 190 Autocrypt has a setting "prefer-encrypt". 191 When the recommendation algorithm returns "available" and BOTH 192 sender and recipient choose "prefer-encrypt", encryption will be 193 automatically enabled. 194 Otherwise the UI will show encryption is "available" but the user 195 will be required to enable encryption manually. 196 */ 197 if (mutt_yesorno (_("Prefer encryption?"), MUTT_NO) == MUTT_YES) 198 prefer_encrypt = 1; 199 200 if (mutt_autocrypt_db_account_insert (addr, mutt_b2s (keyid), mutt_b2s (keydata), 201 prefer_encrypt)) 202 goto cleanup; 203 204 rv = 0; 205 206cleanup: 207 if (rv) 208 /* L10N: 209 Error message displayed if creating an autocrypt account failed 210 or was aborted by the user. 211 */ 212 mutt_error _("Autocrypt account creation aborted."); 213 else 214 /* L10N: 215 Message displayed after an autocrypt account is successfully created. 216 */ 217 mutt_message _("Autocrypt account creation succeeded"); 218 mutt_sleep (1); 219 220 mutt_autocrypt_db_account_free (&account); 221 rfc822_free_address (&addr); 222 mutt_buffer_pool_release (&keyid); 223 mutt_buffer_pool_release (&keydata); 224 return rv; 225} 226 227int mutt_autocrypt_process_autocrypt_header (HEADER *hdr, ENVELOPE *env) 228{ 229 AUTOCRYPTHDR *ac_hdr, *valid_ac_hdr = NULL; 230 struct timeval now; 231 AUTOCRYPT_PEER *peer = NULL; 232 AUTOCRYPT_PEER_HISTORY *peerhist = NULL; 233 BUFFER *keyid = NULL; 234 int update_db = 0, insert_db = 0, insert_db_history = 0, import_gpg = 0; 235 int rv = -1; 236 237 if (!option (OPTAUTOCRYPT)) 238 return 0; 239 240 if (mutt_autocrypt_init (0)) 241 return -1; 242 243 if (!hdr || !hdr->content || !env) 244 return 0; 245 246 /* 1.1 spec says to skip emails with more than one From header */ 247 if (!env->from || env->from->next) 248 return 0; 249 250 /* 1.1 spec also says to skip multipart/report emails */ 251 if (hdr->content->type == TYPEMULTIPART && 252 !(ascii_strcasecmp (hdr->content->subtype, "report"))) 253 return 0; 254 255 /* Ignore emails that appear to be more than a week in the future, 256 * since they can block all future updates during that time. */ 257 gettimeofday (&now, NULL); 258 if (hdr->date_sent > (now.tv_sec + 7 * 24 * 60 * 60)) 259 return 0; 260 261 for (ac_hdr = env->autocrypt; ac_hdr; ac_hdr = ac_hdr->next) 262 { 263 if (ac_hdr->invalid) 264 continue; 265 266 /* NOTE: this assumes the processing is occurring right after 267 * mutt_parse_rfc822_line() and the from ADDR is still in the same 268 * form (intl) as the autocrypt header addr field */ 269 if (ascii_strcasecmp (env->from->mailbox, ac_hdr->addr)) 270 continue; 271 272 /* 1.1 spec says ignore all, if more than one valid header is found. */ 273 if (valid_ac_hdr) 274 { 275 valid_ac_hdr = NULL; 276 break; 277 } 278 valid_ac_hdr = ac_hdr; 279 } 280 281 if (mutt_autocrypt_db_peer_get (env->from, &peer) < 0) 282 goto cleanup; 283 284 if (peer) 285 { 286 if (hdr->date_sent <= peer->autocrypt_timestamp) 287 { 288 rv = 0; 289 goto cleanup; 290 } 291 292 if (hdr->date_sent > peer->last_seen) 293 { 294 update_db = 1; 295 peer->last_seen = hdr->date_sent; 296 } 297 298 if (valid_ac_hdr) 299 { 300 update_db = 1; 301 peer->autocrypt_timestamp = hdr->date_sent; 302 peer->prefer_encrypt = valid_ac_hdr->prefer_encrypt; 303 if (mutt_strcmp (peer->keydata, valid_ac_hdr->keydata)) 304 { 305 import_gpg = 1; 306 insert_db_history = 1; 307 mutt_str_replace (&peer->keydata, valid_ac_hdr->keydata); 308 } 309 } 310 } 311 else if (valid_ac_hdr) 312 { 313 import_gpg = 1; 314 insert_db = 1; 315 insert_db_history = 1; 316 } 317 318 if (!(import_gpg || insert_db || update_db)) 319 { 320 rv = 0; 321 goto cleanup; 322 } 323 324 if (!peer) 325 { 326 peer = mutt_autocrypt_db_peer_new (); 327 peer->last_seen = hdr->date_sent; 328 peer->autocrypt_timestamp = hdr->date_sent; 329 peer->keydata = safe_strdup (valid_ac_hdr->keydata); 330 peer->prefer_encrypt = valid_ac_hdr->prefer_encrypt; 331 } 332 333 if (import_gpg) 334 { 335 keyid = mutt_buffer_pool_get (); 336 if (mutt_autocrypt_gpgme_import_key (peer->keydata, keyid)) 337 goto cleanup; 338 mutt_str_replace (&peer->keyid, mutt_b2s (keyid)); 339 } 340 341 if (insert_db && 342 mutt_autocrypt_db_peer_insert (env->from, peer)) 343 goto cleanup; 344 345 if (update_db && 346 mutt_autocrypt_db_peer_update (peer)) 347 goto cleanup; 348 349 if (insert_db_history) 350 { 351 peerhist = mutt_autocrypt_db_peer_history_new (); 352 peerhist->email_msgid = safe_strdup (env->message_id); 353 peerhist->timestamp = hdr->date_sent; 354 peerhist->keydata = safe_strdup (peer->keydata); 355 if (mutt_autocrypt_db_peer_history_insert (env->from, peerhist)) 356 goto cleanup; 357 } 358 359 rv = 0; 360 361cleanup: 362 mutt_autocrypt_db_peer_free (&peer); 363 mutt_autocrypt_db_peer_history_free (&peerhist); 364 mutt_buffer_pool_release (&keyid); 365 366 return rv; 367} 368 369int mutt_autocrypt_process_gossip_header (HEADER *hdr, ENVELOPE *prot_headers) 370{ 371 ENVELOPE *env; 372 AUTOCRYPTHDR *ac_hdr; 373 struct timeval now; 374 AUTOCRYPT_PEER *peer = NULL; 375 AUTOCRYPT_GOSSIP_HISTORY *gossip_hist = NULL; 376 ADDRESS *peer_addr, *recips = NULL, *last = NULL, ac_hdr_addr = {0}; 377 BUFFER *keyid = NULL; 378 int update_db = 0, insert_db = 0, insert_db_history = 0, import_gpg = 0; 379 int rv = -1; 380 381 if (!option (OPTAUTOCRYPT)) 382 return 0; 383 384 if (mutt_autocrypt_init (0)) 385 return -1; 386 387 if (!hdr || !hdr->env || !prot_headers) 388 return 0; 389 390 env = hdr->env; 391 392 if (!env->from) 393 return 0; 394 395 /* Ignore emails that appear to be more than a week in the future, 396 * since they can block all future updates during that time. */ 397 gettimeofday (&now, NULL); 398 if (hdr->date_sent > (now.tv_sec + 7 * 24 * 60 * 60)) 399 return 0; 400 401 keyid = mutt_buffer_pool_get (); 402 403 /* Normalize the recipient list for comparison */ 404 last = rfc822_append (&recips, env->to, 0); 405 last = rfc822_append (last ? &last : &recips, env->cc, 0); 406 rfc822_append (last ? &last : &recips, env->reply_to, 0); 407 mutt_autocrypt_db_normalize_addrlist (recips); 408 409 for (ac_hdr = prot_headers->autocrypt_gossip; ac_hdr; ac_hdr = ac_hdr->next) 410 { 411 if (ac_hdr->invalid) 412 continue; 413 414 /* normalize for comparison against recipient list */ 415 mutt_str_replace (&ac_hdr_addr.mailbox, ac_hdr->addr); 416 ac_hdr_addr.is_intl = 1; 417 ac_hdr_addr.intl_checked = 1; 418 mutt_autocrypt_db_normalize_addrlist (&ac_hdr_addr); 419 420 /* Check to make sure the address is in the recipient list. Since the 421 * addresses are normalized we use strcmp, not ascii_strcasecmp. */ 422 for (peer_addr = recips; peer_addr; peer_addr = peer_addr->next) 423 if (!mutt_strcmp (peer_addr->mailbox, ac_hdr_addr.mailbox)) 424 break; 425 if (!peer_addr) 426 continue; 427 428 if (mutt_autocrypt_db_peer_get (peer_addr, &peer) < 0) 429 goto cleanup; 430 431 if (peer) 432 { 433 if (hdr->date_sent <= peer->gossip_timestamp) 434 { 435 mutt_autocrypt_db_peer_free (&peer); 436 continue; 437 } 438 439 update_db = 1; 440 peer->gossip_timestamp = hdr->date_sent; 441 /* This is slightly different from the autocrypt 1.1 spec. 442 * Avoid setting an empty peer.gossip_keydata with a value that matches 443 * the current peer.keydata. */ 444 if ((peer->gossip_keydata && mutt_strcmp (peer->gossip_keydata, ac_hdr->keydata)) || 445 (!peer->gossip_keydata && mutt_strcmp (peer->keydata, ac_hdr->keydata))) 446 { 447 import_gpg = 1; 448 insert_db_history = 1; 449 mutt_str_replace (&peer->gossip_keydata, ac_hdr->keydata); 450 } 451 } 452 else 453 { 454 import_gpg = 1; 455 insert_db = 1; 456 insert_db_history = 1; 457 } 458 459 if (!peer) 460 { 461 peer = mutt_autocrypt_db_peer_new (); 462 peer->gossip_timestamp = hdr->date_sent; 463 peer->gossip_keydata = safe_strdup (ac_hdr->keydata); 464 } 465 466 if (import_gpg) 467 { 468 if (mutt_autocrypt_gpgme_import_key (peer->gossip_keydata, keyid)) 469 goto cleanup; 470 mutt_str_replace (&peer->gossip_keyid, mutt_b2s (keyid)); 471 } 472 473 if (insert_db && 474 mutt_autocrypt_db_peer_insert (peer_addr, peer)) 475 goto cleanup; 476 477 if (update_db && 478 mutt_autocrypt_db_peer_update (peer)) 479 goto cleanup; 480 481 if (insert_db_history) 482 { 483 gossip_hist = mutt_autocrypt_db_gossip_history_new (); 484 gossip_hist->sender_email_addr = safe_strdup (env->from->mailbox); 485 gossip_hist->email_msgid = safe_strdup (env->message_id); 486 gossip_hist->timestamp = hdr->date_sent; 487 gossip_hist->gossip_keydata = safe_strdup (peer->gossip_keydata); 488 if (mutt_autocrypt_db_gossip_history_insert (peer_addr, gossip_hist)) 489 goto cleanup; 490 } 491 492 mutt_autocrypt_db_peer_free (&peer); 493 mutt_autocrypt_db_gossip_history_free (&gossip_hist); 494 mutt_buffer_clear (keyid); 495 update_db = insert_db = insert_db_history = import_gpg = 0; 496 } 497 498 rv = 0; 499 500cleanup: 501 FREE (&ac_hdr_addr.mailbox); 502 rfc822_free_address (&recips); 503 mutt_autocrypt_db_peer_free (&peer); 504 mutt_autocrypt_db_gossip_history_free (&gossip_hist); 505 mutt_buffer_pool_release (&keyid); 506 507 return rv; 508} 509 510/* Returns the recommendation. If the recommendataion is > NO and 511 * keylist is not NULL, keylist will be populated with the autocrypt 512 * keyids 513 */ 514autocrypt_rec_t mutt_autocrypt_ui_recommendation (HEADER *hdr, char **keylist) 515{ 516 autocrypt_rec_t rv = AUTOCRYPT_REC_OFF; 517 AUTOCRYPT_ACCOUNT *account = NULL; 518 AUTOCRYPT_PEER *peer = NULL; 519 ADDRESS *recip, *recips = NULL, *last = NULL; 520 int all_encrypt = 1, has_discourage = 0; 521 BUFFER *keylist_buf = NULL; 522 const char *matching_key; 523 524 if (!option (OPTAUTOCRYPT) || 525 mutt_autocrypt_init (0) || 526 !hdr || 527 !hdr->env->from || 528 hdr->env->from->next) 529 return AUTOCRYPT_REC_OFF; 530 531 if (hdr->security & APPLICATION_SMIME) 532 return AUTOCRYPT_REC_OFF; 533 534 if (mutt_autocrypt_db_account_get (hdr->env->from, &account) <= 0) 535 goto cleanup; 536 537 if (!account->enabled) 538 goto cleanup; 539 540 keylist_buf = mutt_buffer_pool_get (); 541 mutt_buffer_addstr (keylist_buf, account->keyid); 542 543 last = rfc822_append (&recips, hdr->env->to, 0); 544 last = rfc822_append (last ? &last : &recips, hdr->env->cc, 0); 545 rfc822_append (last ? &last : &recips, hdr->env->bcc, 0); 546 547 rv = AUTOCRYPT_REC_NO; 548 if (!recips) 549 goto cleanup; 550 551 for (recip = recips; recip; recip = recip->next) 552 { 553 if (mutt_autocrypt_db_peer_get (recip, &peer) <= 0) 554 { 555 if (keylist) 556 /* L10N: 557 %s is an email address. Autocrypt is scanning for the keyids 558 to use to encrypt, but it can't find a valid keyid for this address. 559 The message is printed and they are returned to the compose menu. 560 */ 561 mutt_message (_("No (valid) autocrypt key found for %s."), recip->mailbox); 562 goto cleanup; 563 } 564 565 if (mutt_autocrypt_gpgme_is_valid_key (peer->keyid)) 566 { 567 matching_key = peer->keyid; 568 569 if (!(peer->last_seen && peer->autocrypt_timestamp) || 570 (peer->last_seen - peer->autocrypt_timestamp > 35 * 24 * 60 * 60)) 571 { 572 has_discourage = 1; 573 all_encrypt = 0; 574 } 575 576 if (!account->prefer_encrypt || !peer->prefer_encrypt) 577 all_encrypt = 0; 578 } 579 else if (mutt_autocrypt_gpgme_is_valid_key (peer->gossip_keyid)) 580 { 581 matching_key = peer->gossip_keyid; 582 583 has_discourage = 1; 584 all_encrypt = 0; 585 } 586 else 587 { 588 if (keylist) 589 mutt_message (_("No (valid) autocrypt key found for %s."), recip->mailbox); 590 goto cleanup; 591 } 592 593 if (mutt_buffer_len (keylist_buf)) 594 mutt_buffer_addch (keylist_buf, ' '); 595 mutt_buffer_addstr (keylist_buf, matching_key); 596 597 mutt_autocrypt_db_peer_free (&peer); 598 } 599 600 if (all_encrypt) 601 rv = AUTOCRYPT_REC_YES; 602 else if (has_discourage) 603 rv = AUTOCRYPT_REC_DISCOURAGE; 604 else 605 rv = AUTOCRYPT_REC_AVAILABLE; 606 607 if (keylist) 608 mutt_str_replace (keylist, mutt_b2s (keylist_buf)); 609 610cleanup: 611 mutt_autocrypt_db_account_free (&account); 612 rfc822_free_address (&recips); 613 mutt_autocrypt_db_peer_free (&peer); 614 mutt_buffer_pool_release (&keylist_buf); 615 return rv; 616} 617 618int mutt_autocrypt_set_sign_as_default_key (HEADER *hdr) 619{ 620 int rv = -1; 621 AUTOCRYPT_ACCOUNT *account = NULL; 622 623 if (!option (OPTAUTOCRYPT) || 624 mutt_autocrypt_init (0) || 625 !hdr || 626 !hdr->env->from || 627 hdr->env->from->next) 628 return -1; 629 630 if (mutt_autocrypt_db_account_get (hdr->env->from, &account) <= 0) 631 goto cleanup; 632 if (!account->keyid) 633 goto cleanup; 634 if (!account->enabled) 635 goto cleanup; 636 637 mutt_str_replace (&AutocryptSignAs, account->keyid); 638 mutt_str_replace (&AutocryptDefaultKey, account->keyid); 639 640 rv = 0; 641 642cleanup: 643 mutt_autocrypt_db_account_free (&account); 644 return rv; 645} 646 647 648static void write_autocrypt_header_line (FILE *fp, const char *addr, 649 int prefer_encrypt, 650 const char *keydata) 651{ 652 int count = 0; 653 654 fprintf (fp, "addr=%s; ", addr); 655 if (prefer_encrypt) 656 fputs ("prefer-encrypt=mutual; ", fp); 657 fputs ("keydata=\n", fp); 658 659 while (*keydata) 660 { 661 count = 0; 662 fputs ("\t", fp); 663 while (*keydata && count < 75) 664 { 665 fputc (*keydata, fp); 666 count++; 667 keydata++; 668 } 669 fputs ("\n", fp); 670 } 671} 672 673int mutt_autocrypt_write_autocrypt_header (ENVELOPE *env, FILE *fp) 674{ 675 int rv = -1; 676 AUTOCRYPT_ACCOUNT *account = NULL; 677 678 if (!option (OPTAUTOCRYPT) || 679 mutt_autocrypt_init (0) || 680 !env || 681 !env->from || 682 env->from->next) 683 return -1; 684 685 if (mutt_autocrypt_db_account_get (env->from, &account) <= 0) 686 goto cleanup; 687 if (!account->keydata) 688 goto cleanup; 689 if (!account->enabled) 690 goto cleanup; 691 692 fputs ("Autocrypt: ", fp); 693 write_autocrypt_header_line (fp, account->email_addr, account->prefer_encrypt, 694 account->keydata); 695 696 rv = 0; 697 698cleanup: 699 mutt_autocrypt_db_account_free (&account); 700 return rv; 701} 702 703int mutt_autocrypt_write_gossip_headers (ENVELOPE *env, FILE *fp) 704{ 705 AUTOCRYPTHDR *gossip; 706 707 if (!option (OPTAUTOCRYPT) || 708 mutt_autocrypt_init (0) || 709 !env) 710 return -1; 711 712 for (gossip = env->autocrypt_gossip; gossip; gossip = gossip->next) 713 { 714 fputs ("Autocrypt-Gossip: ", fp); 715 write_autocrypt_header_line (fp, gossip->addr, 0, gossip->keydata); 716 } 717 718 return 0; 719} 720 721int mutt_autocrypt_generate_gossip_list (HEADER *hdr) 722{ 723 int rv = -1; 724 AUTOCRYPT_PEER *peer = NULL; 725 AUTOCRYPT_ACCOUNT *account = NULL; 726 ADDRESS *recip, *recips = NULL, *last = NULL; 727 AUTOCRYPTHDR *gossip; 728 const char *keydata, *addr; 729 ENVELOPE *mime_headers; 730 731 if (!option (OPTAUTOCRYPT) || 732 mutt_autocrypt_init (0) || 733 !hdr) 734 return -1; 735 736 mime_headers = hdr->content->mime_headers; 737 if (!mime_headers) 738 mime_headers = hdr->content->mime_headers = mutt_new_envelope (); 739 mutt_free_autocrypthdr (&mime_headers->autocrypt_gossip); 740 741 last = rfc822_append (&recips, hdr->env->to, 0); 742 last = rfc822_append (last ? &last : &recips, hdr->env->cc, 0); 743 744 for (recip = recips; recip; recip = recip->next) 745 { 746 /* At this point, we just accept missing keys and include what 747 * we can. */ 748 if (mutt_autocrypt_db_peer_get (recip, &peer) <= 0) 749 continue; 750 751 keydata = NULL; 752 if (mutt_autocrypt_gpgme_is_valid_key (peer->keyid)) 753 keydata = peer->keydata; 754 else if (mutt_autocrypt_gpgme_is_valid_key (peer->gossip_keyid)) 755 keydata = peer->gossip_keydata; 756 757 if (keydata) 758 { 759 gossip = mutt_new_autocrypthdr (); 760 gossip->addr = safe_strdup (peer->email_addr); 761 gossip->keydata = safe_strdup (keydata); 762 gossip->next = mime_headers->autocrypt_gossip; 763 mime_headers->autocrypt_gossip = gossip; 764 } 765 766 mutt_autocrypt_db_peer_free (&peer); 767 } 768 769 for (recip = hdr->env->reply_to; recip; recip = recip->next) 770 { 771 addr = keydata = NULL; 772 if (mutt_autocrypt_db_account_get (recip, &account) > 0) 773 { 774 addr = account->email_addr; 775 keydata = account->keydata; 776 } 777 else if (mutt_autocrypt_db_peer_get (recip, &peer) > 0) 778 { 779 addr = peer->email_addr; 780 if (mutt_autocrypt_gpgme_is_valid_key (peer->keyid)) 781 keydata = peer->keydata; 782 else if (mutt_autocrypt_gpgme_is_valid_key (peer->gossip_keyid)) 783 keydata = peer->gossip_keydata; 784 } 785 786 if (keydata) 787 { 788 gossip = mutt_new_autocrypthdr (); 789 gossip->addr = safe_strdup (addr); 790 gossip->keydata = safe_strdup (keydata); 791 gossip->next = mime_headers->autocrypt_gossip; 792 mime_headers->autocrypt_gossip = gossip; 793 } 794 mutt_autocrypt_db_account_free (&account); 795 mutt_autocrypt_db_peer_free (&peer); 796 } 797 798 rfc822_free_address (&recips); 799 mutt_autocrypt_db_account_free (&account); 800 mutt_autocrypt_db_peer_free (&peer); 801 return rv; 802} 803 804/* This is invoked during the first autocrypt initialization, 805 * to scan one or more mailboxes for autocrypt headers. 806 * 807 * Due to the implementation, header-cached headers are not scanned, 808 * so this routine just opens up the mailboxes with $header_cache 809 * temporarily disabled. 810 */ 811void mutt_autocrypt_scan_mailboxes (void) 812{ 813 int scan; 814 BUFFER *folderbuf = NULL; 815 CONTEXT *ctx = NULL; 816 817#ifdef USE_HCACHE 818 char *old_hdrcache = HeaderCache; 819 HeaderCache = NULL; 820#endif 821 822 folderbuf = mutt_buffer_pool_get (); 823 824 /* L10N: 825 The first time autocrypt is enabled, Mutt will ask to scan 826 through one or more mailboxes for Autocrypt: headers. 827 Those headers are then captured in the database as peer records 828 and used for encryption. 829 If this is answered yes, they will be prompted for a mailbox. 830 */ 831 scan = mutt_yesorno (_("Scan a mailbox for autocrypt headers?"), 832 MUTT_YES); 833 while (scan == MUTT_YES) 834 { 835 /* L10N: 836 The prompt for a mailbox to scan for Autocrypt: headers 837 */ 838 if ((!mutt_buffer_enter_fname (_("Scan mailbox"), folderbuf, 1)) && 839 mutt_buffer_len (folderbuf)) 840 { 841 mutt_buffer_expand_path (folderbuf); 842 /* NOTE: I am purposely *not* executing folder hooks here, 843 * as they can do all sorts of things like push into the getch() buffer. 844 * Authentication should be in account-hooks. */ 845 ctx = mx_open_mailbox (mutt_b2s (folderbuf), MUTT_READONLY, NULL); 846 mutt_sleep (1); 847 mx_close_mailbox (ctx, NULL); 848 849 FREE (&ctx); 850 mutt_buffer_clear (folderbuf); 851 } 852 853 /* L10N: 854 This is the second prompt to see if the user would like 855 to scan more than one mailbox for Autocrypt headers. 856 I'm purposely being extra verbose; asking first then prompting 857 for a mailbox. This is because this is a one-time operation 858 and I don't want them to accidentally ctrl-g and abort it. 859 */ 860 scan = mutt_yesorno (_("Scan another mailbox for autocrypt headers?"), 861 MUTT_YES); 862 } 863 864#ifdef USE_HCACHE 865 HeaderCache = old_hdrcache; 866#endif 867 mutt_buffer_pool_release (&folderbuf); 868}