mutt stable branch with some hacks
at master 1044 lines 23 kB view raw
1/* 2 * Copyright (C) 1996-1997,2007 Michael R. Elkins <me@mutt.org> 3 * Copyright (c) 1998-2003 Thomas Roessler <roessler@does-not-exist.org> 4 * 5 * This program is free software; you can redistribute it 6 * and/or modify it under the terms of the GNU General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later 9 * version. 10 * 11 * This program is distributed in the hope that it will be 12 * useful, but WITHOUT ANY WARRANTY; without even the implied 13 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 14 * PURPOSE. See the GNU General Public License for more 15 * details. 16 * 17 * You should have received a copy of the GNU General Public 18 * License along with this program; if not, write to the Free 19 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA. 21 */ 22 23#if HAVE_CONFIG_H 24# include "config.h" 25#endif 26 27#include "mutt.h" 28#include "mutt_curses.h" 29#include "mutt_menu.h" 30#include "mime.h" 31#include "pgp.h" 32#include "pager.h" 33#include "sort.h" 34 35#include <string.h> 36#include <ctype.h> 37#include <stdlib.h> 38#include <unistd.h> 39#include <sys/stat.h> 40#include <sys/wait.h> 41 42#include <locale.h> 43 44#ifdef CRYPT_BACKEND_CLASSIC_PGP 45 46struct pgp_cache 47{ 48 char *what; 49 char *dflt; 50 struct pgp_cache *next; 51}; 52 53static struct pgp_cache *id_defaults = NULL; 54 55static const char trust_flags[] = "?- +"; 56 57static char *pgp_key_abilities (int flags) 58{ 59 static char buff[3]; 60 61 if (!(flags & KEYFLAG_CANENCRYPT)) 62 buff[0] = '-'; 63 else if (flags & KEYFLAG_PREFER_SIGNING) 64 buff[0] = '.'; 65 else 66 buff[0] = 'e'; 67 68 if (!(flags & KEYFLAG_CANSIGN)) 69 buff[1] = '-'; 70 else if (flags & KEYFLAG_PREFER_ENCRYPTION) 71 buff[1] = '.'; 72 else 73 buff[1] = 's'; 74 75 buff[2] = '\0'; 76 77 return buff; 78} 79 80static char pgp_flags (int flags) 81{ 82 if (flags & KEYFLAG_REVOKED) 83 return 'R'; 84 else if (flags & KEYFLAG_EXPIRED) 85 return 'X'; 86 else if (flags & KEYFLAG_DISABLED) 87 return 'd'; 88 else if (flags & KEYFLAG_CRITICAL) 89 return 'c'; 90 else 91 return ' '; 92} 93 94static pgp_key_t pgp_principal_key (pgp_key_t key) 95{ 96 if (key->flags & KEYFLAG_SUBKEY && key->parent) 97 return key->parent; 98 else 99 return key; 100} 101 102/* 103 * Format an entry on the PGP key selection menu. 104 * 105 * %n number 106 * %k key id %K key id of the principal key 107 * %u user id 108 * %a algorithm %A algorithm of the princ. key 109 * %l length %L length of the princ. key 110 * %f flags %F flags of the princ. key 111 * %c capabilities %C capabilities of the princ. key 112 * %t trust/validity of the key-uid association 113 * %[...] date of key using strftime(3) 114 */ 115 116typedef struct pgp_entry 117{ 118 size_t num; 119 pgp_uid_t *uid; 120} pgp_entry_t; 121 122static const char *pgp_entry_fmt (char *dest, 123 size_t destlen, 124 size_t col, 125 int cols, 126 char op, 127 const char *src, 128 const char *prefix, 129 const char *ifstring, 130 const char *elsestring, 131 unsigned long data, 132 format_flag flags) 133{ 134 char fmt[16]; 135 pgp_entry_t *entry; 136 pgp_uid_t *uid; 137 pgp_key_t key, pkey; 138 int kflags = 0; 139 int optional = (flags & MUTT_FORMAT_OPTIONAL); 140 141 entry = (pgp_entry_t *) data; 142 uid = entry->uid; 143 key = uid->parent; 144 pkey = pgp_principal_key (key); 145 146 if (isupper ((unsigned char) op)) 147 key = pkey; 148 149 kflags = key->flags | (pkey->flags & KEYFLAG_RESTRICTIONS) 150 | uid->flags; 151 152 switch (ascii_tolower (op)) 153 { 154 case '[': 155 156 { 157 const char *cp; 158 char buf2[SHORT_STRING], *p; 159 int do_locales; 160 struct tm *tm; 161 size_t len; 162 163 p = dest; 164 165 cp = src; 166 if (*cp == '!') 167 { 168 do_locales = 0; 169 cp++; 170 } 171 else 172 do_locales = 1; 173 174 len = destlen - 1; 175 while (len > 0 && *cp != ']') 176 { 177 if (*cp == '%') 178 { 179 cp++; 180 if (len >= 2) 181 { 182 *p++ = '%'; 183 *p++ = *cp; 184 len -= 2; 185 } 186 else 187 break; /* not enough space */ 188 cp++; 189 } 190 else 191 { 192 *p++ = *cp++; 193 len--; 194 } 195 } 196 *p = 0; 197 198 199 tm = localtime (&key->gen_time); 200 201 if (!do_locales) 202 setlocale (LC_TIME, "C"); 203 strftime (buf2, sizeof (buf2), dest, tm); 204 if (!do_locales) 205 setlocale (LC_TIME, ""); 206 207 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 208 snprintf (dest, destlen, fmt, buf2); 209 if (len > 0) 210 src = cp + 1; 211 } 212 break; 213 case 'n': 214 if (!optional) 215 { 216 snprintf (fmt, sizeof (fmt), "%%%sd", prefix); 217 snprintf (dest, destlen, fmt, entry->num); 218 } 219 break; 220 case 'k': 221 if (!optional) 222 { 223 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 224 snprintf (dest, destlen, fmt, _pgp_keyid (key)); 225 } 226 break; 227 case 'u': 228 if (!optional) 229 { 230 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 231 snprintf (dest, destlen, fmt, NONULL (uid->addr)); 232 } 233 break; 234 case 'a': 235 if (!optional) 236 { 237 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 238 snprintf (dest, destlen, fmt, key->algorithm); 239 } 240 break; 241 case 'l': 242 if (!optional) 243 { 244 snprintf (fmt, sizeof (fmt), "%%%sd", prefix); 245 snprintf (dest, destlen, fmt, key->keylen); 246 } 247 break; 248 case 'f': 249 if (!optional) 250 { 251 snprintf (fmt, sizeof (fmt), "%%%sc", prefix); 252 snprintf (dest, destlen, fmt, pgp_flags (kflags)); 253 } 254 else if (!(kflags & (KEYFLAG_RESTRICTIONS))) 255 optional = 0; 256 break; 257 case 'c': 258 if (!optional) 259 { 260 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 261 snprintf (dest, destlen, fmt, pgp_key_abilities (kflags)); 262 } 263 else if (!(kflags & (KEYFLAG_ABILITIES))) 264 optional = 0; 265 break; 266 case 't': 267 if (!optional) 268 { 269 snprintf (fmt, sizeof (fmt), "%%%sc", prefix); 270 snprintf (dest, destlen, fmt, trust_flags[uid->trust & 0x03]); 271 } 272 else if (!(uid->trust & 0x03)) 273 /* undefined trust */ 274 optional = 0; 275 break; 276 default: 277 *dest = '\0'; 278 } 279 280 if (optional) 281 mutt_FormatString (dest, destlen, col, cols, ifstring, mutt_attach_fmt, data, 0); 282 else if (flags & MUTT_FORMAT_OPTIONAL) 283 mutt_FormatString (dest, destlen, col, cols, elsestring, mutt_attach_fmt, data, 0); 284 return (src); 285} 286 287static void pgp_entry (char *s, size_t l, MUTTMENU * menu, int num) 288{ 289 pgp_uid_t **KeyTable = (pgp_uid_t **) menu->data; 290 pgp_entry_t entry; 291 292 entry.uid = KeyTable[num]; 293 entry.num = num + 1; 294 295 mutt_FormatString (s, l, 0, MuttIndexWindow->cols, NONULL (PgpEntryFormat), pgp_entry_fmt, 296 (unsigned long) &entry, MUTT_FORMAT_ARROWCURSOR); 297} 298 299static int _pgp_compare_address (const void *a, const void *b) 300{ 301 int r; 302 303 pgp_uid_t **s = (pgp_uid_t **) a; 304 pgp_uid_t **t = (pgp_uid_t **) b; 305 306 if ((r = mutt_strcasecmp ((*s)->addr, (*t)->addr))) 307 return r > 0; 308 else 309 return (mutt_strcasecmp (pgp_fpr_or_lkeyid ((*s)->parent), 310 pgp_fpr_or_lkeyid ((*t)->parent)) > 0); 311} 312 313static int pgp_compare_address (const void *a, const void *b) 314{ 315 return ((PgpSortKeys & SORT_REVERSE) ? !_pgp_compare_address (a, b) 316 : _pgp_compare_address (a, b)); 317} 318 319 320 321static int _pgp_compare_keyid (const void *a, const void *b) 322{ 323 int r; 324 325 pgp_uid_t **s = (pgp_uid_t **) a; 326 pgp_uid_t **t = (pgp_uid_t **) b; 327 328 if ((r = mutt_strcasecmp (pgp_fpr_or_lkeyid ((*s)->parent), 329 pgp_fpr_or_lkeyid ((*t)->parent)))) 330 return r > 0; 331 else 332 return (mutt_strcasecmp ((*s)->addr, (*t)->addr)) > 0; 333} 334 335static int pgp_compare_keyid (const void *a, const void *b) 336{ 337 return ((PgpSortKeys & SORT_REVERSE) ? !_pgp_compare_keyid (a, b) 338 : _pgp_compare_keyid (a, b)); 339} 340 341static int _pgp_compare_date (const void *a, const void *b) 342{ 343 int r; 344 pgp_uid_t **s = (pgp_uid_t **) a; 345 pgp_uid_t **t = (pgp_uid_t **) b; 346 347 if ((r = ((*s)->parent->gen_time - (*t)->parent->gen_time))) 348 return r > 0; 349 return (mutt_strcasecmp ((*s)->addr, (*t)->addr)) > 0; 350} 351 352static int pgp_compare_date (const void *a, const void *b) 353{ 354 return ((PgpSortKeys & SORT_REVERSE) ? !_pgp_compare_date (a, b) 355 : _pgp_compare_date (a, b)); 356} 357 358static int _pgp_compare_trust (const void *a, const void *b) 359{ 360 int r; 361 362 pgp_uid_t **s = (pgp_uid_t **) a; 363 pgp_uid_t **t = (pgp_uid_t **) b; 364 365 if ((r = (((*s)->parent->flags & (KEYFLAG_RESTRICTIONS)) 366 - ((*t)->parent->flags & (KEYFLAG_RESTRICTIONS))))) 367 return r > 0; 368 if ((r = ((*s)->trust - (*t)->trust))) 369 return r < 0; 370 if ((r = ((*s)->parent->keylen - (*t)->parent->keylen))) 371 return r < 0; 372 if ((r = ((*s)->parent->gen_time - (*t)->parent->gen_time))) 373 return r < 0; 374 if ((r = mutt_strcasecmp ((*s)->addr, (*t)->addr))) 375 return r > 0; 376 return (mutt_strcasecmp (pgp_fpr_or_lkeyid ((*s)->parent), 377 pgp_fpr_or_lkeyid ((*t)->parent))) > 0; 378} 379 380static int pgp_compare_trust (const void *a, const void *b) 381{ 382 return ((PgpSortKeys & SORT_REVERSE) ? !_pgp_compare_trust (a, b) 383 : _pgp_compare_trust (a, b)); 384} 385 386static int pgp_key_is_valid (pgp_key_t k) 387{ 388 pgp_key_t pk = pgp_principal_key (k); 389 if (k->flags & KEYFLAG_CANTUSE) 390 return 0; 391 if (pk->flags & KEYFLAG_CANTUSE) 392 return 0; 393 394 return 1; 395} 396 397static int pgp_id_is_strong (pgp_uid_t *uid) 398{ 399 if ((uid->trust & 3) < 3) 400 return 0; 401 /* else */ 402 return 1; 403} 404 405static int pgp_id_is_valid (pgp_uid_t *uid) 406{ 407 if (!pgp_key_is_valid (uid->parent)) 408 return 0; 409 if (uid->flags & KEYFLAG_CANTUSE) 410 return 0; 411 /* else */ 412 return 1; 413} 414 415#define PGP_KV_VALID 1 416#define PGP_KV_ADDR 2 417#define PGP_KV_STRING 4 418#define PGP_KV_STRONGID 8 419 420#define PGP_KV_MATCH (PGP_KV_ADDR|PGP_KV_STRING) 421 422static int pgp_id_matches_addr (ADDRESS *addr, ADDRESS *u_addr, pgp_uid_t *uid) 423{ 424 int rv = 0; 425 426 if (pgp_id_is_valid (uid)) 427 rv |= PGP_KV_VALID; 428 429 if (pgp_id_is_strong (uid)) 430 rv |= PGP_KV_STRONGID; 431 432 if (addr->mailbox && u_addr->mailbox 433 && mutt_strcasecmp (addr->mailbox, u_addr->mailbox) == 0) 434 rv |= PGP_KV_ADDR; 435 436 if (addr->personal && u_addr->personal 437 && mutt_strcasecmp (addr->personal, u_addr->personal) == 0) 438 rv |= PGP_KV_STRING; 439 440 return rv; 441} 442 443static pgp_key_t pgp_select_key (pgp_key_t keys, 444 ADDRESS * p, const char *s) 445{ 446 int keymax; 447 pgp_uid_t **KeyTable; 448 MUTTMENU *menu; 449 int i, done = 0; 450 char helpstr[LONG_STRING], buf[LONG_STRING], tmpbuf[STRING]; 451 char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX]; 452 FILE *fp, *devnull; 453 pid_t thepid; 454 pgp_key_t kp; 455 pgp_uid_t *a; 456 int (*f) (const void *, const void *); 457 458 int unusable = 0; 459 460 keymax = 0; 461 KeyTable = NULL; 462 463 for (i = 0, kp = keys; kp; kp = kp->next) 464 { 465 if (!option (OPTPGPSHOWUNUSABLE) && (kp->flags & KEYFLAG_CANTUSE)) 466 { 467 unusable = 1; 468 continue; 469 } 470 471 for (a = kp->address; a; a = a->next) 472 { 473 if (!option (OPTPGPSHOWUNUSABLE) && (a->flags & KEYFLAG_CANTUSE)) 474 { 475 unusable = 1; 476 continue; 477 } 478 479 if (i == keymax) 480 { 481 keymax += 5; 482 safe_realloc (&KeyTable, sizeof (pgp_uid_t *) * keymax); 483 } 484 485 KeyTable[i++] = a; 486 } 487 } 488 489 if (!i && unusable) 490 { 491 mutt_error _("All matching keys are expired, revoked, or disabled."); 492 mutt_sleep (1); 493 return NULL; 494 } 495 496 switch (PgpSortKeys & SORT_MASK) 497 { 498 case SORT_DATE: 499 f = pgp_compare_date; 500 break; 501 case SORT_KEYID: 502 f = pgp_compare_keyid; 503 break; 504 case SORT_ADDRESS: 505 f = pgp_compare_address; 506 break; 507 case SORT_TRUST: 508 default: 509 f = pgp_compare_trust; 510 break; 511 } 512 qsort (KeyTable, i, sizeof (pgp_uid_t *), f); 513 514 helpstr[0] = 0; 515 mutt_make_help (buf, sizeof (buf), _("Exit "), MENU_PGP, OP_EXIT); 516 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ 517 mutt_make_help (buf, sizeof (buf), _("Select "), MENU_PGP, 518 OP_GENERIC_SELECT_ENTRY); 519 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ 520 mutt_make_help (buf, sizeof (buf), _("Check key "), MENU_PGP, OP_VERIFY_KEY); 521 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ 522 mutt_make_help (buf, sizeof (buf), _("Help"), MENU_PGP, OP_HELP); 523 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ 524 525 menu = mutt_new_menu (MENU_PGP); 526 menu->max = i; 527 menu->make_entry = pgp_entry; 528 menu->help = helpstr; 529 menu->data = KeyTable; 530 531 if (p) 532 snprintf (buf, sizeof (buf), _("PGP keys matching <%s>."), p->mailbox); 533 else 534 snprintf (buf, sizeof (buf), _("PGP keys matching \"%s\"."), s); 535 536 537 menu->title = buf; 538 539 kp = NULL; 540 541 mutt_clear_error (); 542 543 while (!done) 544 { 545 switch (mutt_menuLoop (menu)) 546 { 547 548 case OP_VERIFY_KEY: 549 550 mutt_mktemp (tempfile, sizeof (tempfile)); 551 if ((devnull = fopen ("/dev/null", "w")) == NULL) /* __FOPEN_CHECKED__ */ 552 { 553 mutt_perror _("Can't open /dev/null"); 554 break; 555 } 556 if ((fp = safe_fopen (tempfile, "w")) == NULL) 557 { 558 safe_fclose (&devnull); 559 mutt_perror _("Can't create temporary file"); 560 break; 561 } 562 563 mutt_message _("Invoking PGP..."); 564 565 snprintf (tmpbuf, sizeof (tmpbuf), "0x%s", 566 pgp_fpr_or_lkeyid (pgp_principal_key (KeyTable[menu->current]->parent))); 567 568 if ((thepid = pgp_invoke_verify_key (NULL, NULL, NULL, -1, 569 fileno (fp), fileno (devnull), tmpbuf)) == -1) 570 { 571 mutt_perror _("Can't create filter"); 572 unlink (tempfile); 573 safe_fclose (&fp); 574 safe_fclose (&devnull); 575 } 576 577 mutt_wait_filter (thepid); 578 safe_fclose (&fp); 579 safe_fclose (&devnull); 580 mutt_clear_error (); 581 snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"), 582 pgp_keyid (pgp_principal_key (KeyTable[menu->current]->parent))); 583 mutt_do_pager (cmd, tempfile, 0, NULL); 584 menu->redraw = REDRAW_FULL; 585 586 break; 587 588 case OP_VIEW_ID: 589 590 mutt_message ("%s", NONULL (KeyTable[menu->current]->addr)); 591 break; 592 593 case OP_GENERIC_SELECT_ENTRY: 594 595 596 /* XXX make error reporting more verbose */ 597 598 if (option (OPTPGPCHECKTRUST)) 599 if (!pgp_key_is_valid (KeyTable[menu->current]->parent)) 600 { 601 mutt_error _("This key can't be used: expired/disabled/revoked."); 602 break; 603 } 604 605 if (option (OPTPGPCHECKTRUST) && 606 (!pgp_id_is_valid (KeyTable[menu->current]) 607 || !pgp_id_is_strong (KeyTable[menu->current]))) 608 { 609 char *s = ""; 610 char buff[LONG_STRING]; 611 612 if (KeyTable[menu->current]->flags & KEYFLAG_CANTUSE) 613 s = N_("ID is expired/disabled/revoked."); 614 else switch (KeyTable[menu->current]->trust & 0x03) 615 { 616 case 0: 617 s = N_("ID has undefined validity."); 618 break; 619 case 1: 620 s = N_("ID is not valid."); 621 break; 622 case 2: 623 s = N_("ID is only marginally valid."); 624 break; 625 } 626 627 snprintf (buff, sizeof (buff), _("%s Do you really want to use the key?"), 628 _(s)); 629 630 if (mutt_yesorno (buff, MUTT_NO) != MUTT_YES) 631 { 632 mutt_clear_error (); 633 break; 634 } 635 } 636 637# if 0 638 kp = pgp_principal_key (KeyTable[menu->current]->parent); 639# else 640 kp = KeyTable[menu->current]->parent; 641# endif 642 done = 1; 643 break; 644 645 case OP_EXIT: 646 647 kp = NULL; 648 done = 1; 649 break; 650 } 651 } 652 653 mutt_menuDestroy (&menu); 654 FREE (&KeyTable); 655 656 set_option (OPTNEEDREDRAW); 657 658 return (kp); 659} 660 661pgp_key_t pgp_ask_for_key (char *tag, char *whatfor, 662 short abilities, pgp_ring_t keyring) 663{ 664 pgp_key_t key; 665 char resp[SHORT_STRING]; 666 struct pgp_cache *l = NULL; 667 668 mutt_clear_error (); 669 670 resp[0] = 0; 671 if (whatfor) 672 { 673 674 for (l = id_defaults; l; l = l->next) 675 if (!mutt_strcasecmp (whatfor, l->what)) 676 { 677 strfcpy (resp, NONULL (l->dflt), sizeof (resp)); 678 break; 679 } 680 } 681 682 683 FOREVER 684 { 685 resp[0] = 0; 686 if (mutt_get_field (tag, resp, sizeof (resp), MUTT_CLEAR) != 0) 687 return NULL; 688 689 if (whatfor) 690 { 691 if (l) 692 mutt_str_replace (&l->dflt, resp); 693 else 694 { 695 l = safe_malloc (sizeof (struct pgp_cache)); 696 l->next = id_defaults; 697 id_defaults = l; 698 l->what = safe_strdup (whatfor); 699 l->dflt = safe_strdup (resp); 700 } 701 } 702 703 if ((key = pgp_getkeybystr (resp, abilities, keyring))) 704 return key; 705 706 BEEP (); 707 } 708 /* not reached */ 709} 710 711/* generate a public key attachment */ 712 713BODY *pgp_make_key_attachment (char *tempf) 714{ 715 BODY *att; 716 char buff[LONG_STRING]; 717 char tempfb[_POSIX_PATH_MAX], tmp[STRING]; 718 FILE *tempfp; 719 FILE *devnull; 720 struct stat sb; 721 pid_t thepid; 722 pgp_key_t key; 723 unset_option (OPTPGPCHECKTRUST); 724 725 key = pgp_ask_for_key (_("Please enter the key ID: "), NULL, 0, PGP_PUBRING); 726 727 if (!key) return NULL; 728 729 snprintf (tmp, sizeof (tmp), "0x%s", pgp_fpr_or_lkeyid (pgp_principal_key (key))); 730 pgp_free_key (&key); 731 732 if (!tempf) 733 { 734 mutt_mktemp (tempfb, sizeof (tempfb)); 735 tempf = tempfb; 736 } 737 738 if ((tempfp = safe_fopen (tempf, tempf == tempfb ? "w" : "a")) == NULL) 739 { 740 mutt_perror _("Can't create temporary file"); 741 return NULL; 742 } 743 744 if ((devnull = fopen ("/dev/null", "w")) == NULL) /* __FOPEN_CHECKED__ */ 745 { 746 mutt_perror _("Can't open /dev/null"); 747 safe_fclose (&tempfp); 748 if (tempf == tempfb) 749 unlink (tempf); 750 return NULL; 751 } 752 753 mutt_message _("Invoking PGP..."); 754 755 756 if ((thepid = 757 pgp_invoke_export (NULL, NULL, NULL, -1, 758 fileno (tempfp), fileno (devnull), tmp)) == -1) 759 { 760 mutt_perror _("Can't create filter"); 761 unlink (tempf); 762 safe_fclose (&tempfp); 763 safe_fclose (&devnull); 764 return NULL; 765 } 766 767 mutt_wait_filter (thepid); 768 769 safe_fclose (&tempfp); 770 safe_fclose (&devnull); 771 772 att = mutt_new_body (); 773 att->filename = safe_strdup (tempf); 774 att->unlink = 1; 775 att->use_disp = 0; 776 att->type = TYPEAPPLICATION; 777 att->subtype = safe_strdup ("pgp-keys"); 778 snprintf (buff, sizeof (buff), _("PGP Key %s."), tmp); 779 att->description = safe_strdup (buff); 780 mutt_update_encoding (att); 781 782 stat (tempf, &sb); 783 att->length = sb.st_size; 784 785 return att; 786} 787 788static LIST *pgp_add_string_to_hints (LIST *hints, const char *str) 789{ 790 char *scratch; 791 char *t; 792 793 if ((scratch = safe_strdup (str)) == NULL) 794 return hints; 795 796 for (t = strtok (scratch, " ,.:\"()<>\n"); t; 797 t = strtok (NULL, " ,.:\"()<>\n")) 798 { 799 if (strlen (t) > 3) 800 hints = mutt_add_list (hints, t); 801 } 802 803 FREE (&scratch); 804 return hints; 805} 806 807static pgp_key_t *pgp_get_lastp (pgp_key_t p) 808{ 809 for (; p; p = p->next) 810 if (!p->next) 811 return &p->next; 812 813 return NULL; 814} 815 816pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring, 817 int oppenc_mode) 818{ 819 ADDRESS *r, *p; 820 LIST *hints = NULL; 821 822 int multi = 0; 823 int match; 824 825 pgp_key_t keys, k, kn; 826 pgp_key_t the_strong_valid_key = NULL; 827 pgp_key_t a_valid_addrmatch_key = NULL; 828 pgp_key_t matches = NULL; 829 pgp_key_t *last = &matches; 830 pgp_uid_t *q; 831 832 if (a && a->mailbox) 833 hints = pgp_add_string_to_hints (hints, a->mailbox); 834 if (a && a->personal) 835 hints = pgp_add_string_to_hints (hints, a->personal); 836 837 if (! oppenc_mode ) 838 mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox); 839 keys = pgp_get_candidates (keyring, hints); 840 841 mutt_free_list (&hints); 842 843 if (!keys) 844 return NULL; 845 846 dprint (5, (debugfile, "pgp_getkeybyaddr: looking for %s <%s>.", 847 a->personal, a->mailbox)); 848 849 850 for (k = keys; k; k = kn) 851 { 852 kn = k->next; 853 854 dprint (5, (debugfile, " looking at key: %s\n", 855 pgp_keyid (k))); 856 857 if (abilities && !(k->flags & abilities)) 858 { 859 dprint (5, (debugfile, " insufficient abilities: Has %x, want %x\n", 860 k->flags, abilities)); 861 continue; 862 } 863 864 match = 0; /* any match */ 865 866 for (q = k->address; q; q = q->next) 867 { 868 r = rfc822_parse_adrlist (NULL, NONULL (q->addr)); 869 870 for (p = r; p; p = p->next) 871 { 872 int validity = pgp_id_matches_addr (a, p, q); 873 874 if (validity & PGP_KV_MATCH) /* something matches */ 875 match = 1; 876 877 if ((validity & PGP_KV_VALID) 878 && (validity & PGP_KV_ADDR)) 879 { 880 if (validity & PGP_KV_STRONGID) 881 { 882 if (the_strong_valid_key && the_strong_valid_key != k) 883 multi = 1; 884 the_strong_valid_key = k; 885 } 886 else 887 { 888 a_valid_addrmatch_key = k; 889 } 890 } 891 } 892 893 rfc822_free_address (&r); 894 } 895 896 if (match) 897 { 898 *last = pgp_principal_key (k); 899 kn = pgp_remove_key (&keys, *last); 900 last = pgp_get_lastp (k); 901 } 902 } 903 904 pgp_free_key (&keys); 905 906 if (matches) 907 { 908 if (oppenc_mode) 909 { 910 if (the_strong_valid_key) 911 { 912 pgp_remove_key (&matches, the_strong_valid_key); 913 k = the_strong_valid_key; 914 } 915 else if (a_valid_addrmatch_key) 916 { 917 pgp_remove_key (&matches, a_valid_addrmatch_key); 918 k = a_valid_addrmatch_key; 919 } 920 else 921 k = NULL; 922 } 923 else if (the_strong_valid_key && !multi) 924 { 925 /* 926 * There was precisely one strong match on a valid ID. 927 * 928 * Proceed without asking the user. 929 */ 930 pgp_remove_key (&matches, the_strong_valid_key); 931 k = the_strong_valid_key; 932 } 933 else 934 { 935 /* 936 * Else: Ask the user. 937 */ 938 if ((k = pgp_select_key (matches, a, NULL))) 939 pgp_remove_key (&matches, k); 940 } 941 942 pgp_free_key (&matches); 943 944 return k; 945 } 946 947 return NULL; 948} 949 950pgp_key_t pgp_getkeybystr (char *p, short abilities, pgp_ring_t keyring) 951{ 952 LIST *hints = NULL; 953 pgp_key_t keys; 954 pgp_key_t matches = NULL; 955 pgp_key_t *last = &matches; 956 pgp_key_t k, kn; 957 pgp_uid_t *a; 958 short match; 959 size_t l; 960 const char *ps, *pl, *pfcopy, *phint; 961 962 if ((l = mutt_strlen (p)) && p[l-1] == '!') 963 p[l-1] = 0; 964 965 mutt_message (_("Looking for keys matching \"%s\"..."), p); 966 967 pfcopy = crypt_get_fingerprint_or_id (p, &phint, &pl, &ps); 968 hints = pgp_add_string_to_hints (hints, phint); 969 keys = pgp_get_candidates (keyring, hints); 970 mutt_free_list (&hints); 971 972 if (!keys) 973 goto out; 974 975 for (k = keys; k; k = kn) 976 { 977 kn = k->next; 978 if (abilities && !(k->flags & abilities)) 979 continue; 980 981 /* This shouldn't happen, but keys without any addresses aren't selectable 982 * in pgp_select_key(). 983 */ 984 if (!k->address) 985 continue; 986 987 match = 0; 988 989 dprint (5, (debugfile, "pgp_getkeybystr: matching \"%s\" against key %s:\n", 990 p, pgp_long_keyid (k))); 991 992 if (!*p || 993 (pfcopy && mutt_strcasecmp (pfcopy, k->fingerprint) == 0) || 994 (pl && mutt_strcasecmp (pl, pgp_long_keyid (k)) == 0) || 995 (ps && mutt_strcasecmp (ps, pgp_short_keyid (k)) == 0)) 996 { 997 dprint (5, (debugfile, "\t\tmatch.\n")); 998 match = 1; 999 } 1000 else 1001 { 1002 for (a = k->address; a; a = a->next) 1003 { 1004 dprint (5, (debugfile, "pgp_getkeybystr: matching \"%s\" against key %s, \"%s\":\n", 1005 p, pgp_long_keyid (k), NONULL (a->addr))); 1006 if (mutt_stristr (a->addr, p)) 1007 { 1008 dprint (5, (debugfile, "\t\tmatch.\n")); 1009 match = 1; 1010 break; 1011 } 1012 } 1013 } 1014 1015 if (match) 1016 { 1017 *last = pgp_principal_key (k); 1018 kn = pgp_remove_key (&keys, *last); 1019 last = pgp_get_lastp (k); 1020 } 1021 } 1022 1023 pgp_free_key (&keys); 1024 1025 if (matches) 1026 { 1027 if ((k = pgp_select_key (matches, NULL, p))) 1028 pgp_remove_key (&matches, k); 1029 1030 pgp_free_key (&matches); 1031 FREE (&pfcopy); 1032 if (l && !p[l-1]) 1033 p[l-1] = '!'; 1034 return k; 1035 } 1036 1037out: 1038 FREE (&pfcopy); 1039 if (l && !p[l-1]) 1040 p[l-1] = '!'; 1041 return NULL; 1042} 1043 1044#endif /* CRYPT_BACKEND_CLASSIC_PGP */