mutt stable branch with some hacks
at jcs 5528 lines 145 kB view raw
1/* crypt-gpgme.c - GPGME based crypto operations 2 * Copyright (C) 1996-1997,2007 Michael R. Elkins <me@cs.hmc.edu> 3 * Copyright (C) 1998-2000 Thomas Roessler <roessler@does-not-exist.org> 4 * Copyright (C) 2001 Thomas Roessler <roessler@does-not-exist.org> 5 * Oliver Ehli <elmy@acm.org> 6 * Copyright (C) 2002-2004, 2018 g10 Code GmbH 7 * Copyright (C) 2010,2012-2013 Michael R. Elkins <me@sigpipe.org> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 */ 23 24#if HAVE_CONFIG_H 25# include "config.h" 26#endif 27 28#ifdef CRYPT_BACKEND_GPGME 29 30#include "mutt.h" 31#include "mutt_crypt.h" 32#include "mutt_menu.h" 33#include "mutt_curses.h" 34#include "mime.h" 35#include "copy.h" 36#include "pager.h" 37#include "sort.h" 38 39#include <sys/wait.h> 40#include <string.h> 41#include <stdlib.h> 42#include <unistd.h> 43#include <sys/stat.h> 44#include <errno.h> 45#include <ctype.h> 46 47#include <gpgme.h> 48 49#ifdef HAVE_LOCALE_H 50#include <locale.h> 51#endif 52#ifdef HAVE_LANGINFO_D_T_FMT 53#include <langinfo.h> 54#endif 55 56#ifdef HAVE_SYS_TIME_H 57# include <sys/time.h> 58#endif 59 60#ifdef HAVE_SYS_RESOURCE_H 61# include <sys/resource.h> 62#endif 63 64 65/* 66 * Helper macros. 67 */ 68#define digitp(p) (*(p) >= '0' && *(p) <= '9') 69#define hexdigitp(a) (digitp (a) \ 70 || (*(a) >= 'A' && *(a) <= 'F') \ 71 || (*(a) >= 'a' && *(a) <= 'f')) 72#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ 73 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) 74#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) 75 76#define PKA_NOTATION_NAME "pka-address@gnupg.org" 77#define is_pka_notation(notation) ((notation)->name && \ 78 ! strcmp ((notation)->name, \ 79 PKA_NOTATION_NAME)) 80 81/* Values used for comparing addresses. */ 82#define CRYPT_KV_VALID 1 83#define CRYPT_KV_ADDR 2 84#define CRYPT_KV_STRING 4 85#define CRYPT_KV_STRONGID 8 86#define CRYPT_KV_MATCH (CRYPT_KV_ADDR|CRYPT_KV_STRING) 87 88/* 89 * Type definitions. 90 */ 91 92struct crypt_cache 93{ 94 char *what; 95 char *dflt; 96 struct crypt_cache *next; 97}; 98 99struct dn_array_s 100{ 101 char *key; 102 char *value; 103}; 104 105/* We work based on user IDs, getting from a user ID to the key is 106 check and does not need any memory (gpgme uses reference counting). */ 107typedef struct crypt_keyinfo 108{ 109 struct crypt_keyinfo *next; 110 gpgme_key_t kobj; 111 int idx; /* and the user ID at this index */ 112 const char *uid; /* and for convenience point to this user ID */ 113 unsigned int flags; /* global and per uid flags (for convenience)*/ 114 gpgme_validity_t validity; /* uid validity (cached for convenience) */ 115} crypt_key_t; 116 117typedef struct crypt_entry 118{ 119 size_t num; 120 crypt_key_t *key; 121} crypt_entry_t; 122 123 124static struct crypt_cache *id_defaults = NULL; 125static gpgme_key_t signature_key = NULL; 126static char *current_sender = NULL; 127 128 129/* 130 * General helper functions. 131 */ 132 133/* return true when s points to a digit or letter. */ 134static int 135digit_or_letter (const unsigned char *s) 136{ 137 return ( (*s >= '0' && *s < '9') 138 || (*s >= 'A' && *s <= 'Z') 139 || (*s >= 'a' && *s <= 'z')); 140} 141 142/* Print the utf-8 encoded string BUF of length LEN bytes to stream 143 FP. Convert the character set. */ 144static void 145print_utf8 (FILE *fp, const char *buf, size_t len) 146{ 147 char *tstr; 148 149 tstr = safe_malloc (len+1); 150 memcpy (tstr, buf, len); 151 tstr[len] = 0; 152 153 /* fromcode "utf-8" is sure, so we don't want 154 * charset-hook corrections: flags must be 0. 155 */ 156 mutt_convert_string (&tstr, "utf-8", Charset, 0); 157 fputs (tstr, fp); 158 FREE (&tstr); 159} 160 161 162/* Compare function for version strings. The return value is 163 * like strcmp(). LEVEL may be 164 * 0 - reserved 165 * 1 - format is "<major><patchlevel>". 166 * 2 - format is "<major>.<minor><patchlevel>". 167 * 3 - format is "<major>.<minor>.<micro><patchlevel>". 168 * To ignore the patchlevel in the comparison add 10 to LEVEL. To get 169 * a reverse sorting order use a negative number. */ 170#if GPGRT_VERSION_NUMBER >= 0x012100 /* libgpg-error >= 1.33 */ 171static int 172cmp_version_strings (const char *a, const char *b, int level) 173{ 174 return gpgrt_cmp_version (a, b, level); 175} 176#else /* gpgme < 1.33 */ 177/* This function parses the first portion of the version number S and 178 * stores it at NUMBER. On success, this function returns a pointer 179 * into S starting with the first character, which is not part of the 180 * initial number portion; on failure, NULL is returned. */ 181static const char *parse_version_number (const char *s, int *number) 182{ 183 int val = 0; 184 185 if (*s == '0' && digitp (s+1)) 186 return NULL; /* Leading zeros are not allowed. */ 187 for (; digitp (s); s++) 188 { 189 val *= 10; 190 val += *s - '0'; 191 } 192 *number = val; 193 return val < 0 ? NULL : s; 194} 195/* This function breaks up the complete string-representation of the 196 * version number S, which is of the following struture: <major 197 * number>.<minor number>.<micro number><patch level>. The major, 198 * minor and micro number components will be stored in *MAJOR, *MINOR 199 * and *MICRO. If MINOR or MICRO is NULL the version number is 200 * assumed to have just 1 respective 2 parts. 201 * 202 * On success, the last component, the patch level, will be returned; 203 * in failure, NULL will be returned. */ 204static const char *parse_version_string (const char *s, int *major, 205 int *minor, int *micro) 206{ 207 s = parse_version_number (s, major); 208 if (!s) 209 return NULL; 210 if (!minor) 211 { 212 if (*s == '.') 213 s++; 214 } 215 else 216 { 217 if (*s != '.') 218 return NULL; 219 s++; 220 s = parse_version_number (s, minor); 221 if (!s) 222 return NULL; 223 if (!micro) 224 { 225 if (*s == '.') 226 s++; 227 } 228 else 229 { 230 if (*s != '.') 231 return NULL; 232 s++; 233 s = parse_version_number (s, micro); 234 if (!s) 235 return NULL; 236 } 237 } 238 return s; /* patchlevel */ 239} 240/* Substitute for the gpgrt based implementation. 241 * See above for a description. */ 242static int 243cmp_version_strings (const char *a, const char *b, int level) 244{ 245 int a_major, a_minor, a_micro; 246 int b_major, b_minor, b_micro; 247 const char *a_plvl, *b_plvl; 248 int r; 249 int ignore_plvl; 250 int positive, negative; 251 252 if (level < 0) 253 { 254 positive = -1; 255 negative = 1; 256 level = 0 - level; 257 } 258 else 259 { 260 positive = 1; 261 negative = -1; 262 } 263 if ((ignore_plvl = (level > 9))) 264 level %= 10; 265 266 a_major = a_minor = a_micro = 0; 267 a_plvl = parse_version_string (a, &a_major, 268 level > 1? &a_minor : NULL, 269 level > 2? &a_micro : NULL); 270 if (!a_plvl) 271 a_major = a_minor = a_micro = 0; /* Error. */ 272 273 b_major = b_minor = b_micro = 0; 274 b_plvl = parse_version_string (b, &b_major, 275 level > 1? &b_minor : NULL, 276 level > 2? &b_micro : NULL); 277 if (!b_plvl) 278 b_major = b_minor = b_micro = 0; 279 280 if (!ignore_plvl) 281 { 282 if (!a_plvl && !b_plvl) 283 return negative; /* Put invalid strings at the end. */ 284 if (a_plvl && !b_plvl) 285 return positive; 286 if (!a_plvl && b_plvl) 287 return negative; 288 } 289 290 if (a_major > b_major) 291 return positive; 292 if (a_major < b_major) 293 return negative; 294 295 if (a_minor > b_minor) 296 return positive; 297 if (a_minor < b_minor) 298 return negative; 299 300 if (a_micro > b_micro) 301 return positive; 302 if (a_micro < b_micro) 303 return negative; 304 305 if (ignore_plvl) 306 return 0; 307 308 for (; *a_plvl && *b_plvl; a_plvl++, b_plvl++) 309 { 310 if (*a_plvl == '.' && *b_plvl == '.') 311 { 312 r = strcmp (a_plvl, b_plvl); 313 if (!r) 314 return 0; 315 else if ( r > 0 ) 316 return positive; 317 else 318 return negative; 319 } 320 else if (*a_plvl == '.') 321 return negative; /* B is larger. */ 322 else if (*b_plvl == '.') 323 return positive; /* A is larger. */ 324 else if (*a_plvl != *b_plvl) 325 break; 326 } 327 if (*a_plvl == *b_plvl) 328 return 0; 329 else if ((*(signed char *)a_plvl - *(signed char *)b_plvl) > 0) 330 return positive; 331 else 332 return negative; 333} 334#endif /* gpgme < 1.33 */ 335 336 337 338/* 339 * Key management. 340 */ 341 342/* Return the keyID for the key K. Note that this string is valid as 343 long as K is valid */ 344static const char *crypt_keyid (crypt_key_t *k) 345{ 346 const char *s = "????????"; 347 348 if (k->kobj && k->kobj->subkeys) 349 { 350 s = k->kobj->subkeys->keyid; 351 if ((! option (OPTPGPLONGIDS)) && (strlen (s) == 16)) 352 /* Return only the short keyID. */ 353 s += 8; 354 } 355 356 return s; 357} 358 359/* Return the long keyID for the key K. */ 360static const char *crypt_long_keyid (crypt_key_t *k) 361{ 362 const char *s = "????????????????"; 363 364 if (k->kobj && k->kobj->subkeys) 365 { 366 s = k->kobj->subkeys->keyid; 367 } 368 369 return s; 370} 371 372/* Return the short keyID for the key K. */ 373static const char *crypt_short_keyid (crypt_key_t *k) 374{ 375 const char *s = "????????"; 376 377 if (k->kobj && k->kobj->subkeys) 378 { 379 s = k->kobj->subkeys->keyid; 380 if (strlen (s) == 16) 381 s += 8; 382 } 383 384 return s; 385} 386 387/* Return the hexstring fingerprint from the key K. */ 388static const char *crypt_fpr (crypt_key_t *k) 389{ 390 const char *s = ""; 391 392 if (k->kobj && k->kobj->subkeys) 393 s = k->kobj->subkeys->fpr; 394 395 return s; 396} 397 398/* Returns the fingerprint if available, otherwise 399 * returns the long keyid. 400 */ 401static const char *crypt_fpr_or_lkeyid(crypt_key_t *k) 402{ 403 const char *s = "????????????????"; 404 405 if (k->kobj && k->kobj->subkeys) 406 { 407 if (k->kobj->subkeys->fpr) 408 s = k->kobj->subkeys->fpr; 409 else 410 s = k->kobj->subkeys->keyid; 411 } 412 413 return s; 414} 415 416/* Parse FLAGS and return a statically allocated(!) string with them. */ 417static char *crypt_key_abilities (int flags) 418{ 419 static char buff[3]; 420 421 if (!(flags & KEYFLAG_CANENCRYPT)) 422 buff[0] = '-'; 423 else if (flags & KEYFLAG_PREFER_SIGNING) 424 buff[0] = '.'; 425 else 426 buff[0] = 'e'; 427 428 if (!(flags & KEYFLAG_CANSIGN)) 429 buff[1] = '-'; 430 else if (flags & KEYFLAG_PREFER_ENCRYPTION) 431 buff[1] = '.'; 432 else 433 buff[1] = 's'; 434 435 buff[2] = '\0'; 436 437 return buff; 438} 439 440/* Parse FLAGS and return a character describing the most important flag. */ 441static char crypt_flags (int flags) 442{ 443 if (flags & KEYFLAG_REVOKED) 444 return 'R'; 445 else if (flags & KEYFLAG_EXPIRED) 446 return 'X'; 447 else if (flags & KEYFLAG_DISABLED) 448 return 'd'; 449 else if (flags & KEYFLAG_CRITICAL) 450 return 'c'; 451 else 452 return ' '; 453} 454 455/* Return a copy of KEY. */ 456static crypt_key_t *crypt_copy_key (crypt_key_t *key) 457{ 458 crypt_key_t *k; 459 460 k = safe_calloc (1, sizeof *k); 461 k->kobj = key->kobj; 462 gpgme_key_ref (key->kobj); 463 k->idx = key->idx; 464 k->uid = key->uid; 465 k->flags = key->flags; 466 k->validity = key->validity; 467 468 return k; 469} 470 471/* Release all the keys at the address of KEYLIST and set the address 472 to NULL. */ 473static void crypt_free_key (crypt_key_t **keylist) 474{ 475 crypt_key_t *k; 476 477 if (!keylist) 478 return; 479 480 while (*keylist) 481 { 482 k = *keylist; 483 *keylist = (*keylist)->next; 484 485 gpgme_key_unref (k->kobj); 486 FREE (&k); 487 } 488} 489 490/* Return trute when key K is valid. */ 491static int crypt_key_is_valid (crypt_key_t *k) 492{ 493 if (k->flags & KEYFLAG_CANTUSE) 494 return 0; 495 return 1; 496} 497 498/* Return true whe validity of KEY is sufficient. */ 499static int crypt_id_is_strong (crypt_key_t *key) 500{ 501 unsigned int is_strong = 0; 502 503 if ((key->flags & KEYFLAG_ISX509)) 504 return 1; 505 506 switch (key->validity) 507 { 508 case GPGME_VALIDITY_UNKNOWN: 509 case GPGME_VALIDITY_UNDEFINED: 510 case GPGME_VALIDITY_NEVER: 511 case GPGME_VALIDITY_MARGINAL: 512 is_strong = 0; 513 break; 514 515 case GPGME_VALIDITY_FULL: 516 case GPGME_VALIDITY_ULTIMATE: 517 is_strong = 1; 518 break; 519 } 520 521 return is_strong; 522} 523 524/* Return true when the KEY is valid, i.e. not marked as unusable. */ 525static int crypt_id_is_valid (crypt_key_t *key) 526{ 527 return ! (key->flags & KEYFLAG_CANTUSE); 528} 529 530/* Return a bit vector describing how well the addresses ADDR and 531 U_ADDR match and whether KEY is valid. */ 532static int crypt_id_matches_addr (ADDRESS *addr, ADDRESS *u_addr, 533 crypt_key_t *key) 534{ 535 int rv = 0; 536 537 if (crypt_id_is_valid (key)) 538 rv |= CRYPT_KV_VALID; 539 540 if (crypt_id_is_strong (key)) 541 rv |= CRYPT_KV_STRONGID; 542 543 if (addr->mailbox && u_addr->mailbox 544 && mutt_strcasecmp (addr->mailbox, u_addr->mailbox) == 0) 545 rv |= CRYPT_KV_ADDR; 546 547 if (addr->personal && u_addr->personal 548 && mutt_strcasecmp (addr->personal, u_addr->personal) == 0) 549 rv |= CRYPT_KV_STRING; 550 551 return rv; 552} 553 554 555/* 556 * GPGME convenient functions. 557 */ 558 559/* Create a new gpgme context and return it. With FOR_SMIME set to 560 true, the protocol of the context is set to CMS. */ 561static gpgme_ctx_t create_gpgme_context (int for_smime) 562{ 563 gpgme_error_t err; 564 gpgme_ctx_t ctx; 565 566 err = gpgme_new (&ctx); 567 568#ifdef USE_AUTOCRYPT 569 if (!err && option (OPTAUTOCRYPTGPGME)) 570 err = gpgme_ctx_set_engine_info (ctx, GPGME_PROTOCOL_OpenPGP, NULL, 571 AutocryptDir); 572#endif 573 574 if (err) 575 { 576 mutt_error (_("error creating gpgme context: %s\n"), gpgme_strerror (err)); 577 sleep (2); 578 mutt_exit (1); 579 } 580 581 if (for_smime) 582 { 583 err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); 584 if (err) 585 { 586 mutt_error (_("error enabling CMS protocol: %s\n"), 587 gpgme_strerror (err)); 588 sleep (2); 589 mutt_exit (1); 590 } 591 } 592 593 return ctx; 594} 595 596 597/* Create a new gpgme data object. This is a wrapper to die on 598 error. */ 599static gpgme_data_t create_gpgme_data (void) 600{ 601 gpgme_error_t err; 602 gpgme_data_t data; 603 604 err = gpgme_data_new (&data); 605 if (err) 606 { 607 mutt_error (_("error creating gpgme data object: %s\n"), 608 gpgme_strerror (err)); 609 sleep (2); 610 mutt_exit (1); 611 } 612 return data; 613} 614 615 616/* Return true if the OpenPGP engine's version is at least VERSION. */ 617static int have_gpg_version (const char *version) 618{ 619 static char *engine_version; 620 621 if (!engine_version) 622 { 623 gpgme_ctx_t ctx; 624 gpgme_engine_info_t engineinfo; 625 626 ctx = create_gpgme_context (0); 627 engineinfo = gpgme_ctx_get_engine_info (ctx); 628 while (engineinfo && engineinfo->protocol != GPGME_PROTOCOL_OpenPGP) 629 engineinfo = engineinfo->next; 630 if (!engineinfo) 631 { 632 dprint (1, (debugfile, "Error finding GPGME PGP engine\n")); 633 engine_version = safe_strdup ("0.0.0"); 634 } 635 else 636 engine_version = safe_strdup (engineinfo->version); 637 gpgme_release (ctx); 638 } 639 640 return cmp_version_strings (engine_version, version, 3) >= 0; 641} 642 643 644/* Create a new GPGME Data object from the mail body A. With CONVERT 645 passed as true, the lines are converted to CR,LF if required. 646 Return NULL on error or the gpgme_data_t object on success. */ 647static gpgme_data_t body_to_data_object (BODY *a, int convert) 648{ 649 BUFFER *tempfile = NULL; 650 FILE *fptmp; 651 int err; 652 gpgme_data_t data = NULL; 653 654 tempfile = mutt_buffer_pool_get (); 655 mutt_buffer_mktemp (tempfile); 656 fptmp = safe_fopen (mutt_b2s (tempfile), "w+"); 657 if (!fptmp) 658 { 659 mutt_perror (mutt_b2s (tempfile)); 660 goto cleanup; 661 } 662 663 mutt_write_mime_header (a, fptmp); 664 fputc ('\n', fptmp); 665 mutt_write_mime_body (a, fptmp); 666 667 if (convert) 668 { 669 int c, hadcr = 0; 670 unsigned char buf[1]; 671 672 data = create_gpgme_data (); 673 rewind (fptmp); 674 while ((c = fgetc (fptmp)) != EOF) 675 { 676 if (c == '\r') 677 hadcr = 1; 678 else 679 { 680 if (c == '\n' && !hadcr) 681 { 682 buf[0] = '\r'; 683 gpgme_data_write (data, buf, 1); 684 } 685 686 hadcr = 0; 687 } 688 /* FIXME: This is quite suboptimal */ 689 buf[0] = c; 690 gpgme_data_write (data, buf, 1); 691 } 692 safe_fclose (&fptmp); 693 gpgme_data_seek (data, 0, SEEK_SET); 694 } 695 else 696 { 697 safe_fclose (&fptmp); 698 err = gpgme_data_new_from_file (&data, mutt_b2s (tempfile), 1); 699 if (err) 700 { 701 mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err)); 702 gpgme_data_release (data); 703 data = NULL; 704 /* fall through to unlink the tempfile */ 705 } 706 } 707 unlink (mutt_b2s (tempfile)); 708 709cleanup: 710 mutt_buffer_pool_release (&tempfile); 711 return data; 712} 713 714/* Create a GPGME data object from the stream FP but limit the object 715 to LENGTH bytes starting at OFFSET bytes from the beginning of the 716 file. */ 717static gpgme_data_t file_to_data_object (FILE *fp, long offset, long length) 718{ 719 int err = 0; 720 gpgme_data_t data; 721 722 err = gpgme_data_new_from_filepart (&data, NULL, fp, offset, length); 723 if (err) 724 { 725 mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err)); 726 return NULL; 727 } 728 729 return data; 730} 731 732/* Write a GPGME data object to the stream FP. */ 733static int data_object_to_stream (gpgme_data_t data, FILE *fp) 734{ 735 int err; 736 char buf[4096], *p; 737 ssize_t nread; 738 739 err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1) 740 ? gpgme_error_from_errno (errno) : 0); 741 if (err) 742 { 743 mutt_error (_("error rewinding data object: %s\n"), gpgme_strerror (err)); 744 return -1; 745 } 746 747 while ((nread = gpgme_data_read (data, buf, sizeof (buf)))) 748 { 749 /* fixme: we are not really converting CRLF to LF but just 750 skipping CR. Doing it correctly needs a more complex logic */ 751 for (p=buf; nread; p++, nread--) 752 { 753 if (*p != '\r') 754 putc (*p, fp); 755 } 756 757 if (ferror (fp)) 758 { 759 mutt_perror ("[tempfile]"); 760 return -1; 761 } 762 } 763 if (nread == -1) 764 { 765 mutt_error (_("error reading data object: %s\n"), strerror (errno)); 766 return -1; 767 } 768 return 0; 769} 770 771/* Copy a data object to a temporary file. 772 * The tempfile name may be optionally passed in. 773 * If ret_fp is passed in, the file will be rewound, left open, and returned 774 * via that parameter. 775 * The tempfile name is returned, and must be freed. 776 */ 777static char *data_object_to_tempfile (gpgme_data_t data, const char *tempf, FILE **ret_fp) 778{ 779 int err; 780 BUFFER *tempfb = NULL; 781 char *rv = NULL; 782 FILE *fp; 783 size_t nread = 0; 784 785 if (!tempf) 786 { 787 tempfb = mutt_buffer_pool_get (); 788 mutt_buffer_mktemp (tempfb); 789 tempf = mutt_b2s (tempfb); 790 } 791 if ((fp = safe_fopen (tempf, tempf == mutt_b2s (tempfb) ? "w+" : "a+")) == NULL) 792 { 793 mutt_perror _("Can't create temporary file"); 794 goto cleanup; 795 } 796 797 err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1) 798 ? gpgme_error_from_errno (errno) : 0); 799 if (!err) 800 { 801 char buf[4096]; 802 803 while ((nread = gpgme_data_read (data, buf, sizeof (buf)))) 804 { 805 if (fwrite (buf, nread, 1, fp) != 1) 806 { 807 mutt_perror (tempf); 808 safe_fclose (&fp); 809 unlink (tempf); 810 goto cleanup; 811 } 812 } 813 } 814 if (ret_fp) 815 rewind (fp); 816 else 817 safe_fclose (&fp); 818 if (nread == -1) 819 { 820 mutt_error (_("error reading data object: %s\n"), gpgme_strerror (err)); 821 unlink (tempf); 822 safe_fclose (&fp); 823 goto cleanup; 824 } 825 if (ret_fp) 826 *ret_fp = fp; 827 rv = safe_strdup (tempf); 828 829cleanup: 830 mutt_buffer_pool_release (&tempfb); 831 return rv; 832} 833 834 835#if GPGME_VERSION_NUMBER >= 0x010b00 /* gpgme >= 1.11.0 */ 836 837static void create_recipient_string (const char *keylist, BUFFER *recpstring, 838 int use_smime) 839{ 840 const char *s; 841 unsigned int n = 0; 842 843 s = keylist; 844 do 845 { 846 while (*s == ' ') 847 s++; 848 if (*s) 849 { 850 if (!n) 851 { 852 if (!use_smime) 853 mutt_buffer_addstr (recpstring, "--\n"); 854 } 855 else 856 mutt_buffer_addch (recpstring, '\n'); 857 n++; 858 859 while (*s && *s != ' ') 860 mutt_buffer_addch (recpstring, *s++); 861 } 862 } while (*s); 863} 864 865#else 866 867static void free_recipient_set (gpgme_key_t **p_rset) 868{ 869 gpgme_key_t *rset, k; 870 871 if (!p_rset) 872 return; 873 874 rset = *p_rset; 875 if (!rset) 876 return; 877 878 while (*rset) 879 { 880 k = *rset; 881 gpgme_key_unref (k); 882 rset++; 883 } 884 885 FREE (p_rset); /* __FREE_CHECKED__ */ 886} 887 888 889/* Create a GpgmeRecipientSet from the keys in the string KEYLIST. 890 The keys must be space delimited. */ 891static gpgme_key_t *create_recipient_set (const char *keylist, int use_smime) 892{ 893 int err; 894 const char *s; 895 char buf[100]; 896 int i; 897 gpgme_key_t *rset = NULL; 898 unsigned int rset_n = 0; 899 gpgme_key_t key = NULL; 900 gpgme_ctx_t context = NULL; 901 902 context = create_gpgme_context (use_smime); 903 s = keylist; 904 do 905 { 906 while (*s == ' ') 907 s++; 908 for (i=0; *s && *s != ' ' && i < sizeof(buf)-1;) 909 buf[i++] = *s++; 910 buf[i] = 0; 911 if (*buf) 912 { 913 if (i>1 && buf[i-1] == '!') 914 { 915 /* The user selected to override the validity of that 916 key. */ 917 buf[i-1] = 0; 918 919 err = gpgme_get_key (context, buf, &key, 0); 920 if (! err) 921 key->uids->validity = GPGME_VALIDITY_FULL; 922 buf[i-1] = '!'; 923 } 924 else 925 err = gpgme_get_key (context, buf, &key, 0); 926 927 safe_realloc (&rset, sizeof (*rset) * (rset_n + 1)); 928 if (! err) 929 rset[rset_n++] = key; 930 else 931 { 932 mutt_error (_("error adding recipient `%s': %s\n"), 933 buf, gpgme_strerror (err)); 934 rset[rset_n] = NULL; 935 free_recipient_set (&rset); 936 gpgme_release (context); 937 return NULL; 938 } 939 } 940 } while (*s); 941 942 /* NULL terminate. */ 943 safe_realloc (&rset, sizeof (*rset) * (rset_n + 1)); 944 rset[rset_n++] = NULL; 945 946 gpgme_release (context); 947 948 return rset; 949} 950 951#endif /* GPGME_VERSION_NUMBER >= 0x010b00 */ 952 953 954/* Make sure that the correct signer is set. Returns 0 on success. */ 955static int set_signer (gpgme_ctx_t ctx, int for_smime) 956{ 957 char *signid; 958 gpgme_error_t err; 959 gpgme_ctx_t listctx; 960 gpgme_key_t key, key2; 961 char *fpr, *fpr2; 962 963 if (for_smime) 964 signid = SmimeSignAs ? SmimeSignAs : SmimeDefaultKey; 965#ifdef USE_AUTOCRYPT 966 else if (option (OPTAUTOCRYPTGPGME)) 967 signid = AutocryptSignAs; 968#endif 969 else 970 signid = PgpSignAs ? PgpSignAs : PgpDefaultKey; 971 972 if (!signid) 973 return 0; 974 975 listctx = create_gpgme_context (for_smime); 976 err = gpgme_op_keylist_start (listctx, signid, 1); 977 if (!err) 978 err = gpgme_op_keylist_next (listctx, &key); 979 if (err) 980 { 981 gpgme_release (listctx); 982 mutt_error (_("secret key `%s' not found: %s\n"), 983 signid, gpgme_strerror (err)); 984 return -1; 985 } 986 fpr = "fpr1"; 987 if (key->subkeys) 988 fpr = key->subkeys->fpr ? key->subkeys->fpr : key->subkeys->keyid; 989 while (! gpgme_op_keylist_next (listctx, &key2)) 990 { 991 fpr2 = "fpr2"; 992 if (key2->subkeys) 993 fpr2 = key2->subkeys->fpr ? key2->subkeys->fpr : key2->subkeys->keyid; 994 if (mutt_strcmp(fpr, fpr2)) 995 { 996 gpgme_key_unref (key); 997 gpgme_key_unref (key2); 998 gpgme_release (listctx); 999 mutt_error (_("ambiguous specification of secret key `%s'\n"), 1000 signid); 1001 return -1; 1002 } else { 1003 gpgme_key_unref (key2); 1004 } 1005 } 1006 gpgme_op_keylist_end (listctx); 1007 gpgme_release (listctx); 1008 1009 gpgme_signers_clear (ctx); 1010 err = gpgme_signers_add (ctx, key); 1011 gpgme_key_unref (key); 1012 if (err) 1013 { 1014 mutt_error (_("error setting secret key `%s': %s\n"), 1015 signid, gpgme_strerror (err)); 1016 return -1; 1017 } 1018 return 0; 1019} 1020 1021static gpgme_error_t 1022set_pka_sig_notation (gpgme_ctx_t ctx) 1023{ 1024 gpgme_error_t err; 1025 1026 err = gpgme_sig_notation_add (ctx, 1027 PKA_NOTATION_NAME, current_sender, 0); 1028 1029 if (err) 1030 { 1031 mutt_error (_("error setting PKA signature notation: %s\n"), 1032 gpgme_strerror (err)); 1033 mutt_sleep (2); 1034 } 1035 1036 return err; 1037} 1038 1039/* Encrypt the gpgme data object PLAINTEXT to the recipients in RSET 1040 and return an allocated filename to a temporary file containing the 1041 enciphered text. With USE_SMIME set to true, the smime backend is 1042 used. With COMBINED_SIGNED a PGP message is signed and 1043 encrypted. Returns NULL in case of error */ 1044static char *encrypt_gpgme_object (gpgme_data_t plaintext, char *keylist, 1045 int use_smime, int combined_signed) 1046{ 1047 gpgme_error_t err; 1048 gpgme_ctx_t ctx; 1049 gpgme_data_t ciphertext; 1050 char *outfile = NULL; 1051 1052#if GPGME_VERSION_NUMBER >= 0x010b00 /* gpgme >= 1.11.0 */ 1053 BUFFER *recpstring = mutt_buffer_pool_get (); 1054 create_recipient_string (keylist, recpstring, use_smime); 1055 if (mutt_buffer_len (recpstring) == 0) 1056 { 1057 mutt_buffer_pool_release (&recpstring); 1058 return NULL; 1059 } 1060#else 1061 gpgme_key_t *rset = create_recipient_set (keylist, use_smime); 1062 if (!rset) 1063 return NULL; 1064#endif /* GPGME_VERSION_NUMBER >= 0x010b00 */ 1065 1066 ctx = create_gpgme_context (use_smime); 1067 if (!use_smime) 1068 gpgme_set_armor (ctx, 1); 1069 1070 ciphertext = create_gpgme_data (); 1071 1072 if (combined_signed) 1073 { 1074 if (set_signer (ctx, use_smime)) 1075 goto cleanup; 1076 1077 if (option (OPTCRYPTUSEPKA)) 1078 { 1079 err = set_pka_sig_notation (ctx); 1080 if (err) 1081 goto cleanup; 1082 } 1083 1084#if GPGME_VERSION_NUMBER >= 0x010b00 /* gpgme >= 1.11.0 */ 1085 err = gpgme_op_encrypt_sign_ext (ctx, NULL, mutt_b2s (recpstring), 1086 GPGME_ENCRYPT_ALWAYS_TRUST, 1087 plaintext, ciphertext); 1088#else 1089 err = gpgme_op_encrypt_sign (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST, 1090 plaintext, ciphertext); 1091#endif 1092 } 1093 else 1094 { 1095#if GPGME_VERSION_NUMBER >= 0x010b00 /* gpgme >= 1.11.0 */ 1096 err = gpgme_op_encrypt_ext (ctx, NULL, mutt_b2s (recpstring), 1097 GPGME_ENCRYPT_ALWAYS_TRUST, 1098 plaintext, ciphertext); 1099#else 1100 err = gpgme_op_encrypt (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST, 1101 plaintext, ciphertext); 1102#endif 1103 } 1104 1105 mutt_need_hard_redraw (); 1106 if (err) 1107 { 1108 mutt_error (_("error encrypting data: %s\n"), gpgme_strerror (err)); 1109 goto cleanup; 1110 } 1111 1112 outfile = data_object_to_tempfile (ciphertext, NULL, NULL); 1113 1114cleanup: 1115#if GPGME_VERSION_NUMBER >= 0x010b00 /* gpgme >= 1.11.0 */ 1116 mutt_buffer_pool_release (&recpstring); 1117#else 1118 free_recipient_set (&rset); 1119#endif 1120 gpgme_release (ctx); 1121 gpgme_data_release (ciphertext); 1122 return outfile; 1123} 1124 1125/* Find the "micalg" parameter from the last Gpgme operation on 1126 context CTX. It is expected that this operation was a sign 1127 operation. Return the algorithm name as a C string in buffer BUF 1128 which must have been allocated by the caller with size BUFLEN. 1129 Returns 0 on success or -1 in case of an error. The return string 1130 is truncted to BUFLEN - 1. */ 1131static int get_micalg (gpgme_ctx_t ctx, int use_smime, char *buf, size_t buflen) 1132{ 1133 gpgme_sign_result_t result = NULL; 1134 const char *algorithm_name = NULL; 1135 1136 if (buflen < 5) 1137 return -1; 1138 1139 *buf = 0; 1140 result = gpgme_op_sign_result (ctx); 1141 if (result && result->signatures) 1142 { 1143 algorithm_name = gpgme_hash_algo_name (result->signatures->hash_algo); 1144 if (algorithm_name) 1145 { 1146 if (use_smime) 1147 { 1148 /* convert GPGME raw hash name to RFC 2633 format */ 1149 snprintf (buf, buflen, "%s", algorithm_name); 1150 ascii_strlower (buf); 1151 } 1152 else 1153 { 1154 /* convert GPGME raw hash name to RFC 3156 format */ 1155 snprintf (buf, buflen, "pgp-%s", algorithm_name); 1156 ascii_strlower (buf + 4); 1157 } 1158 } 1159 } 1160 1161 return *buf? 0:-1; 1162} 1163 1164static void print_time(time_t t, STATE *s) 1165{ 1166 char p[STRING]; 1167 1168#ifdef HAVE_LANGINFO_D_T_FMT 1169 strftime (p, sizeof (p), nl_langinfo (D_T_FMT), localtime (&t)); 1170#else 1171 strftime (p, sizeof (p), "%c", localtime (&t)); 1172#endif 1173 state_puts (p, s); 1174} 1175 1176/* 1177 * Implementation of `sign_message'. 1178 */ 1179 1180/* Sign the MESSAGE in body A either using OpenPGP or S/MIME when 1181 USE_SMIME is passed as true. Returns the new body or NULL on 1182 error. */ 1183static BODY *sign_message (BODY *a, int use_smime) 1184{ 1185 BODY *t; 1186 char *sigfile; 1187 int err = 0; 1188 char buf[100]; 1189 gpgme_ctx_t ctx; 1190 gpgme_data_t message, signature; 1191 gpgme_sign_result_t sigres; 1192 1193 convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */ 1194 1195 message = body_to_data_object (a, 1); 1196 if (!message) 1197 return NULL; 1198 signature = create_gpgme_data (); 1199 1200 ctx = create_gpgme_context (use_smime); 1201 if (!use_smime) 1202 gpgme_set_armor (ctx, 1); 1203 1204 if (set_signer (ctx, use_smime)) 1205 { 1206 gpgme_data_release (signature); 1207 gpgme_data_release (message); 1208 gpgme_release (ctx); 1209 return NULL; 1210 } 1211 1212 if (option (OPTCRYPTUSEPKA)) 1213 { 1214 err = set_pka_sig_notation (ctx); 1215 if (err) 1216 { 1217 gpgme_data_release (signature); 1218 gpgme_data_release (message); 1219 gpgme_release (ctx); 1220 return NULL; 1221 } 1222 } 1223 1224 err = gpgme_op_sign (ctx, message, signature, GPGME_SIG_MODE_DETACH ); 1225 mutt_need_hard_redraw (); 1226 gpgme_data_release (message); 1227 if (err) 1228 { 1229 gpgme_data_release (signature); 1230 gpgme_release (ctx); 1231 mutt_error (_("error signing data: %s\n"), gpgme_strerror (err)); 1232 return NULL; 1233 } 1234 /* Check for zero signatures generated. This can occur when $pgp_sign_as is 1235 * unset and there is no default key specified in ~/.gnupg/gpg.conf 1236 */ 1237 sigres = gpgme_op_sign_result (ctx); 1238 if (!sigres->signatures) 1239 { 1240 gpgme_data_release (signature); 1241 gpgme_release (ctx); 1242 mutt_error (_("$pgp_sign_as unset and no default key specified in ~/.gnupg/gpg.conf")); 1243 return NULL; 1244 } 1245 1246 sigfile = data_object_to_tempfile (signature, NULL, NULL); 1247 gpgme_data_release (signature); 1248 if (!sigfile) 1249 { 1250 gpgme_release (ctx); 1251 return NULL; 1252 } 1253 1254 t = mutt_new_body (); 1255 t->type = TYPEMULTIPART; 1256 t->subtype = safe_strdup ("signed"); 1257 t->encoding = ENC7BIT; 1258 t->use_disp = 0; 1259 t->disposition = DISPINLINE; 1260 1261 mutt_generate_boundary (&t->parameter); 1262 mutt_set_parameter ("protocol", 1263 use_smime? "application/pkcs7-signature" 1264 : "application/pgp-signature", 1265 &t->parameter); 1266 /* Get the micalg from gpgme. Old gpgme versions don't support this 1267 for S/MIME so we assume sha-1 in this case. */ 1268 if (!get_micalg (ctx, use_smime, buf, sizeof buf)) 1269 mutt_set_parameter ("micalg", buf, &t->parameter); 1270 else if (use_smime) 1271 mutt_set_parameter ("micalg", "sha1", &t->parameter); 1272 gpgme_release (ctx); 1273 1274 t->parts = a; 1275 a = t; 1276 1277 t->parts->next = mutt_new_body (); 1278 t = t->parts->next; 1279 t->type = TYPEAPPLICATION; 1280 if (use_smime) 1281 { 1282 t->subtype = safe_strdup ("pkcs7-signature"); 1283 mutt_set_parameter ("name", "smime.p7s", &t->parameter); 1284 t->encoding = ENCBASE64; 1285 t->use_disp = 1; 1286 t->disposition = DISPATTACH; 1287 t->d_filename = safe_strdup ("smime.p7s"); 1288 } 1289 else 1290 { 1291 t->subtype = safe_strdup ("pgp-signature"); 1292 mutt_set_parameter ("name", "signature.asc", &t->parameter); 1293 t->use_disp = 0; 1294 t->disposition = DISPNONE; 1295 t->encoding = ENC7BIT; 1296 } 1297 t->filename = sigfile; 1298 t->unlink = 1; /* ok to remove this file after sending. */ 1299 1300 return a; 1301} 1302 1303 1304BODY *pgp_gpgme_sign_message (BODY *a) 1305{ 1306 return sign_message (a, 0); 1307} 1308 1309BODY *smime_gpgme_sign_message (BODY *a) 1310{ 1311 return sign_message (a, 1); 1312} 1313 1314/* 1315 * Implementation of `encrypt_message'. 1316 */ 1317 1318/* Encrypt the mail body A to all keys given as space separated keyids 1319 or fingerprints in KEYLIST and return the encrypted body. */ 1320BODY *pgp_gpgme_encrypt_message (BODY *a, char *keylist, int sign) 1321{ 1322 char *outfile = NULL; 1323 BODY *t; 1324 gpgme_data_t plaintext; 1325 1326 if (sign) 1327 convert_to_7bit (a); 1328 plaintext = body_to_data_object (a, 0); 1329 if (!plaintext) 1330 return NULL; 1331 1332 outfile = encrypt_gpgme_object (plaintext, keylist, 0, sign); 1333 gpgme_data_release (plaintext); 1334 if (!outfile) 1335 return NULL; 1336 1337 t = mutt_new_body (); 1338 t->type = TYPEMULTIPART; 1339 t->subtype = safe_strdup ("encrypted"); 1340 t->encoding = ENC7BIT; 1341 t->use_disp = 0; 1342 t->disposition = DISPINLINE; 1343 1344 mutt_generate_boundary(&t->parameter); 1345 mutt_set_parameter("protocol", "application/pgp-encrypted", &t->parameter); 1346 1347 t->parts = mutt_new_body (); 1348 t->parts->type = TYPEAPPLICATION; 1349 t->parts->subtype = safe_strdup ("pgp-encrypted"); 1350 t->parts->encoding = ENC7BIT; 1351 1352 t->parts->next = mutt_new_body (); 1353 t->parts->next->type = TYPEAPPLICATION; 1354 t->parts->next->subtype = safe_strdup ("octet-stream"); 1355 t->parts->next->encoding = ENC7BIT; 1356 t->parts->next->filename = outfile; 1357 t->parts->next->use_disp = 1; 1358 t->parts->next->disposition = DISPATTACH; 1359 t->parts->next->unlink = 1; /* delete after sending the message */ 1360 t->parts->next->d_filename = safe_strdup ("msg.asc"); /* non pgp/mime 1361 can save */ 1362 1363 return t; 1364} 1365 1366/* 1367 * Implementation of `smime_build_smime_entity'. 1368 */ 1369 1370/* Encrypt the mail body A to all keys given as space separated 1371 fingerprints in KEYLIST and return the S/MIME encrypted body. */ 1372BODY *smime_gpgme_build_smime_entity (BODY *a, char *keylist) 1373{ 1374 char *outfile = NULL; 1375 BODY *t; 1376 gpgme_data_t plaintext; 1377 1378 /* OpenSSL converts line endings to crlf when encrypting. Some 1379 * clients depend on this for signed+encrypted messages: they do not 1380 * convert line endings between decrypting and checking the 1381 * signature. See #3904. */ 1382 plaintext = body_to_data_object (a, 1); 1383 if (!plaintext) 1384 return NULL; 1385 1386 outfile = encrypt_gpgme_object (plaintext, keylist, 1, 0); 1387 gpgme_data_release (plaintext); 1388 if (!outfile) 1389 return NULL; 1390 1391 t = mutt_new_body (); 1392 t->type = TYPEAPPLICATION; 1393 t->subtype = safe_strdup ("pkcs7-mime"); 1394 mutt_set_parameter ("name", "smime.p7m", &t->parameter); 1395 mutt_set_parameter ("smime-type", "enveloped-data", &t->parameter); 1396 t->encoding = ENCBASE64; /* The output of OpenSSL SHOULD be binary */ 1397 t->use_disp = 1; 1398 t->disposition = DISPATTACH; 1399 t->d_filename = safe_strdup ("smime.p7m"); 1400 t->filename = outfile; 1401 t->unlink = 1; /*delete after sending the message */ 1402 t->parts=0; 1403 t->next=0; 1404 1405 return t; 1406} 1407 1408 1409/* 1410 * Implementation of `verify_one'. 1411 */ 1412 1413/* Display the common attributes of the signature summary SUM. 1414 Return 1 if there is is a severe warning. 1415 */ 1416static int show_sig_summary (unsigned long sum, 1417 gpgme_ctx_t ctx, gpgme_key_t key, int idx, 1418 STATE *s, gpgme_signature_t sig) 1419{ 1420 int severe = 0; 1421 1422 if ((sum & GPGME_SIGSUM_KEY_REVOKED)) 1423 { 1424 state_puts (_("Warning: One of the keys has been revoked\n"),s); 1425 severe = 1; 1426 } 1427 1428 if ((sum & GPGME_SIGSUM_KEY_EXPIRED)) 1429 { 1430 time_t at = key->subkeys->expires ? key->subkeys->expires : 0; 1431 if (at) 1432 { 1433 state_puts (_("Warning: The key used to create the " 1434 "signature expired at: "), s); 1435 print_time (at , s); 1436 state_puts ("\n", s); 1437 } 1438 else 1439 state_puts (_("Warning: At least one certification key " 1440 "has expired\n"), s); 1441 } 1442 1443 if ((sum & GPGME_SIGSUM_SIG_EXPIRED)) 1444 { 1445 gpgme_verify_result_t result; 1446 gpgme_signature_t sig; 1447 unsigned int i; 1448 1449 result = gpgme_op_verify_result (ctx); 1450 1451 for (sig = result->signatures, i = 0; sig && (i < idx); 1452 sig = sig->next, i++) 1453 ; 1454 1455 state_puts (_("Warning: The signature expired at: "), s); 1456 print_time (sig ? sig->exp_timestamp : 0, s); 1457 state_puts ("\n", s); 1458 } 1459 1460 if ((sum & GPGME_SIGSUM_KEY_MISSING)) 1461 state_puts (_("Can't verify due to a missing " 1462 "key or certificate\n"), s); 1463 1464 if ((sum & GPGME_SIGSUM_CRL_MISSING)) 1465 { 1466 state_puts (_("The CRL is not available\n"), s); 1467 severe = 1; 1468 } 1469 1470 if ((sum & GPGME_SIGSUM_CRL_TOO_OLD)) 1471 { 1472 state_puts (_("Available CRL is too old\n"), s); 1473 severe = 1; 1474 } 1475 1476 if ((sum & GPGME_SIGSUM_BAD_POLICY)) 1477 state_puts (_("A policy requirement was not met\n"), s); 1478 1479 if ((sum & GPGME_SIGSUM_SYS_ERROR)) 1480 { 1481 const char *t0 = NULL, *t1 = NULL; 1482 gpgme_verify_result_t result; 1483 gpgme_signature_t sig; 1484 unsigned int i; 1485 1486 state_puts (_("A system error occurred"), s ); 1487 1488 /* Try to figure out some more detailed system error information. */ 1489 result = gpgme_op_verify_result (ctx); 1490 for (sig = result->signatures, i = 0; sig && (i < idx); 1491 sig = sig->next, i++) 1492 ; 1493 if (sig) 1494 { 1495 t0 = ""; 1496 t1 = sig->wrong_key_usage ? "Wrong_Key_Usage" : ""; 1497 } 1498 1499 if (t0 || t1) 1500 { 1501 state_puts (": ", s); 1502 if (t0) 1503 state_puts (t0, s); 1504 if (t1 && !(t0 && !strcmp (t0, t1))) 1505 { 1506 if (t0) 1507 state_puts (",", s); 1508 state_puts (t1, s); 1509 } 1510 } 1511 state_puts ("\n", s); 1512 } 1513 1514 if (option (OPTCRYPTUSEPKA)) 1515 { 1516 if (sig->pka_trust == 1 && sig->pka_address) 1517 { 1518 state_puts (_("WARNING: PKA entry does not match " 1519 "signer's address: "), s); 1520 state_puts (sig->pka_address, s); 1521 state_puts ("\n", s); 1522 } 1523 else if (sig->pka_trust == 2 && sig->pka_address) 1524 { 1525 state_puts (_("PKA verified signer's address is: "), s); 1526 state_puts (sig->pka_address, s); 1527 state_puts ("\n", s); 1528 } 1529 } 1530 1531 return severe; 1532} 1533 1534 1535static void show_fingerprint (gpgme_key_t key, STATE *state) 1536{ 1537 const char *s; 1538 int i, is_pgp; 1539 char *buf, *p; 1540 const char *prefix = _("Fingerprint: "); 1541 1542 if (!key) 1543 return; 1544 s = key->subkeys ? key->subkeys->fpr : NULL; 1545 if (!s) 1546 return; 1547 is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP); 1548 1549 buf = safe_malloc ( strlen (prefix) + strlen(s) * 4 + 2 ); 1550 strcpy (buf, prefix); /* __STRCPY_CHECKED__ */ 1551 p = buf + strlen (buf); 1552 if (is_pgp && strlen (s) == 40) 1553 { /* PGP v4 style formatted. */ 1554 for (i=0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) 1555 { 1556 *p++ = s[0]; 1557 *p++ = s[1]; 1558 *p++ = s[2]; 1559 *p++ = s[3]; 1560 *p++ = ' '; 1561 if (i == 4) 1562 *p++ = ' '; 1563 } 1564 } 1565 else 1566 { 1567 for (i=0; *s && s[1] && s[2]; s += 2, i++) 1568 { 1569 *p++ = s[0]; 1570 *p++ = s[1]; 1571 *p++ = is_pgp? ' ':':'; 1572 if (is_pgp && i == 7) 1573 *p++ = ' '; 1574 } 1575 } 1576 1577 /* just in case print remaining odd digits */ 1578 for (; *s; s++) 1579 *p++ = *s; 1580 *p++ = '\n'; 1581 *p = 0; 1582 state_puts (buf, state); 1583 FREE (&buf); 1584} 1585 1586/* Show the validity of a key used for one signature. */ 1587static void show_one_sig_validity (gpgme_ctx_t ctx, int idx, STATE *s) 1588{ 1589 gpgme_verify_result_t result = NULL; 1590 gpgme_signature_t sig = NULL; 1591 const char *txt = NULL; 1592 1593 result = gpgme_op_verify_result (ctx); 1594 if (result) 1595 for (sig = result->signatures; sig && (idx > 0); sig = sig->next, idx--); 1596 1597 switch (sig ? sig->validity : 0) 1598 { 1599 case GPGME_VALIDITY_UNKNOWN: 1600 txt = _("WARNING: We have NO indication whether " 1601 "the key belongs to the person named " 1602 "as shown above\n"); 1603 break; 1604 case GPGME_VALIDITY_UNDEFINED: 1605 break; 1606 case GPGME_VALIDITY_NEVER: 1607 txt = _("WARNING: The key does NOT BELONG to " 1608 "the person named as shown above\n"); 1609 break; 1610 case GPGME_VALIDITY_MARGINAL: 1611 txt = _("WARNING: It is NOT certain that the key " 1612 "belongs to the person named as shown above\n"); 1613 break; 1614 case GPGME_VALIDITY_FULL: 1615 case GPGME_VALIDITY_ULTIMATE: 1616 txt = NULL; 1617 break; 1618 } 1619 if (txt) 1620 state_puts (txt, s); 1621} 1622 1623static void print_smime_keyinfo (const char* msg, gpgme_signature_t sig, 1624 gpgme_key_t key, STATE *s) 1625{ 1626 int msgwid; 1627 gpgme_user_id_t uids = NULL; 1628 int i, aka = 0; 1629 1630 state_puts (msg, s); 1631 state_puts (" ", s); 1632 /* key is NULL when not present in the user's keyring */ 1633 if (key) 1634 { 1635 for (uids = key->uids; uids; uids = uids->next) 1636 { 1637 if (uids->revoked) 1638 continue; 1639 if (aka) 1640 { 1641 msgwid = mutt_strwidth (msg) - mutt_strwidth (_("aka: ")) + 1; 1642 if (msgwid < 0) 1643 msgwid = 0; 1644 for (i = 0; i < msgwid; i++) 1645 state_puts(" ", s); 1646 state_puts(_("aka: "), s); 1647 } 1648 state_puts (uids->uid, s); 1649 state_puts ("\n", s); 1650 1651 aka = 1; 1652 } 1653 } 1654 else 1655 { 1656 if (sig->fpr == NULL) 1657 /* L10N: You will see this message in place of "KeyID " 1658 if the S/MIME key has no ID. This is quite an error. 1659 */ 1660 state_puts (_("no signature fingerprint available"), s); 1661 else 1662 { 1663 state_puts (_("KeyID "), s); 1664 state_puts (sig->fpr, s); 1665 } 1666 state_puts ("\n", s); 1667 } 1668 1669 /* timestamp is 0 when verification failed. 1670 "Jan 1 1970" is not the created date. */ 1671 if (sig->timestamp) 1672 { 1673 msgwid = mutt_strwidth (msg) - mutt_strwidth (_("created: ")) + 1; 1674 if (msgwid < 0) 1675 msgwid = 0; 1676 for (i = 0; i < msgwid; i++) 1677 state_puts(" ", s); 1678 state_puts (_("created: "), s); 1679 print_time (sig->timestamp, s); 1680 state_puts ("\n", s); 1681 } 1682} 1683 1684/* Show information about one signature. This function is called with 1685 the context CTX of a successful verification operation and the 1686 enumerator IDX which should start at 0 and increment for each 1687 call/signature. 1688 1689 Return values are: 0 for normal procession, 1 for a bad signature, 1690 2 for a signature with a warning or -1 for no more signature. */ 1691static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE *s) 1692{ 1693 const char *fpr; 1694 gpgme_key_t key = NULL; 1695 int i, anybad = 0, anywarn = 0; 1696 unsigned int sum; 1697 gpgme_verify_result_t result; 1698 gpgme_signature_t sig; 1699 gpgme_error_t err = GPG_ERR_NO_ERROR; 1700 char buf[LONG_STRING]; 1701 1702 result = gpgme_op_verify_result (ctx); 1703 if (result) 1704 { 1705 /* FIXME: this code should use a static variable and remember 1706 the current position in the list of signatures, IMHO. 1707 -moritz. */ 1708 1709 for (i = 0, sig = result->signatures; sig && (i < idx); 1710 i++, sig = sig->next) 1711 ; 1712 if (! sig) 1713 return -1; /* Signature not found. */ 1714 1715 if (signature_key) 1716 { 1717 gpgme_key_unref (signature_key); 1718 signature_key = NULL; 1719 } 1720 1721 fpr = sig->fpr; 1722 sum = sig->summary; 1723 1724 if (gpg_err_code (sig->status) != GPG_ERR_NO_ERROR) 1725 anybad = 1; 1726 1727 if (gpg_err_code (sig->status) != GPG_ERR_NO_PUBKEY) 1728 { 1729 err = gpgme_get_key (ctx, fpr, &key, 0); /* secret key? */ 1730 if (! err) 1731 { 1732 if (! signature_key) 1733 signature_key = key; 1734 } 1735 else 1736 { 1737 key = NULL; /* Old gpgme versions did not set KEY to NULL on 1738 error. Do it here to avoid a double free. */ 1739 } 1740 } 1741 else 1742 { 1743 /* pubkey not present */ 1744 } 1745 1746 if (!s || !s->fpout || !(s->flags & MUTT_DISPLAY)) 1747 ; /* No state information so no way to print anything. */ 1748 else if (err) 1749 { 1750 snprintf (buf, sizeof (buf), 1751 _("Error getting key information for KeyID %s: %s\n"), 1752 fpr, gpgme_strerror (err)); 1753 state_puts (buf, s); 1754 anybad = 1; 1755 } 1756 else if ((sum & GPGME_SIGSUM_GREEN)) 1757 { 1758 print_smime_keyinfo (_("Good signature from:"), sig, key, s); 1759 if (show_sig_summary (sum, ctx, key, idx, s, sig)) 1760 anywarn = 1; 1761 show_one_sig_validity (ctx, idx, s); 1762 } 1763 else if ((sum & GPGME_SIGSUM_RED)) 1764 { 1765 print_smime_keyinfo (_("*BAD* signature from:"), sig, key, s); 1766 show_sig_summary (sum, ctx, key, idx, s, sig); 1767 } 1768 else if (!anybad && key && (key->protocol == GPGME_PROTOCOL_OpenPGP)) 1769 { /* We can't decide (yellow) but this is a PGP key with a good 1770 signature, so we display what a PGP user expects: The name, 1771 fingerprint and the key validity (which is neither fully or 1772 ultimate). */ 1773 print_smime_keyinfo (_("Good signature from:"), sig, key, s); 1774 show_one_sig_validity (ctx, idx, s); 1775 show_fingerprint (key,s); 1776 if (show_sig_summary (sum, ctx, key, idx, s, sig)) 1777 anywarn = 1; 1778 } 1779 else /* can't decide (yellow) */ 1780 { 1781 print_smime_keyinfo (_("Problem signature from:"), sig, key, s); 1782 /* 0 indicates no expiration */ 1783 if (sig->exp_timestamp) 1784 { 1785 /* L10N: 1786 This is trying to match the width of the 1787 "Problem signature from:" translation just above. */ 1788 state_puts (_(" expires: "), s); 1789 print_time (sig->exp_timestamp, s); 1790 state_puts ("\n", s); 1791 } 1792 show_sig_summary (sum, ctx, key, idx, s, sig); 1793 anywarn = 1; 1794 } 1795 1796 if (key != signature_key) 1797 gpgme_key_unref (key); 1798 } 1799 1800 return anybad ? 1 : anywarn ? 2 : 0; 1801} 1802 1803/* Do the actual verification step. With IS_SMIME set to true we 1804 assume S/MIME (surprise!) */ 1805static int verify_one (BODY *sigbdy, STATE *s, 1806 const char *tempfile, int is_smime) 1807{ 1808 int badsig = -1; 1809 int anywarn = 0; 1810 int err; 1811 gpgme_ctx_t ctx; 1812 gpgme_data_t signature, message; 1813 1814 signature = file_to_data_object (s->fpin, sigbdy->offset, sigbdy->length); 1815 if (!signature) 1816 return -1; 1817 1818 /* We need to tell gpgme about the encoding because the backend can't 1819 auto-detect plain base-64 encoding which is used by S/MIME. */ 1820 if (is_smime) 1821 gpgme_data_set_encoding (signature, GPGME_DATA_ENCODING_BASE64); 1822 1823 err = gpgme_data_new_from_file (&message, tempfile, 1); 1824 if (err) 1825 { 1826 gpgme_data_release (signature); 1827 mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err)); 1828 return -1; 1829 } 1830 ctx = create_gpgme_context (is_smime); 1831 1832 /* Note: We don't need a current time output because GPGME avoids 1833 such an attack by separating the meta information from the 1834 data. */ 1835 state_attach_puts (_("[-- Begin signature information --]\n"), s); 1836 1837 err = gpgme_op_verify (ctx, signature, message, NULL); 1838 gpgme_data_release (message); 1839 gpgme_data_release (signature); 1840 1841 mutt_need_hard_redraw (); 1842 if (err) 1843 { 1844 char buf[200]; 1845 1846 snprintf (buf, sizeof(buf)-1, 1847 _("Error: verification failed: %s\n"), 1848 gpgme_strerror (err)); 1849 state_puts (buf, s); 1850 } 1851 else 1852 { /* Verification succeeded, see what the result is. */ 1853 int res, idx; 1854 int anybad = 0; 1855 gpgme_verify_result_t verify_result; 1856 1857 if (signature_key) 1858 { 1859 gpgme_key_unref (signature_key); 1860 signature_key = NULL; 1861 } 1862 1863 verify_result = gpgme_op_verify_result (ctx); 1864 if (verify_result && verify_result->signatures) 1865 { 1866 for (idx=0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) 1867 { 1868 if (res == 1) 1869 anybad = 1; 1870 else if (res == 2) 1871 anywarn = 2; 1872 } 1873 if (!anybad) 1874 badsig = 0; 1875 } 1876 } 1877 1878 if (!badsig) 1879 { 1880 gpgme_verify_result_t result; 1881 gpgme_sig_notation_t notation; 1882 gpgme_signature_t signature; 1883 int non_pka_notations; 1884 1885 result = gpgme_op_verify_result (ctx); 1886 if (result) 1887 { 1888 for (signature = result->signatures; signature; 1889 signature = signature->next) 1890 { 1891 non_pka_notations = 0; 1892 for (notation = signature->notations; notation; 1893 notation = notation->next) 1894 if (! is_pka_notation (notation)) 1895 non_pka_notations++; 1896 1897 if (non_pka_notations) 1898 { 1899 char buf[SHORT_STRING]; 1900 snprintf (buf, sizeof (buf), 1901 _("*** Begin Notation (signature by: %s) ***\n"), 1902 signature->fpr); 1903 state_puts (buf, s); 1904 for (notation = signature->notations; notation; 1905 notation = notation->next) 1906 { 1907 if (is_pka_notation (notation)) 1908 continue; 1909 1910 if (notation->name) 1911 { 1912 state_puts (notation->name, s); 1913 state_puts ("=", s); 1914 } 1915 if (notation->value) 1916 { 1917 state_puts (notation->value, s); 1918 if (!(*notation->value 1919 && (notation->value[strlen (notation->value)-1]=='\n'))) 1920 state_puts ("\n", s); 1921 } 1922 } 1923 state_puts (_("*** End Notation ***\n"), s); 1924 } 1925 } 1926 } 1927 } 1928 1929 gpgme_release (ctx); 1930 1931 state_attach_puts (_("[-- End signature information --]\n\n"), s); 1932 dprint (1, (debugfile, "verify_one: returning %d.\n", badsig)); 1933 1934 return badsig? 1: anywarn? 2 : 0; 1935} 1936 1937int pgp_gpgme_verify_one (BODY *sigbdy, STATE *s, const char *tempfile) 1938{ 1939 return verify_one (sigbdy, s, tempfile, 0); 1940} 1941 1942int smime_gpgme_verify_one (BODY *sigbdy, STATE *s, const char *tempfile) 1943{ 1944 return verify_one (sigbdy, s, tempfile, 1); 1945} 1946 1947/* 1948 * Implementation of `decrypt_part'. 1949 */ 1950 1951/* Decrypt a PGP or SMIME message (depending on the boolean flag 1952 IS_SMIME) with body A described further by state S. Write 1953 plaintext out to file FPOUT and return a new body. For PGP returns 1954 a flag in R_IS_SIGNED to indicate whether this is a combined 1955 encrypted and signed message, for S/MIME it returns true when it is 1956 not a encrypted but a signed message. */ 1957static BODY *decrypt_part (BODY *a, STATE *s, FILE *fpout, int is_smime, 1958 int *r_is_signed) 1959{ 1960 struct stat info; 1961 BODY *tattach = NULL; 1962 int err = 0; 1963 gpgme_ctx_t ctx = NULL; 1964 gpgme_data_t ciphertext = NULL, plaintext = NULL; 1965 int maybe_signed = 0; 1966 int anywarn = 0; 1967 int sig_stat = 0; 1968 1969 if (r_is_signed) 1970 *r_is_signed = 0; 1971 1972restart: 1973 ctx = create_gpgme_context (is_smime); 1974 1975 /* Make a data object from the body, create context etc. */ 1976 ciphertext = file_to_data_object (s->fpin, a->offset, a->length); 1977 if (!ciphertext) 1978 goto cleanup; 1979 plaintext = create_gpgme_data (); 1980 1981 /* Do the decryption or the verification in case of the S/MIME hack. */ 1982 if ((! is_smime) || maybe_signed) 1983 { 1984 if (! is_smime) 1985 err = gpgme_op_decrypt_verify (ctx, ciphertext, plaintext); 1986 else if (maybe_signed) 1987 err = gpgme_op_verify (ctx, ciphertext, NULL, plaintext); 1988 1989 if (err == GPG_ERR_NO_ERROR) 1990 { 1991 /* Check whether signatures have been verified. */ 1992 gpgme_verify_result_t verify_result = gpgme_op_verify_result (ctx); 1993 if (verify_result->signatures) 1994 sig_stat = 1; 1995 } 1996 } 1997 else 1998 err = gpgme_op_decrypt (ctx, ciphertext, plaintext); 1999 gpgme_data_release (ciphertext); 2000 ciphertext = NULL; 2001 if (err) 2002 { 2003 /* Abort right away and silently. Autocrypt will retry on the 2004 * normal keyring. */ 2005 if (option (OPTAUTOCRYPTGPGME)) 2006 goto cleanup; 2007 if (is_smime && !maybe_signed 2008 && gpg_err_code (err) == GPG_ERR_NO_DATA) 2009 { 2010 /* Check whether this might be a signed message despite what 2011 the mime header told us. Retry then. gpgsm returns the 2012 error information "unsupported Algorithm '?'" but gpgme 2013 will not store this unknown algorithm, thus we test that 2014 it has not been set. */ 2015 gpgme_decrypt_result_t result; 2016 2017 result = gpgme_op_decrypt_result (ctx); 2018 if (!result->unsupported_algorithm) 2019 { 2020 maybe_signed = 1; 2021 gpgme_data_release (plaintext); 2022 plaintext = NULL; 2023 /* We release the context because recent versions of gpgme+gpgsm 2024 * appear to end the session after an error */ 2025 gpgme_release (ctx); 2026 ctx = NULL; 2027 goto restart; 2028 } 2029 } 2030 mutt_need_hard_redraw (); 2031 if ((s->flags & MUTT_DISPLAY)) 2032 { 2033 char buf[200]; 2034 2035 snprintf (buf, sizeof(buf)-1, 2036 _("[-- Error: decryption failed: %s --]\n\n"), 2037 gpgme_strerror (err)); 2038 state_attach_puts (buf, s); 2039 } 2040 goto cleanup; 2041 } 2042 mutt_need_hard_redraw (); 2043 2044 /* Read the output from GPGME, and make sure to change CRLF to LF, 2045 otherwise read_mime_header has a hard time parsing the message. */ 2046 if (data_object_to_stream (plaintext, fpout)) 2047 { 2048 goto cleanup; 2049 } 2050 gpgme_data_release (plaintext); 2051 plaintext = NULL; 2052 2053 a->is_signed_data = 0; 2054 if (sig_stat) 2055 { 2056 int res, idx; 2057 int anybad = 0; 2058 2059 if (maybe_signed) 2060 a->is_signed_data = 1; 2061 if (r_is_signed) 2062 *r_is_signed = -1; /* A signature exists. */ 2063 2064 if ((s->flags & MUTT_DISPLAY)) 2065 state_attach_puts (_("[-- Begin signature " 2066 "information --]\n"), s); 2067 for (idx = 0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) 2068 { 2069 if (res == 1) 2070 anybad = 1; 2071 else if (res == 2) 2072 anywarn = 1; 2073 } 2074 if (!anybad && idx && r_is_signed && *r_is_signed) 2075 *r_is_signed = anywarn? 2:1; /* Good signature. */ 2076 2077 if ((s->flags & MUTT_DISPLAY)) 2078 state_attach_puts (_("[-- End signature " 2079 "information --]\n\n"), s); 2080 } 2081 gpgme_release (ctx); 2082 ctx = NULL; 2083 2084 fflush (fpout); 2085 rewind (fpout); 2086 tattach = mutt_read_mime_header (fpout, 0); 2087 if (tattach) 2088 { 2089 /* 2090 * Need to set the length of this body part. 2091 */ 2092 fstat (fileno (fpout), &info); 2093 tattach->length = info.st_size - tattach->offset; 2094 2095 tattach->warnsig = anywarn; 2096 2097 /* See if we need to recurse on this MIME part. */ 2098 mutt_parse_part (fpout, tattach); 2099 } 2100 2101cleanup: 2102 gpgme_data_release (ciphertext); 2103 gpgme_data_release (plaintext); 2104 gpgme_release (ctx); 2105 2106 return tattach; 2107} 2108 2109/* Decrypt a PGP/MIME message in FPIN and B and return a new body and 2110 the stream in CUR and FPOUT. Returns 0 on success. */ 2111int pgp_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur) 2112{ 2113 BUFFER *tempfile = NULL; 2114 STATE s; 2115 BODY *first_part = b; 2116 int is_signed = 0; 2117 int need_decode = 0; 2118 int saved_type; 2119 LOFF_T saved_offset; 2120 size_t saved_length; 2121 FILE *decoded_fp = NULL; 2122 int rv = 0; 2123 2124 first_part->goodsig = 0; 2125 first_part->warnsig = 0; 2126 2127 if (mutt_is_valid_multipart_pgp_encrypted (b)) 2128 { 2129 b = b->parts->next; 2130 /* Some clients improperly encode the octetstream part. */ 2131 if (b->encoding != ENC7BIT) 2132 need_decode = 1; 2133 } 2134 else if (mutt_is_malformed_multipart_pgp_encrypted (b)) 2135 { 2136 b = b->parts->next->next; 2137 need_decode = 1; 2138 } 2139 else 2140 return -1; 2141 2142 tempfile = mutt_buffer_pool_get (); 2143 2144 memset (&s, 0, sizeof (s)); 2145 s.fpin = fpin; 2146 2147 if (need_decode) 2148 { 2149 saved_type = b->type; 2150 saved_offset = b->offset; 2151 saved_length = b->length; 2152 2153 mutt_buffer_mktemp (tempfile); 2154 if ((decoded_fp = safe_fopen (mutt_b2s (tempfile), "w+")) == NULL) 2155 { 2156 mutt_perror (mutt_b2s (tempfile)); 2157 rv = -1; 2158 goto bail; 2159 } 2160 unlink (mutt_b2s (tempfile)); 2161 2162 fseeko (s.fpin, b->offset, 0); 2163 s.fpout = decoded_fp; 2164 2165 mutt_decode_attachment (b, &s); 2166 2167 fflush (decoded_fp); 2168 b->length = ftello (decoded_fp); 2169 b->offset = 0; 2170 rewind (decoded_fp); 2171 s.fpin = decoded_fp; 2172 s.fpout = 0; 2173 } 2174 2175 mutt_buffer_mktemp (tempfile); 2176 if (!(*fpout = safe_fopen (mutt_b2s (tempfile), "w+"))) 2177 { 2178 mutt_perror (mutt_b2s (tempfile)); 2179 rv = -1; 2180 goto bail; 2181 } 2182 unlink (mutt_b2s (tempfile)); 2183 2184 if ((*cur = decrypt_part (b, &s, *fpout, 0, &is_signed)) == NULL) 2185 { 2186 rv = -1; 2187 safe_fclose (fpout); 2188 } 2189 else 2190 { 2191 rewind (*fpout); 2192 if (is_signed > 0) 2193 first_part->goodsig = 1; 2194 } 2195 2196bail: 2197 mutt_buffer_pool_release (&tempfile); 2198 2199 if (need_decode) 2200 { 2201 b->type = saved_type; 2202 b->length = saved_length; 2203 b->offset = saved_offset; 2204 safe_fclose (&decoded_fp); 2205 } 2206 2207 return rv; 2208} 2209 2210 2211/* Decrypt a S/MIME message in FPIN and B and return a new body and 2212 the stream in CUR and FPOUT. Returns 0 on success. */ 2213int smime_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur) 2214{ 2215 BUFFER *tempfile = NULL; 2216 STATE s; 2217 FILE *tmpfp=NULL; 2218 int is_signed; 2219 LOFF_T saved_b_offset; 2220 size_t saved_b_length; 2221 int saved_b_type; 2222 2223 if (!mutt_is_application_smime (b)) 2224 return -1; 2225 2226 if (b->parts) 2227 return -1; 2228 2229 *cur = NULL; 2230 tempfile = mutt_buffer_pool_get (); 2231 2232 /* Decode the body - we need to pass binary CMS to the 2233 backend. The backend allows for Base64 encoded data but it does 2234 not allow for QP which I have seen in some messages. So better 2235 do it here. */ 2236 saved_b_type = b->type; 2237 saved_b_offset = b->offset; 2238 saved_b_length = b->length; 2239 memset (&s, 0, sizeof (s)); 2240 s.fpin = fpin; 2241 fseeko (s.fpin, b->offset, 0); 2242 mutt_buffer_mktemp (tempfile); 2243 if (!(tmpfp = safe_fopen (mutt_b2s (tempfile), "w+"))) 2244 { 2245 mutt_perror (mutt_b2s (tempfile)); 2246 goto bail; 2247 } 2248 mutt_unlink (mutt_b2s (tempfile)); 2249 2250 s.fpout = tmpfp; 2251 mutt_decode_attachment (b, &s); 2252 fflush (tmpfp); 2253 b->length = ftello (s.fpout); 2254 b->offset = 0; 2255 rewind (tmpfp); 2256 2257 memset (&s, 0, sizeof (s)); 2258 s.fpin = tmpfp; 2259 s.fpout = 0; 2260 mutt_buffer_mktemp (tempfile); 2261 if (!(*fpout = safe_fopen (mutt_b2s (tempfile), "w+"))) 2262 { 2263 mutt_perror (mutt_b2s (tempfile)); 2264 goto bail; 2265 } 2266 mutt_unlink (mutt_b2s (tempfile)); 2267 2268 *cur = decrypt_part (b, &s, *fpout, 1, &is_signed); 2269 if (*cur) 2270 (*cur)->goodsig = is_signed > 0; 2271 b->type = saved_b_type; 2272 b->length = saved_b_length; 2273 b->offset = saved_b_offset; 2274 safe_fclose (&tmpfp); 2275 rewind (*fpout); 2276 if (*cur && !is_signed && !(*cur)->parts && mutt_is_application_smime (*cur)) 2277 { 2278 /* Assume that this is a opaque signed s/mime message. This is 2279 an ugly way of doing it but we have anyway a problem with 2280 arbitrary encoded S/MIME messages: Only the outer part may be 2281 encrypted. The entire mime parsing should be revamped, 2282 probably by keeping the temporary files so that we don't 2283 need to decrypt them all the time. Inner parts of an 2284 encrypted part can then point into this file and there won't 2285 ever be a need to decrypt again. This needs a partial 2286 rewrite of the MIME engine. */ 2287 BODY *bb = *cur; 2288 BODY *tmp_b; 2289 2290 saved_b_type = bb->type; 2291 saved_b_offset = bb->offset; 2292 saved_b_length = bb->length; 2293 memset (&s, 0, sizeof (s)); 2294 s.fpin = *fpout; 2295 fseeko (s.fpin, bb->offset, 0); 2296 mutt_buffer_mktemp (tempfile); 2297 if (!(tmpfp = safe_fopen (mutt_b2s (tempfile), "w+"))) 2298 { 2299 mutt_perror (mutt_b2s (tempfile)); 2300 goto bail; 2301 } 2302 mutt_unlink (mutt_b2s (tempfile)); 2303 2304 s.fpout = tmpfp; 2305 mutt_decode_attachment (bb, &s); 2306 fflush (tmpfp); 2307 bb->length = ftello (s.fpout); 2308 bb->offset = 0; 2309 rewind (tmpfp); 2310 safe_fclose (fpout); 2311 2312 memset (&s, 0, sizeof (s)); 2313 s.fpin = tmpfp; 2314 s.fpout = 0; 2315 mutt_buffer_mktemp (tempfile); 2316 if (!(*fpout = safe_fopen (mutt_b2s (tempfile), "w+"))) 2317 { 2318 mutt_perror (mutt_b2s (tempfile)); 2319 goto bail; 2320 } 2321 mutt_unlink (mutt_b2s (tempfile)); 2322 2323 tmp_b = decrypt_part (bb, &s, *fpout, 1, &is_signed); 2324 if (tmp_b) 2325 tmp_b->goodsig = is_signed > 0; 2326 bb->type = saved_b_type; 2327 bb->length = saved_b_length; 2328 bb->offset = saved_b_offset; 2329 safe_fclose (&tmpfp); 2330 rewind (*fpout); 2331 mutt_free_body (cur); 2332 *cur = tmp_b; 2333 } 2334 2335 mutt_buffer_pool_release (&tempfile); 2336 return *cur? 0:-1; 2337 2338bail: 2339 mutt_buffer_pool_release (&tempfile); 2340 mutt_free_body (cur); 2341 return -1; 2342} 2343 2344static int pgp_gpgme_extract_keys (gpgme_data_t keydata, FILE** fp) 2345{ 2346 /* Before gpgme 1.9.0 and gpg 2.1.14 there was no side-effect free 2347 * way to view key data in GPGME, so we import the key into a 2348 * temporary keyring if we detect an older system. */ 2349 int legacy_api; 2350 BUFFER *tmpdir = NULL; 2351 BUFFER *tmpfile = NULL; 2352 gpgme_ctx_t tmpctx; 2353 gpgme_error_t err; 2354 gpgme_engine_info_t engineinfo; 2355 gpgme_key_t key; 2356 gpgme_user_id_t uid; 2357 gpgme_subkey_t subkey; 2358 const char* shortid; 2359 int len; 2360 char date[STRING]; 2361 int more; 2362 int rc = -1; 2363 time_t tt; 2364 2365#if GPGME_VERSION_NUMBER >= 0x010900 /* gpgme >= 1.9.0 */ 2366 legacy_api = !have_gpg_version ("2.1.14"); 2367#else /* gpgme < 1.9.0 */ 2368 legacy_api = 1; 2369#endif 2370 2371 tmpctx = create_gpgme_context (0); 2372 2373 if (legacy_api) 2374 { 2375 tmpdir = mutt_buffer_pool_get (); 2376 mutt_buffer_printf (tmpdir, "%s/mutt-gpgme-XXXXXX", NONULL (Tempdir)); 2377 if (!mkdtemp (tmpdir->data)) 2378 { 2379 dprint (1, (debugfile, "Error creating temporary GPGME home\n")); 2380 goto err_ctx; 2381 } 2382 2383 engineinfo = gpgme_ctx_get_engine_info (tmpctx); 2384 while (engineinfo && engineinfo->protocol != GPGME_PROTOCOL_OpenPGP) 2385 engineinfo = engineinfo->next; 2386 if (!engineinfo) 2387 { 2388 dprint (1, (debugfile, "Error finding GPGME PGP engine\n")); 2389 goto err_tmpdir; 2390 } 2391 2392 err = gpgme_ctx_set_engine_info (tmpctx, GPGME_PROTOCOL_OpenPGP, 2393 engineinfo->file_name, mutt_b2s (tmpdir)); 2394 if (err != GPG_ERR_NO_ERROR) 2395 { 2396 dprint (1, (debugfile, "Error setting GPGME context home\n")); 2397 goto err_tmpdir; 2398 } 2399 } 2400 2401 tmpfile = mutt_buffer_pool_get (); 2402 mutt_buffer_mktemp (tmpfile); 2403 *fp = safe_fopen (mutt_b2s (tmpfile), "w+"); 2404 if (!*fp) 2405 { 2406 mutt_perror (mutt_b2s (tmpfile)); 2407 goto err_tmpdir; 2408 } 2409 unlink (mutt_b2s (tmpfile)); 2410 2411#if GPGME_VERSION_NUMBER >= 0x010900 /* 1.9.0 */ 2412 if (!legacy_api) 2413 err = gpgme_op_keylist_from_data_start (tmpctx, keydata, 0); 2414 else 2415#endif /* gpgme >= 1.9.0 */ 2416 { 2417 err = gpgme_op_keylist_start (tmpctx, NULL, 0); 2418 } 2419 while (!err) 2420 { 2421 if ((err = gpgme_op_keylist_next (tmpctx, &key))) 2422 break; 2423 uid = key->uids; 2424 subkey = key->subkeys; 2425 more = 0; 2426 while (subkey) 2427 { 2428 shortid = subkey->keyid; 2429 len = mutt_strlen (subkey->keyid); 2430 if (len > 8) 2431 shortid += len - 8; 2432 tt = subkey->timestamp; 2433 strftime (date, sizeof (date), "%Y-%m-%d", localtime (&tt)); 2434 2435 if (!more) 2436 fprintf (*fp, "%s %5.5s %d/%8s %s %s\n", more ? "sub" : "pub", 2437 gpgme_pubkey_algo_name (subkey->pubkey_algo), subkey->length, 2438 shortid, date, uid->uid); 2439 else 2440 fprintf (*fp, "%s %5.5s %d/%8s %s\n", more ? "sub" : "pub", 2441 gpgme_pubkey_algo_name (subkey->pubkey_algo), subkey->length, 2442 shortid, date); 2443 subkey = subkey->next; 2444 more = 1; 2445 } 2446 gpgme_key_unref (key); 2447 } 2448 if (gpg_err_code (err) != GPG_ERR_EOF) 2449 { 2450 dprint (1, (debugfile, "Error listing keys\n")); 2451 goto err_fp; 2452 } 2453 2454 rc = 0; 2455 2456err_fp: 2457 if (rc) 2458 safe_fclose (fp); 2459err_tmpdir: 2460 if (legacy_api) 2461 mutt_rmtree (mutt_b2s (tmpdir)); 2462err_ctx: 2463 gpgme_release (tmpctx); 2464 2465 mutt_buffer_pool_release (&tmpdir); 2466 mutt_buffer_pool_release (&tmpfile); 2467 2468 return rc; 2469} 2470 2471 2472/* Check that 'b' is a complete line containing 'a' followed by either LF or CRLF. 2473 * 2474 * returns: 2475 * 0 if the is a match 2476 * -1 otherwise 2477 */ 2478static int line_compare(const char *a, size_t n, const char *b) 2479{ 2480 if (mutt_strncmp(a, b, n) == 0) 2481 { 2482 /* at this point we know that 'b' is at least 'n' chars long */ 2483 if (b[n] == '\n' || (b[n] == '\r' && b[n+1] == '\n')) 2484 return 0; 2485 } 2486 return -1; 2487} 2488 2489#define _LINE_COMPARE(_x,_y) !line_compare(_x, sizeof(_x)-1, _y) 2490#define MESSAGE(_y) _LINE_COMPARE("MESSAGE-----", _y) 2491#define SIGNED_MESSAGE(_y) _LINE_COMPARE("SIGNED MESSAGE-----", _y) 2492#define PUBLIC_KEY_BLOCK(_y) _LINE_COMPARE("PUBLIC KEY BLOCK-----", _y) 2493#define BEGIN_PGP_SIGNATURE(_y) _LINE_COMPARE("-----BEGIN PGP SIGNATURE-----", _y) 2494 2495/* 2496 * Implementation of `pgp_check_traditional'. 2497 */ 2498 2499static int pgp_check_traditional_one_body (FILE *fp, BODY *b) 2500{ 2501 BUFFER *tempfile = NULL; 2502 char buf[HUGE_STRING]; 2503 FILE *tfp; 2504 int rv = 0; 2505 2506 short sgn = 0; 2507 short enc = 0; 2508 2509 if (b->type != TYPETEXT) 2510 return 0; 2511 2512 tempfile = mutt_buffer_pool_get (); 2513 mutt_buffer_mktemp (tempfile); 2514 if (mutt_decode_save_attachment (fp, b, mutt_b2s (tempfile), 0, 0) != 0) 2515 { 2516 unlink (mutt_b2s (tempfile)); 2517 goto cleanup; 2518 } 2519 2520 if ((tfp = fopen (mutt_b2s (tempfile), "r")) == NULL) 2521 { 2522 unlink (mutt_b2s (tempfile)); 2523 goto cleanup; 2524 } 2525 2526 while (fgets (buf, sizeof (buf), tfp)) 2527 { 2528 if (!mutt_strncmp ("-----BEGIN PGP ", buf, 15)) 2529 { 2530 if (MESSAGE(buf + 15)) 2531 { 2532 enc = 1; 2533 break; 2534 } 2535 else if (SIGNED_MESSAGE(buf + 15)) 2536 { 2537 sgn = 1; 2538 break; 2539 } 2540 } 2541 } 2542 safe_fclose (&tfp); 2543 unlink (mutt_b2s (tempfile)); 2544 2545 if (!enc && !sgn) 2546 goto cleanup; 2547 2548 /* fix the content type */ 2549 2550 mutt_set_parameter ("format", "fixed", &b->parameter); 2551 mutt_set_parameter ("x-action", enc ? "pgp-encrypted" : "pgp-signed", 2552 &b->parameter); 2553 2554 rv = 1; 2555 2556cleanup: 2557 mutt_buffer_pool_release (&tempfile); 2558 return rv; 2559} 2560 2561int pgp_gpgme_check_traditional (FILE *fp, BODY *b, int just_one) 2562{ 2563 int rv = 0; 2564 int r; 2565 for (; b; b = b->next) 2566 { 2567 if (!just_one && is_multipart (b)) 2568 rv = (pgp_gpgme_check_traditional (fp, b->parts, 0) || rv); 2569 else if (b->type == TYPETEXT) 2570 { 2571 if ((r = mutt_is_application_pgp (b))) 2572 rv = (rv || r); 2573 else 2574 rv = (pgp_check_traditional_one_body (fp, b) || rv); 2575 } 2576 2577 if (just_one) 2578 break; 2579 } 2580 return rv; 2581} 2582 2583void pgp_gpgme_invoke_import (const char *fname) 2584{ 2585 gpgme_ctx_t ctx; 2586 gpgme_data_t keydata = NULL; 2587 gpgme_error_t err; 2588 FILE *in = NULL; 2589 gpgme_import_result_t impres; 2590 gpgme_import_status_t st; 2591 int any; 2592 2593 ctx = create_gpgme_context (0); 2594 2595 if (!(in = safe_fopen (fname, "r"))) 2596 { 2597 mutt_perror (fname); 2598 goto leave; 2599 } 2600 2601 /* Note that the stream, "in", needs to be kept open while the keydata 2602 * is used. */ 2603 if ((err = gpgme_data_new_from_stream (&keydata, in)) != GPG_ERR_NO_ERROR) 2604 { 2605 mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err)); 2606 mutt_sleep (1); 2607 goto leave; 2608 } 2609 2610 err = gpgme_op_import (ctx, keydata); 2611 if (err) 2612 { 2613 mutt_error (_("error importing key: %s\n"), gpgme_strerror (err)); 2614 mutt_sleep (1); 2615 goto leave; 2616 } 2617 2618 /* Print infos about the imported keys to stdout. */ 2619 impres = gpgme_op_import_result (ctx); 2620 if (!impres) 2621 { 2622 fputs ("oops: no import result returned\n", stdout); 2623 goto leave; 2624 } 2625 2626 for (st = impres->imports; st; st = st->next) 2627 { 2628 if (st->result) 2629 continue; 2630 printf ("key %s imported (", NONULL (st->fpr)); 2631 /* Note that we use the singular even if it is possible that 2632 * several uids etc are new. This simply looks better. */ 2633 any = 0; 2634 if (st->status & GPGME_IMPORT_SECRET) 2635 { 2636 printf ("secret parts"); 2637 any = 1; 2638 } 2639 if ((st->status & GPGME_IMPORT_NEW)) 2640 { 2641 printf ("%snew key", any? ", ":""); 2642 any = 1; 2643 } 2644 if ((st->status & GPGME_IMPORT_UID)) 2645 { 2646 printf ("%snew uid", any? ", ":""); 2647 any = 1; 2648 } 2649 if ((st->status & GPGME_IMPORT_SIG)) 2650 { 2651 printf ("%snew sig", any? ", ":""); 2652 any = 1; 2653 } 2654 if ((st->status & GPGME_IMPORT_SUBKEY)) 2655 { 2656 printf ("%snew subkey", any? ", ":""); 2657 any = 1; 2658 } 2659 printf ("%s)\n", any? "":"not changed"); 2660 /* Fixme: Should we lookup each imported key and print more infos? */ 2661 } 2662 /* Now print keys which failed the import. Unfortunately in most 2663 * cases gpg will bail out early and not tell gpgme about. */ 2664 /* FIXME: We could instead use the new GPGME_AUDITLOG_DIAG to show 2665 * the actual gpg diagnostics. But I fear that would clutter the 2666 * output too much. Maybe a dedicated prompt or option to do this 2667 * would be helpful. */ 2668 for (st = impres->imports; st; st = st->next) 2669 { 2670 if (!st->result) 2671 continue; 2672 printf ("key %s import failed: %s\n", NONULL (st->fpr), 2673 gpgme_strerror (st->result)); 2674 } 2675 fflush (stdout); 2676 2677 leave: 2678 gpgme_release (ctx); 2679 gpgme_data_release (keydata); 2680 safe_fclose (&in); 2681} 2682 2683 2684/* 2685 * Implementation of `application_handler'. 2686 */ 2687 2688/* 2689 Copy a clearsigned message, and strip the signature and PGP's 2690 dash-escaping. 2691 2692 XXX - charset handling: We assume that it is safe to do 2693 character set decoding first, dash decoding second here, while 2694 we do it the other way around in the main handler. 2695 2696 (Note that we aren't worse than Outlook & Cie in this, and also 2697 note that we can successfully handle anything produced by any 2698 existing versions of mutt.) */ 2699 2700static void copy_clearsigned (gpgme_data_t data, STATE *s, char *charset) 2701{ 2702 char buf[HUGE_STRING]; 2703 short complete, armor_header; 2704 FGETCONV *fc; 2705 char *fname; 2706 FILE *fp; 2707 2708 fname = data_object_to_tempfile (data, NULL, &fp); 2709 if (!fname) 2710 return; 2711 unlink (fname); 2712 FREE (&fname); 2713 2714 /* fromcode comes from the MIME Content-Type charset label. It might 2715 * be a wrong label, so we want the ability to do corrections via 2716 * charset-hooks. Therefore we set flags to MUTT_ICONV_HOOK_FROM. 2717 */ 2718 fc = fgetconv_open (fp, charset, Charset, MUTT_ICONV_HOOK_FROM); 2719 2720 for (complete = 1, armor_header = 1; 2721 fgetconvs (buf, sizeof (buf), fc) != NULL; 2722 complete = strchr (buf, '\n') != NULL) 2723 { 2724 if (!complete) 2725 { 2726 if (!armor_header) 2727 state_puts (buf, s); 2728 continue; 2729 } 2730 2731 if (BEGIN_PGP_SIGNATURE(buf)) 2732 break; 2733 2734 if (armor_header) 2735 { 2736 if (buf[0] == '\n') 2737 armor_header = 0; 2738 continue; 2739 } 2740 2741 if (s->prefix) 2742 state_puts (s->prefix, s); 2743 2744 if (buf[0] == '-' && buf[1] == ' ') 2745 state_puts (buf + 2, s); 2746 else 2747 state_puts (buf, s); 2748 } 2749 2750 fgetconv_close (&fc); 2751 safe_fclose (&fp); 2752} 2753 2754/* Support for classic_application/pgp */ 2755int pgp_gpgme_application_handler (BODY *m, STATE *s) 2756{ 2757 int needpass = -1, pgp_keyblock = 0; 2758 int clearsign = 0; 2759 long bytes; 2760 LOFF_T last_pos, offset; 2761 char buf[HUGE_STRING]; 2762 FILE *pgpout = NULL; 2763 2764 gpgme_error_t err = 0; 2765 gpgme_data_t armored_data = NULL; 2766 2767 short maybe_goodsig = 1; 2768 short have_any_sigs = 0; 2769 2770 char body_charset[STRING]; /* Only used for clearsigned messages. */ 2771 2772 dprint (2, (debugfile, "Entering pgp_application_pgp handler\n")); 2773 2774 /* For clearsigned messages we won't be able to get a character set 2775 but we know that this may only be text thus we assume Latin-1 2776 here. */ 2777 if (!mutt_get_body_charset (body_charset, sizeof (body_charset), m)) 2778 strfcpy (body_charset, "iso-8859-1", sizeof body_charset); 2779 2780 fseeko (s->fpin, m->offset, 0); 2781 last_pos = m->offset; 2782 2783 for (bytes = m->length; bytes > 0;) 2784 { 2785 if (fgets (buf, sizeof (buf), s->fpin) == NULL) 2786 break; 2787 2788 offset = ftello (s->fpin); 2789 bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */ 2790 last_pos = offset; 2791 2792 if (!mutt_strncmp ("-----BEGIN PGP ", buf, 15)) 2793 { 2794 clearsign = 0; 2795 2796 if (MESSAGE(buf + 15)) 2797 needpass = 1; 2798 else if (SIGNED_MESSAGE(buf + 15)) 2799 { 2800 clearsign = 1; 2801 needpass = 0; 2802 } 2803 else if (PUBLIC_KEY_BLOCK(buf + 15)) 2804 { 2805 needpass = 0; 2806 pgp_keyblock = 1; 2807 } 2808 else 2809 { 2810 /* XXX - we may wish to recode here */ 2811 if (s->prefix) 2812 state_puts (s->prefix, s); 2813 state_puts (buf, s); 2814 continue; 2815 } 2816 2817 have_any_sigs = (have_any_sigs 2818 || (clearsign && (s->flags & MUTT_VERIFY))); 2819 2820 /* Copy PGP material to an data container */ 2821 armored_data = file_to_data_object (s->fpin, m->offset, m->length); 2822 /* Invoke PGP if needed */ 2823 if (pgp_keyblock) 2824 { 2825 pgp_gpgme_extract_keys (armored_data, &pgpout); 2826 } 2827 else if (!clearsign || (s->flags & MUTT_VERIFY)) 2828 { 2829 unsigned int sig_stat = 0; 2830 gpgme_data_t plaintext; 2831 gpgme_ctx_t ctx; 2832 2833 plaintext = create_gpgme_data (); 2834 ctx = create_gpgme_context (0); 2835 2836 if (clearsign) 2837 err = gpgme_op_verify (ctx, armored_data, NULL, plaintext); 2838 else 2839 { 2840 err = gpgme_op_decrypt_verify (ctx, armored_data, plaintext); 2841 if (gpg_err_code (err) == GPG_ERR_NO_DATA) 2842 { 2843 /* Decrypt verify can't handle signed only messages. */ 2844 err = (gpgme_data_seek (armored_data, 0, SEEK_SET) == -1) 2845 ? gpgme_error_from_errno (errno) : 0; 2846 /* Must release plaintext so that we supply an 2847 uninitialized object. */ 2848 gpgme_data_release (plaintext); 2849 plaintext = create_gpgme_data (); 2850 err = gpgme_op_verify (ctx, armored_data, 2851 NULL, plaintext); 2852 } 2853 } 2854 mutt_need_hard_redraw (); 2855 2856 if (err) 2857 { 2858 char errbuf[200]; 2859 2860 snprintf (errbuf, sizeof(errbuf)-1, 2861 _("Error: decryption/verification failed: %s\n"), 2862 gpgme_strerror (err)); 2863 state_puts (errbuf, s); 2864 } 2865 else 2866 { /* Decryption/Verification succeeded */ 2867 char *tmpfname; 2868 2869 { 2870 /* Check whether signatures have been verified. */ 2871 gpgme_verify_result_t verify_result; 2872 2873 verify_result = gpgme_op_verify_result (ctx); 2874 if (verify_result->signatures) 2875 sig_stat = 1; 2876 } 2877 2878 have_any_sigs = 0; 2879 maybe_goodsig = 0; 2880 if ((s->flags & MUTT_DISPLAY) && sig_stat) 2881 { 2882 int res, idx; 2883 int anybad = 0; 2884 2885 state_attach_puts (_("[-- Begin signature " 2886 "information --]\n"), s); 2887 have_any_sigs = 1; 2888 for (idx=0; 2889 (res = show_one_sig_status (ctx, idx, s)) != -1; 2890 idx++) 2891 { 2892 if (res == 1) 2893 anybad = 1; 2894 } 2895 if (!anybad && idx) 2896 maybe_goodsig = 1; 2897 2898 state_attach_puts (_("[-- End signature " 2899 "information --]\n\n"), s); 2900 } 2901 2902 tmpfname = data_object_to_tempfile (plaintext, NULL, &pgpout); 2903 if (!tmpfname) 2904 { 2905 pgpout = NULL; 2906 state_puts (_("Error: copy data failed\n"), s); 2907 } 2908 else 2909 { 2910 unlink (tmpfname); 2911 FREE (&tmpfname); 2912 } 2913 } 2914 gpgme_data_release (plaintext); 2915 gpgme_release (ctx); 2916 } 2917 2918 /* 2919 * Now, copy cleartext to the screen. NOTE - we expect that PGP 2920 * outputs utf-8 cleartext. This may not always be true, but it 2921 * seems to be a reasonable guess. 2922 */ 2923 2924 if (s->flags & MUTT_DISPLAY) 2925 { 2926 if (needpass) 2927 state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s); 2928 else if (pgp_keyblock) 2929 state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"), 2930 s); 2931 else 2932 state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"), 2933 s); 2934 } 2935 2936 if (clearsign) 2937 { 2938 copy_clearsigned (armored_data, s, body_charset); 2939 } 2940 else if (pgpout) 2941 { 2942 FGETCONV *fc; 2943 int c; 2944 rewind (pgpout); 2945 fc = fgetconv_open (pgpout, "utf-8", Charset, 0); 2946 while ((c = fgetconv (fc)) != EOF) 2947 { 2948 state_putc (c, s); 2949 if (c == '\n' && s->prefix) 2950 state_puts (s->prefix, s); 2951 } 2952 fgetconv_close (&fc); 2953 } 2954 2955 if (s->flags & MUTT_DISPLAY) 2956 { 2957 state_putc ('\n', s); 2958 if (needpass) 2959 state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s); 2960 else if (pgp_keyblock) 2961 state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s); 2962 else 2963 state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s); 2964 } 2965 2966 gpgme_data_release (armored_data); 2967 if (pgpout) 2968 { 2969 safe_fclose (&pgpout); 2970 } 2971 } 2972 else 2973 { 2974 /* A traditional PGP part may mix signed and unsigned content */ 2975 /* XXX - we may wish to recode here */ 2976 if (s->prefix) 2977 state_puts (s->prefix, s); 2978 state_puts (buf, s); 2979 } 2980 } 2981 2982 m->goodsig = (maybe_goodsig && have_any_sigs); 2983 2984 if (needpass == -1) 2985 { 2986 state_attach_puts (_("[-- Error: could not find beginning" 2987 " of PGP message! --]\n\n"), s); 2988 return 1; 2989 } 2990 dprint (2, (debugfile, "Leaving pgp_application_pgp handler\n")); 2991 2992 return err; 2993} 2994 2995/* 2996 * Implementation of `encrypted_handler'. 2997 */ 2998 2999/* MIME handler for pgp/mime encrypted messages. 3000 * This handler is passed the application/octet-stream directly. 3001 * The caller must propagate a->goodsig to its parent. 3002 */ 3003int pgp_gpgme_encrypted_handler (BODY *a, STATE *s) 3004{ 3005 BUFFER *tempfile = NULL; 3006 FILE *fpout; 3007 BODY *tattach; 3008 int is_signed; 3009 int rc = 0; 3010 3011 dprint (2, (debugfile, "Entering pgp_encrypted handler\n")); 3012 3013 /* Note: the handler calls mutt_body_handler() 3014 * so we don't use the pool for this operation. */ 3015 tempfile = mutt_buffer_new (); 3016 mutt_buffer_mktemp (tempfile); 3017 if (!(fpout = safe_fopen (mutt_b2s (tempfile), "w+"))) 3018 { 3019 if (s->flags & MUTT_DISPLAY) 3020 state_attach_puts (_("[-- Error: could not create temporary file! " 3021 "--]\n"), s); 3022 rc = -1; 3023 goto cleanup; 3024 } 3025 3026 tattach = decrypt_part (a, s, fpout, 0, &is_signed); 3027 if (tattach) 3028 { 3029 tattach->goodsig = is_signed > 0; 3030 3031 if (s->flags & MUTT_DISPLAY) 3032 { 3033 state_attach_puts (is_signed? 3034 _("[-- The following data is PGP/MIME signed and encrypted --]\n\n"): 3035 _("[-- The following data is PGP/MIME encrypted --]\n\n"), 3036 s); 3037 3038 mutt_protected_headers_handler (tattach, s); 3039 } 3040 3041 /* Store any protected headers in the parent so they can be 3042 * accessed for index updates after the handler recursion is done. 3043 * This is done before the handler to prevent a nested encrypted 3044 * handler from freeing the headers. */ 3045 mutt_free_envelope (&a->mime_headers); 3046 a->mime_headers = tattach->mime_headers; 3047 tattach->mime_headers = NULL; 3048 3049 { 3050 FILE *savefp = s->fpin; 3051 s->fpin = fpout; 3052 rc = mutt_body_handler (tattach, s); 3053 s->fpin = savefp; 3054 } 3055 3056 /* Embedded multipart signed protected headers override the 3057 * encrypted headers. We need to do this after the handler so 3058 * they can be printed in the pager. */ 3059 if (mutt_is_multipart_signed (tattach) && 3060 tattach->parts && 3061 tattach->parts->mime_headers) 3062 { 3063 mutt_free_envelope (&a->mime_headers); 3064 a->mime_headers = tattach->parts->mime_headers; 3065 tattach->parts->mime_headers = NULL; 3066 } 3067 3068 /* 3069 * if a multipart/signed is the _only_ sub-part of a 3070 * multipart/encrypted, cache signature verification 3071 * status. 3072 */ 3073 if (mutt_is_multipart_signed (tattach) && !tattach->next) 3074 a->goodsig |= tattach->goodsig; 3075 3076 if (s->flags & MUTT_DISPLAY) 3077 { 3078 state_puts ("\n", s); 3079 state_attach_puts (is_signed? 3080 _("[-- End of PGP/MIME signed and encrypted data --]\n"): 3081 _("[-- End of PGP/MIME encrypted data --]\n"), 3082 s); 3083 } 3084 3085 mutt_free_body (&tattach); 3086 mutt_message _("PGP message successfully decrypted."); 3087 } 3088 else 3089 { 3090 if (!option (OPTAUTOCRYPTGPGME)) 3091 { 3092 mutt_error _("Could not decrypt PGP message"); 3093 mutt_sleep (2); 3094 } 3095 rc = -1; 3096 } 3097 3098 safe_fclose (&fpout); 3099 mutt_unlink(mutt_b2s (tempfile)); 3100 dprint (2, (debugfile, "Leaving pgp_encrypted handler\n")); 3101 3102cleanup: 3103 mutt_buffer_free (&tempfile); 3104 return rc; 3105} 3106 3107/* Support for application/smime */ 3108int smime_gpgme_application_handler (BODY *a, STATE *s) 3109{ 3110 BUFFER *tempfile = NULL; 3111 FILE *fpout; 3112 BODY *tattach; 3113 int is_signed; 3114 int rc = 0; 3115 3116 dprint (2, (debugfile, "Entering smime_encrypted handler\n")); 3117 3118 /* clear out any mime headers before the handler, so they can't be 3119 * spoofed. */ 3120 mutt_free_envelope (&a->mime_headers); 3121 3122 a->warnsig = 0; 3123 3124 /* Note: the handler calls mutt_body_handler() 3125 * so we don't use the pool for this operation. */ 3126 tempfile = mutt_buffer_new (); 3127 mutt_buffer_mktemp (tempfile); 3128 if (!(fpout = safe_fopen (mutt_b2s (tempfile), "w+"))) 3129 { 3130 if (s->flags & MUTT_DISPLAY) 3131 state_attach_puts (_("[-- Error: could not create temporary file! " 3132 "--]\n"), s); 3133 rc = -1; 3134 goto cleanup; 3135 } 3136 3137 tattach = decrypt_part (a, s, fpout, 1, &is_signed); 3138 if (tattach) 3139 { 3140 tattach->goodsig = is_signed > 0; 3141 3142 if (s->flags & MUTT_DISPLAY) 3143 { 3144 state_attach_puts (is_signed? 3145 _("[-- The following data is S/MIME signed --]\n\n"): 3146 _("[-- The following data is S/MIME encrypted --]\n\n"), 3147 s); 3148 3149 mutt_protected_headers_handler (tattach, s); 3150 } 3151 3152 /* Store any protected headers in the parent so they can be 3153 * accessed for index updates after the handler recursion is done. 3154 * This is done before the handler to prevent a nested encrypted 3155 * handler from freeing the headers. */ 3156 mutt_free_envelope (&a->mime_headers); 3157 a->mime_headers = tattach->mime_headers; 3158 tattach->mime_headers = NULL; 3159 3160 { 3161 FILE *savefp = s->fpin; 3162 s->fpin = fpout; 3163 rc = mutt_body_handler (tattach, s); 3164 s->fpin = savefp; 3165 } 3166 3167 /* Embedded multipart signed protected headers override the 3168 * encrypted headers. We need to do this after the handler so 3169 * they can be printed in the pager. */ 3170 if (mutt_is_multipart_signed (tattach) && 3171 tattach->parts && 3172 tattach->parts->mime_headers) 3173 { 3174 mutt_free_envelope (&a->mime_headers); 3175 a->mime_headers = tattach->parts->mime_headers; 3176 tattach->parts->mime_headers = NULL; 3177 } 3178 3179 /* 3180 * if a multipart/signed is the _only_ sub-part of a 3181 * multipart/encrypted, cache signature verification 3182 * status. 3183 */ 3184 if (mutt_is_multipart_signed (tattach) && !tattach->next) 3185 { 3186 if (!(a->goodsig = tattach->goodsig)) 3187 a->warnsig = tattach->warnsig; 3188 } 3189 else if (tattach->goodsig) 3190 { 3191 a->goodsig = 1; 3192 a->warnsig = tattach->warnsig; 3193 } 3194 3195 if (s->flags & MUTT_DISPLAY) 3196 { 3197 state_puts ("\n", s); 3198 state_attach_puts (is_signed? 3199 _("[-- End of S/MIME signed data --]\n"): 3200 _("[-- End of S/MIME encrypted data --]\n"), 3201 s); 3202 } 3203 3204 mutt_free_body (&tattach); 3205 } 3206 3207 safe_fclose (&fpout); 3208 mutt_unlink(mutt_b2s (tempfile)); 3209 dprint (2, (debugfile, "Leaving smime_encrypted handler\n")); 3210 3211cleanup: 3212 mutt_buffer_free (&tempfile); 3213 return rc; 3214} 3215 3216 3217/* 3218 * Format an entry on the CRYPT key selection menu. 3219 * 3220 * %n number 3221 * %k key id %K key id of the principal key 3222 * %u user id 3223 * %a algorithm %A algorithm of the princ. key 3224 * %l length %L length of the princ. key 3225 * %f flags %F flags of the princ. key 3226 * %c capabilities %C capabilities of the princ. key 3227 * %t trust/validity of the key-uid association 3228 * %p protocol 3229 * %[...] date of key using strftime(3) 3230 */ 3231 3232static const char *crypt_entry_fmt (char *dest, 3233 size_t destlen, 3234 size_t col, 3235 int cols, 3236 char op, 3237 const char *src, 3238 const char *prefix, 3239 const char *ifstring, 3240 const char *elsestring, 3241 unsigned long data, 3242 format_flag flags) 3243{ 3244 char fmt[16]; 3245 crypt_entry_t *entry; 3246 crypt_key_t *key; 3247 int kflags = 0; 3248 int optional = (flags & MUTT_FORMAT_OPTIONAL); 3249 const char *s = NULL; 3250 unsigned long val; 3251 3252 entry = (crypt_entry_t *) data; 3253 key = entry->key; 3254 3255/* if (isupper ((unsigned char) op)) */ 3256/* key = pkey; */ 3257 3258 kflags = (key->flags /*| (pkey->flags & KEYFLAG_RESTRICTIONS) 3259 | uid->flags*/); 3260 3261 switch (ascii_tolower (op)) 3262 { 3263 case '[': 3264 { 3265 const char *cp; 3266 char buf2[SHORT_STRING], *p; 3267 int do_locales; 3268 struct tm *tm; 3269 size_t len; 3270 3271 p = dest; 3272 3273 cp = src; 3274 if (*cp == '!') 3275 { 3276 do_locales = 0; 3277 cp++; 3278 } 3279 else 3280 do_locales = 1; 3281 3282 len = destlen - 1; 3283 while (len > 0 && *cp != ']') 3284 { 3285 if (*cp == '%') 3286 { 3287 cp++; 3288 if (len >= 2) 3289 { 3290 *p++ = '%'; 3291 *p++ = *cp; 3292 len -= 2; 3293 } 3294 else 3295 break; /* not enough space */ 3296 cp++; 3297 } 3298 else 3299 { 3300 *p++ = *cp++; 3301 len--; 3302 } 3303 } 3304 *p = 0; 3305 3306 { 3307 time_t tt = 0; 3308 3309 if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0)) 3310 tt = key->kobj->subkeys->timestamp; 3311 3312 tm = localtime (&tt); 3313 } 3314 3315 if (!do_locales) 3316 setlocale (LC_TIME, "C"); 3317 strftime (buf2, sizeof (buf2), dest, tm); 3318 if (!do_locales) 3319 setlocale (LC_TIME, ""); 3320 3321 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 3322 snprintf (dest, destlen, fmt, buf2); 3323 if (len > 0) 3324 src = cp + 1; 3325 } 3326 break; 3327 case 'n': 3328 if (!optional) 3329 { 3330 snprintf (fmt, sizeof (fmt), "%%%sd", prefix); 3331 snprintf (dest, destlen, fmt, entry->num); 3332 } 3333 break; 3334 case 'k': 3335 if (!optional) 3336 { 3337 /* fixme: we need a way to distinguish between main and subkeys. 3338 Store the idx in entry? */ 3339 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 3340 snprintf (dest, destlen, fmt, crypt_keyid (key)); 3341 } 3342 break; 3343 case 'u': 3344 if (!optional) 3345 { 3346 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 3347 snprintf (dest, destlen, fmt, key->uid); 3348 } 3349 break; 3350 case 'a': 3351 if (!optional) 3352 { 3353 snprintf (fmt, sizeof (fmt), "%%%s.3s", prefix); 3354 if (key->kobj->subkeys) 3355 s = gpgme_pubkey_algo_name (key->kobj->subkeys->pubkey_algo); 3356 else 3357 s = "?"; 3358 snprintf (dest, destlen, fmt, s); 3359 } 3360 break; 3361 case 'l': 3362 if (!optional) 3363 { 3364 snprintf (fmt, sizeof (fmt), "%%%slu", prefix); 3365 if (key->kobj->subkeys) 3366 val = key->kobj->subkeys->length; 3367 else 3368 val = 0; 3369 snprintf (dest, destlen, fmt, val); 3370 } 3371 break; 3372 case 'f': 3373 if (!optional) 3374 { 3375 snprintf (fmt, sizeof (fmt), "%%%sc", prefix); 3376 snprintf (dest, destlen, fmt, crypt_flags (kflags)); 3377 } 3378 else if (!(kflags & (KEYFLAG_RESTRICTIONS))) 3379 optional = 0; 3380 break; 3381 case 'c': 3382 if (!optional) 3383 { 3384 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 3385 snprintf (dest, destlen, fmt, crypt_key_abilities (kflags)); 3386 } 3387 else if (!(kflags & (KEYFLAG_ABILITIES))) 3388 optional = 0; 3389 break; 3390 case 't': 3391 if ((kflags & KEYFLAG_ISX509)) 3392 s = "x"; 3393 else 3394 { 3395 switch (key->validity) 3396 { 3397 case GPGME_VALIDITY_UNDEFINED: 3398 s = "q"; 3399 break; 3400 case GPGME_VALIDITY_NEVER: 3401 s = "n"; 3402 break; 3403 case GPGME_VALIDITY_MARGINAL: 3404 s = "m"; 3405 break; 3406 case GPGME_VALIDITY_FULL: 3407 s = "f"; 3408 break; 3409 case GPGME_VALIDITY_ULTIMATE: 3410 s = "u"; 3411 break; 3412 case GPGME_VALIDITY_UNKNOWN: 3413 default: 3414 s = "?"; 3415 break; 3416 } 3417 } 3418 snprintf (fmt, sizeof (fmt), "%%%sc", prefix); 3419 snprintf (dest, destlen, fmt, s? *s: 'B'); 3420 break; 3421 case 'p': 3422 snprintf (fmt, sizeof (fmt), "%%%ss", prefix); 3423 snprintf (dest, destlen, fmt, 3424 gpgme_get_protocol_name (key->kobj->protocol)); 3425 break; 3426 3427 default: 3428 *dest = '\0'; 3429 } 3430 3431 if (optional) 3432 mutt_FormatString (dest, destlen, col, cols, ifstring, mutt_attach_fmt, data, 0); 3433 else if (flags & MUTT_FORMAT_OPTIONAL) 3434 mutt_FormatString (dest, destlen, col, cols, elsestring, mutt_attach_fmt, data, 0); 3435 return (src); 3436} 3437 3438/* Used by the display function to format a line. */ 3439static void crypt_entry (char *s, size_t l, MUTTMENU * menu, int num) 3440{ 3441 crypt_key_t **key_table = (crypt_key_t **) menu->data; 3442 crypt_entry_t entry; 3443 3444 entry.key = key_table[num]; 3445 entry.num = num + 1; 3446 3447 mutt_FormatString (s, l, 0, MuttIndexWindow->cols, NONULL (PgpEntryFormat), crypt_entry_fmt, 3448 (unsigned long) &entry, MUTT_FORMAT_ARROWCURSOR); 3449} 3450 3451/* Compare two addresses and the keyid to be used for sorting. */ 3452static int _crypt_compare_address (const void *a, const void *b) 3453{ 3454 crypt_key_t **s = (crypt_key_t **) a; 3455 crypt_key_t **t = (crypt_key_t **) b; 3456 int r; 3457 3458 if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid))) 3459 return r > 0; 3460 else 3461 return mutt_strcasecmp (crypt_fpr_or_lkeyid (*s), crypt_fpr_or_lkeyid (*t)) > 0; 3462} 3463 3464static int crypt_compare_address (const void *a, const void *b) 3465{ 3466 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_address (a, b) 3467 : _crypt_compare_address (a, b)); 3468} 3469 3470 3471/* Compare two key IDs and the addresses to be used for sorting. */ 3472static int _crypt_compare_keyid (const void *a, const void *b) 3473{ 3474 crypt_key_t **s = (crypt_key_t **) a; 3475 crypt_key_t **t = (crypt_key_t **) b; 3476 int r; 3477 3478 if ((r = mutt_strcasecmp (crypt_fpr_or_lkeyid (*s), crypt_fpr_or_lkeyid (*t)))) 3479 return r > 0; 3480 else 3481 return mutt_strcasecmp ((*s)->uid, (*t)->uid) > 0; 3482} 3483 3484static int crypt_compare_keyid (const void *a, const void *b) 3485{ 3486 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_keyid (a, b) 3487 : _crypt_compare_keyid (a, b)); 3488} 3489 3490/* Compare 2 creation dates and the addresses. For sorting. */ 3491static int _crypt_compare_date (const void *a, const void *b) 3492{ 3493 crypt_key_t **s = (crypt_key_t **) a; 3494 crypt_key_t **t = (crypt_key_t **) b; 3495 unsigned long ts = 0, tt = 0; 3496 3497 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0)) 3498 ts = (*s)->kobj->subkeys->timestamp; 3499 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0)) 3500 tt = (*t)->kobj->subkeys->timestamp; 3501 3502 if (ts > tt) 3503 return 1; 3504 if (ts < tt) 3505 return 0; 3506 3507 return mutt_strcasecmp ((*s)->uid, (*t)->uid) > 0; 3508} 3509 3510static int crypt_compare_date (const void *a, const void *b) 3511{ 3512 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_date (a, b) 3513 : _crypt_compare_date (a, b)); 3514} 3515 3516/* Compare two trust values, the key length, the creation dates. the 3517 addresses and the key IDs. For sorting. */ 3518static int _crypt_compare_trust (const void *a, const void *b) 3519{ 3520 crypt_key_t **s = (crypt_key_t **) a; 3521 crypt_key_t **t = (crypt_key_t **) b; 3522 unsigned long ts = 0, tt = 0; 3523 int r; 3524 3525 if ((r = (((*s)->flags & (KEYFLAG_RESTRICTIONS)) 3526 - ((*t)->flags & (KEYFLAG_RESTRICTIONS))))) 3527 return r > 0; 3528 3529 ts = (*s)->validity; 3530 tt = (*t)->validity; 3531 if ((r = (tt - ts))) 3532 return r < 0; 3533 3534 if ((*s)->kobj->subkeys) 3535 ts = (*s)->kobj->subkeys->length; 3536 if ((*t)->kobj->subkeys) 3537 tt = (*t)->kobj->subkeys->length; 3538 if (ts != tt) 3539 return ts > tt; 3540 3541 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0)) 3542 ts = (*s)->kobj->subkeys->timestamp; 3543 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0)) 3544 tt = (*t)->kobj->subkeys->timestamp; 3545 if (ts > tt) 3546 return 1; 3547 if (ts < tt) 3548 return 0; 3549 3550 if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid))) 3551 return r > 0; 3552 return (mutt_strcasecmp (crypt_fpr_or_lkeyid ((*s)), crypt_fpr_or_lkeyid ((*t)))) > 0; 3553} 3554 3555static int crypt_compare_trust (const void *a, const void *b) 3556{ 3557 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_trust (a, b) 3558 : _crypt_compare_trust (a, b)); 3559} 3560 3561/* Print the X.500 Distinguished Name part KEY from the array of parts 3562 DN to FP. */ 3563static int 3564print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key) 3565{ 3566 int any = 0; 3567 3568 for (; dn->key; dn++) 3569 { 3570 if (!strcmp (dn->key, key)) 3571 { 3572 if (any) 3573 fputs (" + ", fp); 3574 print_utf8 (fp, dn->value, strlen (dn->value)); 3575 any = 1; 3576 } 3577 } 3578 return any; 3579} 3580 3581/* Print all parts of a DN in a standard sequence. */ 3582static void 3583print_dn_parts (FILE *fp, struct dn_array_s *dn) 3584{ 3585 static const char * const stdpart[] = { 3586 "CN", "OU", "O", "STREET", "L", "ST", "C", NULL 3587 }; 3588 int any=0, any2=0, i; 3589 3590 for (i=0; stdpart[i]; i++) 3591 { 3592 if (any) 3593 fputs (", ", fp); 3594 any = print_dn_part (fp, dn, stdpart[i]); 3595 } 3596 /* now print the rest without any specific ordering */ 3597 for (; dn->key; dn++) 3598 { 3599 for (i=0; stdpart[i]; i++) 3600 { 3601 if (!strcmp (dn->key, stdpart[i])) 3602 break; 3603 } 3604 if (!stdpart[i]) 3605 { 3606 if (any) 3607 fputs (", ", fp); 3608 if (!any2) 3609 fputs ("(", fp); 3610 any = print_dn_part (fp, dn, dn->key); 3611 any2 = 1; 3612 } 3613 } 3614 if (any2) 3615 fputs (")", fp); 3616} 3617 3618 3619/* Parse an RDN; this is a helper to parse_dn(). */ 3620static const unsigned char * 3621parse_dn_part (struct dn_array_s *array, const unsigned char *string) 3622{ 3623 const unsigned char *s, *s1; 3624 size_t n; 3625 unsigned char *p; 3626 3627 /* parse attributeType */ 3628 for (s = string+1; *s && *s != '='; s++) 3629 ; 3630 if (!*s) 3631 return NULL; /* error */ 3632 n = s - string; 3633 if (!n) 3634 return NULL; /* empty key */ 3635 array->key = safe_malloc (n+1); 3636 p = (unsigned char *)array->key; 3637 memcpy (p, string, n); /* fixme: trim trailing spaces */ 3638 p[n] = 0; 3639 string = s + 1; 3640 3641 if (*string == '#') 3642 { /* hexstring */ 3643 string++; 3644 for (s=string; hexdigitp (s); s++) 3645 s++; 3646 n = s - string; 3647 if (!n || (n & 1)) 3648 return NULL; /* empty or odd number of digits */ 3649 n /= 2; 3650 p = safe_malloc (n+1); 3651 array->value = (char*)p; 3652 for (s1=string; n; s1 += 2, n--) 3653 *p++ = xtoi_2 (s1); 3654 *p = 0; 3655 } 3656 else 3657 { /* regular v3 quoted string */ 3658 for (n=0, s=string; *s; s++) 3659 { 3660 if (*s == '\\') 3661 { /* pair */ 3662 s++; 3663 if (*s == ',' || *s == '=' || *s == '+' 3664 || *s == '<' || *s == '>' || *s == '#' || *s == ';' 3665 || *s == '\\' || *s == '\"' || *s == ' ') 3666 n++; 3667 else if (hexdigitp (s) && hexdigitp (s+1)) 3668 { 3669 s++; 3670 n++; 3671 } 3672 else 3673 return NULL; /* invalid escape sequence */ 3674 } 3675 else if (*s == '\"') 3676 return NULL; /* invalid encoding */ 3677 else if (*s == ',' || *s == '=' || *s == '+' 3678 || *s == '<' || *s == '>' || *s == '#' || *s == ';' ) 3679 break; 3680 else 3681 n++; 3682 } 3683 3684 p = safe_malloc (n+1); 3685 array->value = (char*)p; 3686 for (s=string; n; s++, n--) 3687 { 3688 if (*s == '\\') 3689 { 3690 s++; 3691 if (hexdigitp (s)) 3692 { 3693 *p++ = xtoi_2 (s); 3694 s++; 3695 } 3696 else 3697 *p++ = *s; 3698 } 3699 else 3700 *p++ = *s; 3701 } 3702 *p = 0; 3703 } 3704 return s; 3705} 3706 3707 3708/* Parse a DN and return an array-ized one. This is not a validating 3709 parser and it does not support any old-stylish syntax; gpgme is 3710 expected to return only rfc2253 compatible strings. */ 3711static struct dn_array_s * 3712parse_dn (const unsigned char *string) 3713{ 3714 struct dn_array_s *array; 3715 size_t arrayidx, arraysize; 3716 int i; 3717 3718 arraysize = 7; /* C,ST,L,O,OU,CN,email */ 3719 array = safe_malloc ((arraysize+1) * sizeof *array); 3720 arrayidx = 0; 3721 while (*string) 3722 { 3723 while (*string == ' ') 3724 string++; 3725 if (!*string) 3726 break; /* ready */ 3727 if (arrayidx >= arraysize) 3728 { /* mutt lacks a real safe_realoc - so we need to copy */ 3729 struct dn_array_s *a2; 3730 3731 arraysize += 5; 3732 a2 = safe_malloc ((arraysize+1) * sizeof *array); 3733 for (i=0; i < arrayidx; i++) 3734 { 3735 a2[i].key = array[i].key; 3736 a2[i].value = array[i].value; 3737 } 3738 FREE (&array); 3739 array = a2; 3740 } 3741 array[arrayidx].key = NULL; 3742 array[arrayidx].value = NULL; 3743 string = parse_dn_part (array+arrayidx, string); 3744 arrayidx++; 3745 if (!string) 3746 goto failure; 3747 while (*string == ' ') 3748 string++; 3749 if (*string && *string != ',' && *string != ';' && *string != '+') 3750 goto failure; /* invalid delimiter */ 3751 if (*string) 3752 string++; 3753 } 3754 array[arrayidx].key = NULL; 3755 array[arrayidx].value = NULL; 3756 return array; 3757 3758 failure: 3759 for (i=0; i < arrayidx; i++) 3760 { 3761 FREE (&array[i].key); 3762 FREE (&array[i].value); 3763 } 3764 FREE (&array); 3765 return NULL; 3766} 3767 3768 3769/* Print a nice representation of the USERID and make sure it is 3770 displayed in a proper way, which does mean to reorder some parts 3771 for S/MIME's DNs. USERID is a string as returned by the gpgme key 3772 functions. It is utf-8 encoded. */ 3773static void 3774parse_and_print_user_id (FILE *fp, const char *userid) 3775{ 3776 const char *s; 3777 int i; 3778 3779 if (*userid == '<') 3780 { 3781 s = strchr (userid+1, '>'); 3782 if (s) 3783 print_utf8 (fp, userid+1, s-userid-1); 3784 } 3785 else if (*userid == '(') 3786 fputs (_("[Can't display this user ID (unknown encoding)]"), fp); 3787 else if (!digit_or_letter ((const unsigned char *)userid)) 3788 fputs (_("[Can't display this user ID (invalid encoding)]"), fp); 3789 else 3790 { 3791 struct dn_array_s *dn = parse_dn ((const unsigned char *)userid); 3792 if (!dn) 3793 fputs (_("[Can't display this user ID (invalid DN)]"), fp); 3794 else 3795 { 3796 print_dn_parts (fp, dn); 3797 for (i=0; dn[i].key; i++) 3798 { 3799 FREE (&dn[i].key); 3800 FREE (&dn[i].value); 3801 } 3802 FREE (&dn); 3803 } 3804 } 3805} 3806 3807typedef enum 3808 { 3809 KEY_CAP_CAN_ENCRYPT, 3810 KEY_CAP_CAN_SIGN, 3811 KEY_CAP_CAN_CERTIFY 3812 } 3813key_cap_t; 3814 3815static unsigned int 3816key_check_cap (gpgme_key_t key, key_cap_t cap) 3817{ 3818 gpgme_subkey_t subkey = NULL; 3819 unsigned int ret = 0; 3820 3821 switch (cap) 3822 { 3823 case KEY_CAP_CAN_ENCRYPT: 3824 if (! (ret = key->can_encrypt)) 3825 for (subkey = key->subkeys; subkey; subkey = subkey->next) 3826 if ((ret = subkey->can_encrypt)) 3827 break; 3828 break; 3829 case KEY_CAP_CAN_SIGN: 3830 if (! (ret = key->can_sign)) 3831 for (subkey = key->subkeys; subkey; subkey = subkey->next) 3832 if ((ret = subkey->can_sign)) 3833 break; 3834 break; 3835 case KEY_CAP_CAN_CERTIFY: 3836 if (! (ret = key->can_certify)) 3837 for (subkey = key->subkeys; subkey; subkey = subkey->next) 3838 if ((ret = subkey->can_certify)) 3839 break; 3840 break; 3841 } 3842 3843 return ret; 3844} 3845 3846enum 3847{ 3848 KIP_NAME = 0, 3849 KIP_AKA, 3850 KIP_VALID_FROM, 3851 KIP_VALID_TO, 3852 KIP_KEY_TYPE, 3853 KIP_KEY_USAGE, 3854 KIP_FINGERPRINT, 3855 KIP_SERIAL_NO, 3856 KIP_ISSUED_BY, 3857 KIP_SUBKEY, 3858 KIP_END 3859}; 3860 3861static const char * const KeyInfoPrompts[] = 3862{ 3863 /* L10N: 3864 * The following are the headers for the "verify key" output from the 3865 * GPGME key selection menu (bound to "c" in the key selection menu). 3866 * They will be automatically aligned. */ 3867 N_("Name: "), 3868 N_("aka: "), 3869 N_("Valid From: "), 3870 N_("Valid To: "), 3871 N_("Key Type: "), 3872 N_("Key Usage: "), 3873 N_("Fingerprint: "), 3874 N_("Serial-No: "), 3875 N_("Issued By: "), 3876 N_("Subkey: ") 3877}; 3878 3879int KeyInfoPadding[KIP_END] = { 0 }; 3880 3881/* Print verbose information about a key or certificate to FP. */ 3882static void print_key_info (gpgme_key_t key, FILE *fp) 3883{ 3884 int idx; 3885 const char *s = NULL, *s2 = NULL; 3886 time_t tt = 0; 3887 struct tm *tm; 3888 char shortbuf[SHORT_STRING]; 3889 unsigned long aval = 0; 3890 const char *delim; 3891 int is_pgp = 0; 3892 int i; 3893 gpgme_user_id_t uid = NULL; 3894 static int max_header_width = 0; 3895 int width; 3896 3897 if (!max_header_width) 3898 { 3899 for (i = 0; i < KIP_END; i++) 3900 { 3901 KeyInfoPadding[i] = mutt_strlen (_(KeyInfoPrompts[i])); 3902 width = mutt_strwidth (_(KeyInfoPrompts[i])); 3903 if (max_header_width < width) 3904 max_header_width = width; 3905 KeyInfoPadding[i] -= width; 3906 } 3907 for (i = 0; i < KIP_END; i++) 3908 KeyInfoPadding[i] += max_header_width; 3909 } 3910 3911 is_pgp = key->protocol == GPGME_PROTOCOL_OpenPGP; 3912 3913 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) 3914 { 3915 if (uid->revoked) 3916 continue; 3917 3918 s = uid->uid; 3919 3920 if (!idx) 3921 fprintf (fp, "%*s", KeyInfoPadding[KIP_NAME], _(KeyInfoPrompts[KIP_NAME])); 3922 else 3923 fprintf (fp, "%*s", KeyInfoPadding[KIP_AKA], _(KeyInfoPrompts[KIP_AKA])); 3924 if (uid->invalid) 3925 { 3926 /* L10N: comes after the Name or aka if the key is invalid */ 3927 fputs (_("[Invalid]"), fp); 3928 putc (' ', fp); 3929 } 3930 if (is_pgp) 3931 print_utf8 (fp, s, strlen(s)); 3932 else 3933 parse_and_print_user_id (fp, s); 3934 putc ('\n', fp); 3935 } 3936 3937 if (key->subkeys && (key->subkeys->timestamp > 0)) 3938 { 3939 tt = key->subkeys->timestamp; 3940 3941 tm = localtime (&tt); 3942#ifdef HAVE_LANGINFO_D_T_FMT 3943 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm); 3944#else 3945 strftime (shortbuf, sizeof shortbuf, "%c", tm); 3946#endif 3947 fprintf (fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_FROM], 3948 _(KeyInfoPrompts[KIP_VALID_FROM]), shortbuf); 3949 } 3950 3951 if (key->subkeys && (key->subkeys->expires > 0)) 3952 { 3953 tt = key->subkeys->expires; 3954 3955 tm = localtime (&tt); 3956#ifdef HAVE_LANGINFO_D_T_FMT 3957 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm); 3958#else 3959 strftime (shortbuf, sizeof shortbuf, "%c", tm); 3960#endif 3961 fprintf (fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_TO], 3962 _(KeyInfoPrompts[KIP_VALID_TO]), shortbuf); 3963 } 3964 3965 if (key->subkeys) 3966 s = gpgme_pubkey_algo_name (key->subkeys->pubkey_algo); 3967 else 3968 s = "?"; 3969 3970 s2 = is_pgp ? "PGP" : "X.509"; 3971 3972 if (key->subkeys) 3973 aval = key->subkeys->length; 3974 3975 fprintf (fp, "%*s", KeyInfoPadding[KIP_KEY_TYPE], 3976 _(KeyInfoPrompts[KIP_KEY_TYPE])); 3977 /* L10N: This is printed after "Key Type: " and looks like this: 3978 * PGP, 2048 bit RSA */ 3979 fprintf (fp, _("%s, %lu bit %s\n"), s2, aval, s); 3980 3981 fprintf (fp, "%*s", KeyInfoPadding[KIP_KEY_USAGE], 3982 _(KeyInfoPrompts[KIP_KEY_USAGE])); 3983 delim = ""; 3984 3985 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) 3986 { 3987 /* L10N: value in Key Usage: field */ 3988 fprintf (fp, "%s%s", delim, _("encryption")); 3989 delim = _(", "); 3990 } 3991 if (key_check_cap (key, KEY_CAP_CAN_SIGN)) 3992 { 3993 /* L10N: value in Key Usage: field */ 3994 fprintf (fp, "%s%s", delim, _("signing")); 3995 delim = _(", "); 3996 } 3997 if (key_check_cap (key, KEY_CAP_CAN_CERTIFY)) 3998 { 3999 /* L10N: value in Key Usage: field */ 4000 fprintf (fp, "%s%s", delim, _("certification")); 4001 delim = _(", "); 4002 } 4003 putc ('\n', fp); 4004 4005 if (key->subkeys) 4006 { 4007 s = key->subkeys->fpr; 4008 fprintf (fp, "%*s", KeyInfoPadding[KIP_FINGERPRINT], 4009 _(KeyInfoPrompts[KIP_FINGERPRINT])); 4010 if (is_pgp && strlen (s) == 40) 4011 { 4012 for (i=0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) 4013 { 4014 putc (*s, fp); 4015 putc (s[1], fp); 4016 putc (s[2], fp); 4017 putc (s[3], fp); 4018 putc (is_pgp? ' ':':', fp); 4019 if (is_pgp && i == 4) 4020 putc (' ', fp); 4021 } 4022 } 4023 else 4024 { 4025 for (i=0; *s && s[1] && s[2]; s += 2, i++) 4026 { 4027 putc (*s, fp); 4028 putc (s[1], fp); 4029 putc (is_pgp? ' ':':', fp); 4030 if (is_pgp && i == 7) 4031 putc (' ', fp); 4032 } 4033 } 4034 fprintf (fp, "%s\n", s); 4035 } 4036 4037 if (key->issuer_serial) 4038 { 4039 s = key->issuer_serial; 4040 if (s) 4041 fprintf (fp, "%*s0x%s\n", KeyInfoPadding[KIP_SERIAL_NO], 4042 _(KeyInfoPrompts[KIP_SERIAL_NO]), s); 4043 } 4044 4045 if (key->issuer_name) 4046 { 4047 s = key->issuer_name; 4048 if (s) 4049 { 4050 fprintf (fp, "%*s", KeyInfoPadding[KIP_ISSUED_BY], 4051 _(KeyInfoPrompts[KIP_ISSUED_BY])); 4052 parse_and_print_user_id (fp, s); 4053 putc ('\n', fp); 4054 } 4055 } 4056 4057 /* For PGP we list all subkeys. */ 4058 if (is_pgp) 4059 { 4060 gpgme_subkey_t subkey = NULL; 4061 4062 for (idx = 1, subkey = key->subkeys; subkey; 4063 idx++, subkey = subkey->next) 4064 { 4065 s = subkey->keyid; 4066 4067 putc ('\n', fp); 4068 if ( strlen (s) == 16) 4069 s += 8; /* display only the short keyID */ 4070 fprintf (fp, "%*s0x%s", KeyInfoPadding[KIP_SUBKEY], 4071 _(KeyInfoPrompts[KIP_SUBKEY]), s); 4072 if (subkey->revoked) 4073 { 4074 putc (' ', fp); 4075 /* L10N: describes a subkey */ 4076 fputs (_("[Revoked]"), fp); 4077 } 4078 if (subkey->invalid) 4079 { 4080 putc (' ', fp); 4081 /* L10N: describes a subkey */ 4082 fputs (_("[Invalid]"), fp); 4083 } 4084 if (subkey->expired) 4085 { 4086 putc (' ', fp); 4087 /* L10N: describes a subkey */ 4088 fputs (_("[Expired]"), fp); 4089 } 4090 if (subkey->disabled) 4091 { 4092 putc (' ', fp); 4093 /* L10N: describes a subkey */ 4094 fputs (_("[Disabled]"), fp); 4095 } 4096 putc ('\n', fp); 4097 4098 if (subkey->timestamp > 0) 4099 { 4100 tt = subkey->timestamp; 4101 4102 tm = localtime (&tt); 4103#ifdef HAVE_LANGINFO_D_T_FMT 4104 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm); 4105#else 4106 strftime (shortbuf, sizeof shortbuf, "%c", tm); 4107#endif 4108 fprintf (fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_FROM], 4109 _(KeyInfoPrompts[KIP_VALID_FROM]), shortbuf); 4110 } 4111 4112 if (subkey->expires > 0) 4113 { 4114 tt = subkey->expires; 4115 4116 tm = localtime (&tt); 4117#ifdef HAVE_LANGINFO_D_T_FMT 4118 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm); 4119#else 4120 strftime (shortbuf, sizeof shortbuf, "%c", tm); 4121#endif 4122 fprintf (fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_TO], 4123 _(KeyInfoPrompts[KIP_VALID_TO]), shortbuf); 4124 } 4125 4126 if (subkey) 4127 s = gpgme_pubkey_algo_name (subkey->pubkey_algo); 4128 else 4129 s = "?"; 4130 4131 if (subkey) 4132 aval = subkey->length; 4133 else 4134 aval = 0; 4135 4136 fprintf (fp, "%*s", KeyInfoPadding[KIP_KEY_TYPE], 4137 _(KeyInfoPrompts[KIP_KEY_TYPE])); 4138 fprintf (fp, _("%s, %lu bit %s\n"), "PGP", aval, s); 4139 4140 fprintf (fp, "%*s", KeyInfoPadding[KIP_KEY_USAGE], 4141 _(KeyInfoPrompts[KIP_KEY_USAGE])); 4142 delim = ""; 4143 4144 if (subkey->can_encrypt) 4145 { 4146 fprintf (fp, "%s%s", delim, _("encryption")); 4147 delim = _(", "); 4148 } 4149 if (subkey->can_sign) 4150 { 4151 fprintf (fp, "%s%s", delim, _("signing")); 4152 delim = _(", "); 4153 } 4154 if (subkey->can_certify) 4155 { 4156 fprintf (fp, "%s%s", delim, _("certification")); 4157 delim = _(", "); 4158 } 4159 putc ('\n', fp); 4160 } 4161 } 4162} 4163 4164 4165/* Show detailed information about the selected key */ 4166static void 4167verify_key (crypt_key_t *key) 4168{ 4169 FILE *fp; 4170 char cmd[LONG_STRING]; 4171 BUFFER *tempfile = NULL; 4172 const char *s; 4173 gpgme_ctx_t listctx = NULL; 4174 gpgme_error_t err; 4175 gpgme_key_t k = NULL; 4176 int maxdepth = 100; 4177 4178 /* because of the do_pager() call below, we avoid using the buffer pool */ 4179 tempfile = mutt_buffer_new (); 4180 mutt_buffer_mktemp (tempfile); 4181 if (!(fp = safe_fopen (mutt_b2s (tempfile), "w"))) 4182 { 4183 mutt_perror _("Can't create temporary file"); 4184 goto cleanup; 4185 } 4186 mutt_message _("Collecting data..."); 4187 4188 print_key_info (key->kobj, fp); 4189 4190 listctx = create_gpgme_context ((key->flags & KEYFLAG_ISX509)); 4191 4192 k = key->kobj; 4193 gpgme_key_ref (k); 4194 while ((s = k->chain_id) && k->subkeys && strcmp (s, k->subkeys->fpr) ) 4195 { 4196 putc ('\n', fp); 4197 err = gpgme_op_keylist_start (listctx, s, 0); 4198 gpgme_key_unref (k); 4199 k = NULL; 4200 if (!err) 4201 err = gpgme_op_keylist_next (listctx, &k); 4202 if (err) 4203 { 4204 fprintf (fp, _("Error finding issuer key: %s\n"), 4205 gpgme_strerror (err)); 4206 goto leave; 4207 } 4208 gpgme_op_keylist_end (listctx); 4209 4210 print_key_info (k, fp); 4211 if (!--maxdepth) 4212 { 4213 putc ('\n', fp); 4214 fputs (_("Error: certification chain too long - stopping here\n"), 4215 fp); 4216 break; 4217 } 4218 } 4219 4220 leave: 4221 gpgme_key_unref (k); 4222 gpgme_release (listctx); 4223 safe_fclose (&fp); 4224 mutt_clear_error (); 4225 snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"), crypt_keyid (key)); 4226 mutt_do_pager (cmd, mutt_b2s (tempfile), 0, NULL); 4227 4228cleanup: 4229 mutt_buffer_free (&tempfile); 4230} 4231 4232/* 4233 * Implementation of `findkeys'. 4234 */ 4235 4236 4237/* Convert LIST into a pattern string suitable to be passed to GPGME. 4238 We need to convert spaces in an item into a '+' and '%' into 4239 "%25". */ 4240static char *list_to_pattern (LIST *list) 4241{ 4242 LIST *l; 4243 char *pattern, *p; 4244 const char *s; 4245 size_t n; 4246 4247 n = 0; 4248 for (l=list; l; l = l->next) 4249 { 4250 for (s = l->data; *s; s++) 4251 { 4252 if (*s == '%' || *s == '+') 4253 n += 2; 4254 n++; 4255 } 4256 n++; /* delimiter or end of string */ 4257 } 4258 n++; /* make sure to allocate at least one byte */ 4259 pattern = p = safe_calloc (1,n); 4260 for (l=list; l; l = l->next) 4261 { 4262 s = l->data; 4263 if (*s) 4264 { 4265 if (l != list) 4266 *p++ = ' '; 4267 for (s = l->data; *s; s++) 4268 { 4269 if (*s == '%') 4270 { 4271 *p++ = '%'; 4272 *p++ = '2'; 4273 *p++ = '5'; 4274 } 4275 else if (*s == '+') 4276 { 4277 *p++ = '%'; 4278 *p++ = '2'; 4279 *p++ = 'B'; 4280 } 4281 else if (*s == ' ') 4282 *p++ = '+'; 4283 else 4284 *p++ = *s; 4285 } 4286 } 4287 } 4288 *p = 0; 4289 return pattern; 4290} 4291 4292/* Return a list of keys which are candidates for the selection. 4293 Select by looking at the HINTS list. */ 4294static crypt_key_t *get_candidates (LIST * hints, unsigned int app, int secret) 4295{ 4296 crypt_key_t *db, *k, **kend; 4297 char *pattern; 4298 gpgme_error_t err; 4299 gpgme_ctx_t ctx; 4300 gpgme_key_t key; 4301 int idx; 4302 gpgme_user_id_t uid = NULL; 4303 4304 pattern = list_to_pattern (hints); 4305 if (!pattern) 4306 return NULL; 4307 4308 ctx = create_gpgme_context (0); 4309 db = NULL; 4310 kend = &db; 4311 4312 if ((app & APPLICATION_PGP)) 4313 { 4314 /* Its all a mess. That old GPGME expects different things 4315 depending on the protocol. For gpg we don' t need percent 4316 escaped pappert but simple strings passed in an array to the 4317 keylist_ext_start function. */ 4318 LIST *l; 4319 size_t n; 4320 char **patarr; 4321 4322 for (l=hints, n=0; l; l = l->next) 4323 { 4324 if (l->data && *l->data) 4325 n++; 4326 } 4327 if (!n) 4328 goto no_pgphints; 4329 4330 patarr = safe_calloc (n+1, sizeof *patarr); 4331 for (l=hints, n=0; l; l = l->next) 4332 { 4333 if (l->data && *l->data) 4334 patarr[n++] = safe_strdup (l->data); 4335 } 4336 patarr[n] = NULL; 4337 err = gpgme_op_keylist_ext_start (ctx, (const char**)patarr, secret, 0); 4338 for (n=0; patarr[n]; n++) 4339 FREE (&patarr[n]); 4340 FREE (&patarr); 4341 if (err) 4342 { 4343 mutt_error (_("gpgme_op_keylist_start failed: %s"), 4344 gpgme_strerror (err)); 4345 gpgme_release (ctx); 4346 FREE (&pattern); 4347 return NULL; 4348 } 4349 4350 while (!(err = gpgme_op_keylist_next (ctx, &key)) ) 4351 { 4352 unsigned int flags = 0; 4353 4354 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) 4355 flags |= KEYFLAG_CANENCRYPT; 4356 if (key_check_cap (key, KEY_CAP_CAN_SIGN)) 4357 flags |= KEYFLAG_CANSIGN; 4358 4359 if (key->revoked) 4360 flags |= KEYFLAG_REVOKED; 4361 if (key->expired) 4362 flags |= KEYFLAG_EXPIRED; 4363 if (key->disabled) 4364 flags |= KEYFLAG_DISABLED; 4365 4366 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) 4367 { 4368 k = safe_calloc (1, sizeof *k); 4369 k->kobj = key; 4370 gpgme_key_ref (k->kobj); 4371 k->idx = idx; 4372 k->uid = uid->uid; 4373 k->flags = flags; 4374 if (uid->revoked) 4375 k->flags |= KEYFLAG_REVOKED; 4376 k->validity = uid->validity; 4377 *kend = k; 4378 kend = &k->next; 4379 } 4380 gpgme_key_unref (key); 4381 } 4382 if (gpg_err_code (err) != GPG_ERR_EOF) 4383 mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err)); 4384 gpgme_op_keylist_end (ctx); 4385 no_pgphints: 4386 ; 4387 } 4388 4389 if ((app & APPLICATION_SMIME)) 4390 { 4391 /* and now look for x509 certificates */ 4392 gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); 4393 err = gpgme_op_keylist_start (ctx, pattern, 0); 4394 if (err) 4395 { 4396 mutt_error (_("gpgme_op_keylist_start failed: %s"), 4397 gpgme_strerror (err)); 4398 gpgme_release (ctx); 4399 FREE (&pattern); 4400 return NULL; 4401 } 4402 4403 while (!(err = gpgme_op_keylist_next (ctx, &key)) ) 4404 { 4405 unsigned int flags = KEYFLAG_ISX509; 4406 4407 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) 4408 flags |= KEYFLAG_CANENCRYPT; 4409 if (key_check_cap (key, KEY_CAP_CAN_SIGN)) 4410 flags |= KEYFLAG_CANSIGN; 4411 4412 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) 4413 { 4414 k = safe_calloc (1, sizeof *k); 4415 k->kobj = key; 4416 gpgme_key_ref (k->kobj); 4417 k->idx = idx; 4418 k->uid = uid->uid; 4419 k->flags = flags; 4420 k->validity = uid->validity; 4421 *kend = k; 4422 kend = &k->next; 4423 } 4424 gpgme_key_unref (key); 4425 } 4426 if (gpg_err_code (err) != GPG_ERR_EOF) 4427 mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err)); 4428 gpgme_op_keylist_end (ctx); 4429 } 4430 4431 gpgme_release (ctx); 4432 FREE (&pattern); 4433 return db; 4434} 4435 4436/* Add the string STR to the list HINTS. This list is later used to 4437 match addresses. */ 4438static LIST *crypt_add_string_to_hints (LIST *hints, const char *str) 4439{ 4440 char *scratch; 4441 char *t; 4442 4443 if ((scratch = safe_strdup (str)) == NULL) 4444 return hints; 4445 4446 for (t = strtok (scratch, " ,.:\"()<>\n"); t; 4447 t = strtok (NULL, " ,.:\"()<>\n")) 4448 { 4449 if (strlen (t) > 3) 4450 hints = mutt_add_list (hints, t); 4451 } 4452 4453 FREE (&scratch); 4454 return hints; 4455} 4456 4457/* Display a menu to select a key from the array KEYS. FORCED_VALID 4458 will be set to true on return if the user did override the the 4459 key's validity. */ 4460static crypt_key_t *crypt_select_key (crypt_key_t *keys, 4461 ADDRESS * p, const char *s, 4462 unsigned int app, int *forced_valid) 4463{ 4464 int keymax; 4465 crypt_key_t **key_table; 4466 MUTTMENU *menu; 4467 int i, done = 0; 4468 char helpstr[LONG_STRING], buf[LONG_STRING]; 4469 crypt_key_t *k; 4470 int (*f) (const void *, const void *); 4471 int menu_to_use = 0; 4472 int unusable = 0; 4473 4474 *forced_valid = 0; 4475 4476 /* build the key table */ 4477 keymax = i = 0; 4478 key_table = NULL; 4479 for (k = keys; k; k = k->next) 4480 { 4481 if (!option (OPTPGPSHOWUNUSABLE) && (k->flags & KEYFLAG_CANTUSE)) 4482 { 4483 unusable = 1; 4484 continue; 4485 } 4486 4487 if (i == keymax) 4488 { 4489 keymax += 20; 4490 safe_realloc (&key_table, sizeof (crypt_key_t*)*keymax); 4491 } 4492 4493 key_table[i++] = k; 4494 } 4495 4496 if (!i && unusable) 4497 { 4498 mutt_error _("All matching keys are marked expired/revoked."); 4499 mutt_sleep (1); 4500 return NULL; 4501 } 4502 4503 switch (PgpSortKeys & SORT_MASK) 4504 { 4505 case SORT_DATE: 4506 f = crypt_compare_date; 4507 break; 4508 case SORT_KEYID: 4509 f = crypt_compare_keyid; 4510 break; 4511 case SORT_ADDRESS: 4512 f = crypt_compare_address; 4513 break; 4514 case SORT_TRUST: 4515 default: 4516 f = crypt_compare_trust; 4517 break; 4518 } 4519 qsort (key_table, i, sizeof (crypt_key_t*), f); 4520 4521 if (app & APPLICATION_PGP) 4522 menu_to_use = MENU_KEY_SELECT_PGP; 4523 else if (app & APPLICATION_SMIME) 4524 menu_to_use = MENU_KEY_SELECT_SMIME; 4525 4526 helpstr[0] = 0; 4527 mutt_make_help (buf, sizeof (buf), _("Exit "), menu_to_use, OP_EXIT); 4528 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ 4529 mutt_make_help (buf, sizeof (buf), _("Select "), menu_to_use, 4530 OP_GENERIC_SELECT_ENTRY); 4531 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ 4532 mutt_make_help (buf, sizeof (buf), _("Check key "), 4533 menu_to_use, OP_VERIFY_KEY); 4534 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ 4535 mutt_make_help (buf, sizeof (buf), _("Help"), menu_to_use, OP_HELP); 4536 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ 4537 4538 menu = mutt_new_menu (menu_to_use); 4539 menu->max = i; 4540 menu->make_entry = crypt_entry; 4541 menu->help = helpstr; 4542 menu->data = key_table; 4543 mutt_push_current_menu (menu); 4544 4545 { 4546 const char *ts; 4547 4548 if ((app & APPLICATION_PGP) && (app & APPLICATION_SMIME)) 4549 ts = _("PGP and S/MIME keys matching"); 4550 else if ((app & APPLICATION_PGP)) 4551 ts = _("PGP keys matching"); 4552 else if ((app & APPLICATION_SMIME)) 4553 ts = _("S/MIME keys matching"); 4554 else 4555 ts = _("keys matching"); 4556 4557 if (p) 4558 /* L10N: 4559 %1$s is one of the previous four entries. 4560 %2$s is an address. 4561 e.g. "S/MIME keys matching <me@mutt.org>." */ 4562 snprintf (buf, sizeof (buf), _("%s <%s>."), ts, p->mailbox); 4563 else 4564 /* L10N: 4565 e.g. 'S/MIME keys matching "Michael Elkins".' */ 4566 snprintf (buf, sizeof (buf), _("%s \"%s\"."), ts, s); 4567 menu->title = buf; 4568 } 4569 4570 mutt_clear_error (); 4571 k = NULL; 4572 while (!done) 4573 { 4574 *forced_valid = 0; 4575 switch (mutt_menuLoop (menu)) 4576 { 4577 case OP_VERIFY_KEY: 4578 verify_key (key_table[menu->current]); 4579 menu->redraw = REDRAW_FULL; 4580 break; 4581 4582 case OP_VIEW_ID: 4583 mutt_message ("%s", key_table[menu->current]->uid); 4584 break; 4585 4586 case OP_GENERIC_SELECT_ENTRY: 4587 /* FIXME make error reporting more verbose - this should be 4588 easy because gpgme provides more information */ 4589 if (option (OPTPGPCHECKTRUST)) 4590 { 4591 if (!crypt_key_is_valid (key_table[menu->current])) 4592 { 4593 mutt_error _("This key can't be used: " 4594 "expired/disabled/revoked."); 4595 break; 4596 } 4597 } 4598 4599 if (option (OPTPGPCHECKTRUST) && 4600 (!crypt_id_is_valid (key_table[menu->current]) 4601 || !crypt_id_is_strong (key_table[menu->current]))) 4602 { 4603 const char *warn_s; 4604 char buff[LONG_STRING]; 4605 4606 if (key_table[menu->current]->flags & KEYFLAG_CANTUSE) 4607 warn_s = N_("ID is expired/disabled/revoked."); 4608 else 4609 { 4610 warn_s = "??"; 4611 switch (key_table[menu->current]->validity) 4612 { 4613 case GPGME_VALIDITY_UNKNOWN: 4614 case GPGME_VALIDITY_UNDEFINED: 4615 warn_s = N_("ID has undefined validity."); 4616 break; 4617 case GPGME_VALIDITY_NEVER: 4618 warn_s = N_("ID is not valid."); 4619 break; 4620 case GPGME_VALIDITY_MARGINAL: 4621 warn_s = N_("ID is only marginally valid."); 4622 break; 4623 case GPGME_VALIDITY_FULL: 4624 case GPGME_VALIDITY_ULTIMATE: 4625 break; 4626 } 4627 } 4628 4629 snprintf (buff, sizeof (buff), 4630 _("%s Do you really want to use the key?"), 4631 _(warn_s)); 4632 4633 if (mutt_yesorno (buff, 0) != 1) 4634 { 4635 mutt_clear_error (); 4636 break; 4637 } 4638 4639 /* A '!' is appended to a key in find_keys() when forced_valid is 4640 * set. Prior to gpgme 1.11.0, encrypt_gpgme_object() called 4641 * create_recipient_set() which interpreted the '!' to mean set 4642 * GPGME_VALIDITY_FULL for the key. 4643 * 4644 * Starting in gpgme 1.11.0, we now use a '\n' delimited recipient 4645 * string, which is passed directly to the gpgme_op_encrypt_ext() 4646 * function. This allows to use the original meaning of '!' to 4647 * force a subkey use. */ 4648#if GPGME_VERSION_NUMBER < 0x010b00 /* gpgme < 1.11.0 */ 4649 *forced_valid = 1; 4650#endif 4651 } 4652 4653 k = crypt_copy_key (key_table[menu->current]); 4654 done = 1; 4655 break; 4656 4657 case OP_EXIT: 4658 k = NULL; 4659 done = 1; 4660 break; 4661 } 4662 } 4663 4664 mutt_pop_current_menu (menu); 4665 mutt_menuDestroy (&menu); 4666 FREE (&key_table); 4667 4668 return k; 4669} 4670 4671static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities, 4672 unsigned int app, int *forced_valid, 4673 int oppenc_mode) 4674{ 4675 ADDRESS *r, *p; 4676 LIST *hints = NULL; 4677 4678 int multi = 0; 4679 int this_key_has_strong; 4680 int this_key_has_addr_match; 4681 int match; 4682 4683 crypt_key_t *keys, *k; 4684 crypt_key_t *the_strong_valid_key = NULL; 4685 crypt_key_t *a_valid_addrmatch_key = NULL; 4686 crypt_key_t *matches = NULL; 4687 crypt_key_t **matches_endp = &matches; 4688 4689 *forced_valid = 0; 4690 4691 if (a && a->mailbox) 4692 hints = crypt_add_string_to_hints (hints, a->mailbox); 4693 if (a && a->personal) 4694 hints = crypt_add_string_to_hints (hints, a->personal); 4695 4696 if (! oppenc_mode ) 4697 mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox); 4698 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN) ); 4699 4700 mutt_free_list (&hints); 4701 4702 if (!keys) 4703 return NULL; 4704 4705 dprint (5, (debugfile, "crypt_getkeybyaddr: looking for %s <%s>.", 4706 a->personal, a->mailbox)); 4707 4708 for (k = keys; k; k = k->next) 4709 { 4710 dprint (5, (debugfile, " looking at key: %s `%.15s'\n", 4711 crypt_keyid (k), k->uid)); 4712 4713 if (abilities && !(k->flags & abilities)) 4714 { 4715 dprint (5, (debugfile, " insufficient abilities: Has %x, want %x\n", 4716 k->flags, abilities)); 4717 continue; 4718 } 4719 4720 this_key_has_strong = 0; /* strong and valid match */ 4721 this_key_has_addr_match = 0; 4722 match = 0; /* any match */ 4723 4724 r = rfc822_parse_adrlist (NULL, k->uid); 4725 for (p = r; p; p = p->next) 4726 { 4727 int validity = crypt_id_matches_addr (a, p, k); 4728 4729 if (validity & CRYPT_KV_MATCH) /* something matches */ 4730 { 4731 match = 1; 4732 4733 if ((validity & CRYPT_KV_VALID) && 4734 (validity & CRYPT_KV_ADDR)) 4735 { 4736 if (validity & CRYPT_KV_STRONGID) 4737 { 4738 if (the_strong_valid_key 4739 && the_strong_valid_key->kobj != k->kobj) 4740 multi = 1; 4741 this_key_has_strong = 1; 4742 } 4743 else 4744 this_key_has_addr_match = 1; 4745 } 4746 } 4747 } 4748 rfc822_free_address (&r); 4749 4750 if (match) 4751 { 4752 crypt_key_t *tmp; 4753 4754 *matches_endp = tmp = crypt_copy_key (k); 4755 matches_endp = &tmp->next; 4756 4757 if (this_key_has_strong) 4758 the_strong_valid_key = tmp; 4759 else if (this_key_has_addr_match) 4760 a_valid_addrmatch_key = tmp; 4761 } 4762 } 4763 4764 crypt_free_key (&keys); 4765 4766 if (matches) 4767 { 4768 if (oppenc_mode) 4769 { 4770 if (the_strong_valid_key) 4771 k = crypt_copy_key (the_strong_valid_key); 4772 else if (a_valid_addrmatch_key) 4773 k = crypt_copy_key (a_valid_addrmatch_key); 4774 else 4775 k = NULL; 4776 } 4777 else if (the_strong_valid_key && !multi) 4778 { 4779 /* 4780 * There was precisely one strong match on a valid ID. 4781 * 4782 * Proceed without asking the user. 4783 */ 4784 k = crypt_copy_key (the_strong_valid_key); 4785 } 4786 else 4787 { 4788 /* 4789 * Else: Ask the user. 4790 */ 4791 k = crypt_select_key (matches, a, NULL, app, forced_valid); 4792 } 4793 4794 crypt_free_key (&matches); 4795 } 4796 else 4797 k = NULL; 4798 4799 return k; 4800} 4801 4802 4803static crypt_key_t *crypt_getkeybystr (char *p, short abilities, 4804 unsigned int app, int *forced_valid) 4805{ 4806 LIST *hints = NULL; 4807 crypt_key_t *keys; 4808 crypt_key_t *matches = NULL; 4809 crypt_key_t **matches_endp = &matches; 4810 crypt_key_t *k; 4811 const char *ps, *pl, *pfcopy, *phint; 4812 4813 mutt_message (_("Looking for keys matching \"%s\"..."), p); 4814 4815 *forced_valid = 0; 4816 4817 pfcopy = crypt_get_fingerprint_or_id (p, &phint, &pl, &ps); 4818 hints = crypt_add_string_to_hints (hints, phint); 4819 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN)); 4820 mutt_free_list (&hints); 4821 4822 if (!keys) 4823 { 4824 FREE (&pfcopy); 4825 return NULL; 4826 } 4827 4828 for (k = keys; k; k = k->next) 4829 { 4830 if (abilities && !(k->flags & abilities)) 4831 continue; 4832 4833 dprint (5, (debugfile, "crypt_getkeybystr: matching \"%s\" against " 4834 "key %s, \"%s\": ", p, crypt_long_keyid (k), k->uid)); 4835 4836 if (!*p 4837 || (pfcopy && mutt_strcasecmp (pfcopy, crypt_fpr (k)) == 0) 4838 || (pl && mutt_strcasecmp (pl, crypt_long_keyid (k)) == 0) 4839 || (ps && mutt_strcasecmp (ps, crypt_short_keyid (k)) == 0) 4840 || mutt_stristr (k->uid, p)) 4841 { 4842 crypt_key_t *tmp; 4843 4844 dprint (5, (debugfile, "match.\n")); 4845 4846 *matches_endp = tmp = crypt_copy_key (k); 4847 matches_endp = &tmp->next; 4848 } 4849 } 4850 4851 FREE (&pfcopy); 4852 crypt_free_key (&keys); 4853 4854 if (matches) 4855 { 4856 k = crypt_select_key (matches, NULL, p, app, forced_valid); 4857 crypt_free_key (&matches); 4858 return k; 4859 } 4860 4861 return NULL; 4862} 4863 4864/* Display TAG as a prompt to ask for a key. If WHATFOR is not null 4865 use it as default and store it under that label as the next 4866 default. ABILITIES describe the required key abilities (sign, 4867 encrypt) and APP the type of the requested key; ether S/MIME or 4868 PGP. Return a copy of the key or NULL if not found. */ 4869static crypt_key_t *crypt_ask_for_key (char *tag, 4870 char *whatfor, 4871 short abilities, 4872 unsigned int app, 4873 int *forced_valid) 4874{ 4875 crypt_key_t *key; 4876 char resp[SHORT_STRING]; 4877 struct crypt_cache *l = NULL; 4878 int dummy; 4879 4880 if (!forced_valid) 4881 forced_valid = &dummy; 4882 4883 mutt_clear_error (); 4884 4885 *forced_valid = 0; 4886 resp[0] = 0; 4887 if (whatfor) 4888 { 4889 4890 for (l = id_defaults; l; l = l->next) 4891 if (!mutt_strcasecmp (whatfor, l->what)) 4892 { 4893 strfcpy (resp, NONULL (l->dflt), sizeof (resp)); 4894 break; 4895 } 4896 } 4897 4898 4899 for (;;) 4900 { 4901 resp[0] = 0; 4902 if (mutt_get_field (tag, resp, sizeof (resp), MUTT_CLEAR) != 0) 4903 return NULL; 4904 4905 if (whatfor) 4906 { 4907 if (l) 4908 mutt_str_replace (&l->dflt, resp); 4909 else 4910 { 4911 l = safe_malloc (sizeof (struct crypt_cache)); 4912 l->next = id_defaults; 4913 id_defaults = l; 4914 l->what = safe_strdup (whatfor); 4915 l->dflt = safe_strdup (resp); 4916 } 4917 } 4918 4919 if ((key = crypt_getkeybystr (resp, abilities, app, forced_valid))) 4920 return key; 4921 4922 BEEP (); 4923 } 4924 /* not reached */ 4925} 4926 4927/* This routine attempts to find the keyids of the recipients of a 4928 message. It returns NULL if any of the keys can not be found. 4929 If oppenc_mode is true, only keys that can be determined without 4930 prompting will be used. */ 4931static char *find_keys (ADDRESS *adrlist, unsigned int app, int oppenc_mode) 4932{ 4933 LIST *crypt_hook_list, *crypt_hook = NULL; 4934 char *crypt_hook_val = NULL; 4935 const char *keyID = NULL; 4936 char *keylist = NULL, *t; 4937 size_t keylist_size = 0; 4938 size_t keylist_used = 0; 4939 ADDRESS *addr = NULL; 4940 ADDRESS *p, *q; 4941 crypt_key_t *k_info; 4942 const char *fqdn = mutt_fqdn (1); 4943 char buf[LONG_STRING]; 4944 int forced_valid; 4945 int r; 4946 int key_selected; 4947 4948 for (p = adrlist; p ; p = p->next) 4949 { 4950 key_selected = 0; 4951 crypt_hook_list = crypt_hook = mutt_crypt_hook (p); 4952 do 4953 { 4954 q = p; 4955 forced_valid = 0; 4956 k_info = NULL; 4957 4958 if (crypt_hook != NULL) 4959 { 4960 crypt_hook_val = crypt_hook->data; 4961 r = MUTT_YES; 4962 if (! oppenc_mode && option(OPTCRYPTCONFIRMHOOK)) 4963 { 4964 snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), 4965 crypt_hook_val, p->mailbox); 4966 r = mutt_yesorno (buf, MUTT_YES); 4967 } 4968 if (r == MUTT_YES) 4969 { 4970 if (crypt_is_numerical_keyid (crypt_hook_val)) 4971 { 4972 keyID = crypt_hook_val; 4973 if (strncmp (keyID, "0x", 2) == 0) 4974 keyID += 2; 4975 goto bypass_selection; /* you don't see this. */ 4976 } 4977 4978 /* check for e-mail address */ 4979 if ((t = strchr (crypt_hook_val, '@')) && 4980 (addr = rfc822_parse_adrlist (NULL, crypt_hook_val))) 4981 { 4982 if (fqdn) 4983 rfc822_qualify (addr, fqdn); 4984 q = addr; 4985 } 4986 else if (! oppenc_mode) 4987 { 4988 k_info = crypt_getkeybystr (crypt_hook_val, KEYFLAG_CANENCRYPT, 4989 app, &forced_valid); 4990 } 4991 } 4992 else if (r == MUTT_NO) 4993 { 4994 if (key_selected || (crypt_hook->next != NULL)) 4995 { 4996 crypt_hook = crypt_hook->next; 4997 continue; 4998 } 4999 } 5000 else if (r == -1) 5001 { 5002 FREE (&keylist); 5003 rfc822_free_address (&addr); 5004 mutt_free_list (&crypt_hook_list); 5005 return NULL; 5006 } 5007 } 5008 5009 if (k_info == NULL) 5010 { 5011 k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT, 5012 app, &forced_valid, oppenc_mode); 5013 } 5014 5015 if ((k_info == NULL) && (! oppenc_mode)) 5016 { 5017 snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox); 5018 5019 k_info = crypt_ask_for_key (buf, q->mailbox, 5020 KEYFLAG_CANENCRYPT, 5021 app, 5022 &forced_valid); 5023 } 5024 5025 if (k_info == NULL) 5026 { 5027 FREE (&keylist); 5028 rfc822_free_address (&addr); 5029 mutt_free_list (&crypt_hook_list); 5030 return NULL; 5031 } 5032 5033 5034 keyID = crypt_fpr_or_lkeyid (k_info); 5035 5036 bypass_selection: 5037 keylist_size += mutt_strlen (keyID) + 4 + 1; 5038 safe_realloc (&keylist, keylist_size); 5039 sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */ 5040 keylist_used ? " " : "", keyID, 5041 forced_valid? "!":""); 5042 keylist_used = mutt_strlen (keylist); 5043 5044 key_selected = 1; 5045 5046 crypt_free_key (&k_info); 5047 rfc822_free_address (&addr); 5048 5049 if (crypt_hook != NULL) 5050 crypt_hook = crypt_hook->next; 5051 5052 } while (crypt_hook != NULL); 5053 5054 mutt_free_list (&crypt_hook_list); 5055 } 5056 return (keylist); 5057} 5058 5059char *pgp_gpgme_findkeys (ADDRESS *adrlist, int oppenc_mode) 5060{ 5061 return find_keys (adrlist, APPLICATION_PGP, oppenc_mode); 5062} 5063 5064char *smime_gpgme_findkeys (ADDRESS *adrlist, int oppenc_mode) 5065{ 5066 return find_keys (adrlist, APPLICATION_SMIME, oppenc_mode); 5067} 5068 5069/* 5070 * This function is used by autocrypt to select a private key for 5071 * a new account. 5072 * 5073 * Unfortunately, the internal crypt-gpgme.c functions use crypt_key_t, 5074 * and so aren't exportable. 5075 * 5076 * This function queries all private keys, provides the crypt_select_keys() 5077 * menu, and returns the selected key fingerprint in keyid. 5078 */ 5079int mutt_gpgme_select_secret_key (BUFFER *keyid) 5080{ 5081 int rv = -1, junk; 5082 gpgme_ctx_t ctx = NULL; 5083 gpgme_error_t err; 5084 gpgme_key_t key; 5085 gpgme_user_id_t uid; 5086 crypt_key_t *results = NULL, *k, **kend; 5087 crypt_key_t *choice = NULL; 5088 unsigned int flags, idx; 5089 5090 ctx = create_gpgme_context (0); 5091 5092 /* list all secret keys */ 5093 if (gpgme_op_keylist_start (ctx, NULL, 1)) 5094 goto cleanup; 5095 5096 kend = &results; 5097 5098 while (!(err = gpgme_op_keylist_next (ctx, &key)) ) 5099 { 5100 flags = 0; 5101 5102 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) 5103 flags |= KEYFLAG_CANENCRYPT; 5104 if (key_check_cap (key, KEY_CAP_CAN_SIGN)) 5105 flags |= KEYFLAG_CANSIGN; 5106 5107 if (key->revoked) 5108 flags |= KEYFLAG_REVOKED; 5109 if (key->expired) 5110 flags |= KEYFLAG_EXPIRED; 5111 if (key->disabled) 5112 flags |= KEYFLAG_DISABLED; 5113 5114 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) 5115 { 5116 k = safe_calloc (1, sizeof *k); 5117 k->kobj = key; 5118 gpgme_key_ref (k->kobj); 5119 k->idx = idx; 5120 k->uid = uid->uid; 5121 k->flags = flags; 5122 if (uid->revoked) 5123 k->flags |= KEYFLAG_REVOKED; 5124 k->validity = uid->validity; 5125 *kend = k; 5126 kend = &k->next; 5127 } 5128 gpgme_key_unref (key); 5129 } 5130 if (gpg_err_code (err) != GPG_ERR_EOF) 5131 mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err)); 5132 gpgme_op_keylist_end (ctx); 5133 5134 if (!results) 5135 { 5136 /* L10N: 5137 mutt_gpgme_select_secret_key() tries to list all secret keys to choose 5138 from. This error is displayed if no results were found. 5139 */ 5140 mutt_error (_("No secret keys found")); 5141 mutt_sleep (1); 5142 goto cleanup; 5143 } 5144 5145 choice = crypt_select_key (results, NULL, "*", APPLICATION_PGP, &junk); 5146 if (!(choice && choice->kobj && choice->kobj->subkeys && 5147 choice->kobj->subkeys->fpr)) 5148 goto cleanup; 5149 mutt_buffer_strcpy (keyid, choice->kobj->subkeys->fpr); 5150 5151 rv = 0; 5152 5153cleanup: 5154 crypt_free_key (&choice); 5155 crypt_free_key (&results); 5156 gpgme_release (ctx); 5157 return rv; 5158} 5159 5160BODY *pgp_gpgme_make_key_attachment (void) 5161{ 5162 crypt_key_t *key = NULL; 5163 gpgme_ctx_t context = NULL; 5164 gpgme_key_t export_keys[2]; 5165 gpgme_data_t keydata = NULL; 5166 gpgme_error_t err; 5167 BODY *att = NULL; 5168 char buff[LONG_STRING]; 5169 char *attfilename; 5170 struct stat sb; 5171 5172 unset_option (OPTPGPCHECKTRUST); 5173 5174 key = crypt_ask_for_key (_("Please enter the key ID: "), NULL, 0, 5175 APPLICATION_PGP, NULL); 5176 if (!key) 5177 goto bail; 5178 export_keys[0] = key->kobj; 5179 export_keys[1] = NULL; 5180 5181 context = create_gpgme_context (0); 5182 gpgme_set_armor (context, 1); 5183 keydata = create_gpgme_data (); 5184 err = gpgme_op_export_keys (context, export_keys, 0, keydata); 5185 if (err != GPG_ERR_NO_ERROR) 5186 { 5187 mutt_error (_("Error exporting key: %s\n"), gpgme_strerror (err)); 5188 mutt_sleep (1); 5189 goto bail; 5190 } 5191 5192 attfilename = data_object_to_tempfile (keydata, NULL, NULL); 5193 if (!attfilename) 5194 goto bail; 5195 5196 att = mutt_new_body (); 5197 /* attfilename is a newly allocated string, so this is correct: */ 5198 att->filename = attfilename; 5199 att->unlink = 1; 5200 att->use_disp = 0; 5201 att->type = TYPEAPPLICATION; 5202 att->subtype = safe_strdup ("pgp-keys"); 5203 /* L10N: 5204 MIME description for exported (attached) keys. 5205 You can translate this entry to a non-ASCII string (it will be encoded), 5206 but it may be safer to keep it untranslated. */ 5207 snprintf (buff, sizeof (buff), _("PGP Key 0x%s."), crypt_keyid (key)); 5208 att->description = safe_strdup (buff); 5209 mutt_update_encoding (att); 5210 5211 stat (attfilename, &sb); 5212 att->length = sb.st_size; 5213 5214bail: 5215 crypt_free_key (&key); 5216 gpgme_data_release (keydata); 5217 gpgme_release (context); 5218 5219 return att; 5220} 5221 5222/* 5223 * Implementation of `init'. 5224 */ 5225 5226/* This function contains common code needed to be executed for both the pgp 5227 * and smime support of gpgme. */ 5228static void init_common(void) 5229{ 5230 /* this initialization should only run one time, but it may be called by 5231 * either pgp_gpgme_init or smime_gpgme_init */ 5232 static bool has_run = 0; 5233 if (!has_run) 5234 { 5235 gpgme_check_version(NULL); 5236 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL)); 5237#ifdef ENABLE_NLS 5238 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL)); 5239#endif 5240 has_run = 1; /* note use of 1 here is intentional to avoid requiring "true" 5241 to be defined. see #3657 */ 5242 } 5243} 5244 5245static void init_pgp (void) 5246{ 5247 if (gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP) != GPG_ERR_NO_ERROR) 5248 { 5249 mutt_error (_("GPGME: OpenPGP protocol not available")); 5250 } 5251} 5252 5253static void init_smime (void) 5254{ 5255 if (gpgme_engine_check_version (GPGME_PROTOCOL_CMS) != GPG_ERR_NO_ERROR) 5256 { 5257 mutt_error (_("GPGME: CMS protocol not available")); 5258 } 5259} 5260 5261void pgp_gpgme_init (void) 5262{ 5263 init_common (); 5264 init_pgp (); 5265} 5266 5267void smime_gpgme_init (void) 5268{ 5269 init_common (); 5270 init_smime (); 5271} 5272 5273static int gpgme_send_menu (HEADER *msg, int is_smime) 5274{ 5275 crypt_key_t *p; 5276 char input_signas[SHORT_STRING]; 5277 char *prompt, *letters, *choices; 5278 int choice; 5279 5280 if (is_smime) 5281 msg->security |= APPLICATION_SMIME; 5282 else 5283 msg->security |= APPLICATION_PGP; 5284 5285 /* 5286 * Opportunistic encrypt is controlling encryption. 5287 * NOTE: "Signing" and "Clearing" only adjust the sign bit, so we have different 5288 * letter choices for those. 5289 */ 5290 if (option (OPTCRYPTOPPORTUNISTICENCRYPT) && (msg->security & OPPENCRYPT)) 5291 { 5292 if (is_smime) 5293 { 5294 prompt = _("S/MIME (s)ign, sign (a)s, (p)gp, (c)lear, or (o)ppenc mode off? "); 5295 /* L10N: The 'f' is from "forget it", an old undocumented synonym of 5296 'clear'. Please use a corresponding letter in your language. 5297 Alternatively, you may duplicate the letter 'c' is translated to. 5298 This comment also applies to the five following letter sequences. */ 5299 letters = _("sapfco"); 5300 choices = "SapFCo"; 5301 } 5302 else 5303 { 5304 prompt = _("PGP (s)ign, sign (a)s, s/(m)ime, (c)lear, or (o)ppenc mode off? "); 5305 letters = _("samfco"); 5306 choices = "SamFCo"; 5307 } 5308 } 5309 /* 5310 * Opportunistic encryption option is set, but is toggled off 5311 * for this message. 5312 */ 5313 else if (option (OPTCRYPTOPPORTUNISTICENCRYPT)) 5314 { 5315 if (is_smime) 5316 { 5317 prompt = _("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp, (c)lear, or (o)ppenc mode? "); 5318 letters = _("esabpfco"); 5319 choices = "esabpfcO"; 5320 } 5321 else 5322 { 5323 prompt = _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime, (c)lear, or (o)ppenc mode? "); 5324 letters = _("esabmfco"); 5325 choices = "esabmfcO"; 5326 } 5327 } 5328 /* 5329 * Opportunistic encryption is unset 5330 */ 5331 else 5332 { 5333 if (is_smime) 5334 { 5335 prompt = _("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear? "); 5336 letters = _("esabpfc"); 5337 choices = "esabpfc"; 5338 } 5339 else 5340 { 5341 prompt = _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear? "); 5342 letters = _("esabmfc"); 5343 choices = "esabmfc"; 5344 } 5345 } 5346 5347 choice = mutt_multi_choice (prompt, letters); 5348 if (choice > 0) 5349 { 5350 switch (choices[choice - 1]) 5351 { 5352 case 'e': /* (e)ncrypt */ 5353 msg->security |= ENCRYPT; 5354 msg->security &= ~SIGN; 5355 break; 5356 5357 case 's': /* (s)ign */ 5358 msg->security &= ~ENCRYPT; 5359 msg->security |= SIGN; 5360 break; 5361 5362 case 'S': /* (s)ign in oppenc mode */ 5363 msg->security |= SIGN; 5364 break; 5365 5366 case 'a': /* sign (a)s */ 5367 if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN, 5368 is_smime? APPLICATION_SMIME:APPLICATION_PGP, 5369 NULL))) 5370 { 5371 snprintf (input_signas, sizeof (input_signas), "0x%s", 5372 crypt_fpr_or_lkeyid (p)); 5373 mutt_str_replace (is_smime? &SmimeSignAs : &PgpSignAs, input_signas); 5374 crypt_free_key (&p); 5375 5376 msg->security |= SIGN; 5377 } 5378 break; 5379 5380 case 'b': /* (b)oth */ 5381 msg->security |= (ENCRYPT | SIGN); 5382 break; 5383 5384 case 'p': /* (p)gp or s/(m)ime */ 5385 case 'm': 5386 is_smime = !is_smime; 5387 if (is_smime) 5388 { 5389 msg->security &= ~APPLICATION_PGP; 5390 msg->security |= APPLICATION_SMIME; 5391 } 5392 else 5393 { 5394 msg->security &= ~APPLICATION_SMIME; 5395 msg->security |= APPLICATION_PGP; 5396 } 5397 crypt_opportunistic_encrypt (msg); 5398 break; 5399 5400 case 'f': /* (f)orget it: kept for backward compatibility. */ 5401 case 'c': /* (c)lear */ 5402 msg->security &= ~(ENCRYPT | SIGN); 5403 break; 5404 5405 case 'F': /* (f)orget it or (c)lear in oppenc mode */ 5406 case 'C': 5407 msg->security &= ~SIGN; 5408 break; 5409 5410 case 'O': /* oppenc mode on */ 5411 msg->security |= OPPENCRYPT; 5412 crypt_opportunistic_encrypt (msg); 5413 break; 5414 5415 case 'o': /* oppenc mode off */ 5416 msg->security &= ~OPPENCRYPT; 5417 break; 5418 } 5419 } 5420 5421 return (msg->security); 5422} 5423 5424int pgp_gpgme_send_menu (HEADER *msg) 5425{ 5426 return gpgme_send_menu (msg, 0); 5427} 5428 5429int smime_gpgme_send_menu (HEADER *msg) 5430{ 5431 return gpgme_send_menu (msg, 1); 5432} 5433 5434static int verify_sender (HEADER *h, gpgme_protocol_t protocol) 5435{ 5436 ADDRESS *sender = NULL; 5437 unsigned int ret = 1; 5438 5439 if (h->env->from) 5440 { 5441 h->env->from = mutt_expand_aliases (h->env->from); 5442 sender = h->env->from; 5443 } 5444 else if (h->env->sender) 5445 { 5446 h->env->sender = mutt_expand_aliases (h->env->sender); 5447 sender = h->env->sender; 5448 } 5449 5450 if (sender) 5451 { 5452 if (signature_key) 5453 { 5454 gpgme_key_t key = signature_key; 5455 gpgme_user_id_t uid = NULL; 5456 int sender_length = 0; 5457 int uid_length = 0; 5458 5459 sender_length = strlen (sender->mailbox); 5460 for (uid = key->uids; uid && ret; uid = uid->next) 5461 { 5462 uid_length = strlen (uid->email); 5463 if (1 5464 && (uid->email[0] == '<') 5465 && (uid->email[uid_length - 1] == '>') 5466 && (uid_length == sender_length + 2)) 5467 { 5468 const char* at_sign = strchr(uid->email + 1, '@'); 5469 if (at_sign == NULL) 5470 { 5471 if (! strncmp (uid->email + 1, sender->mailbox, sender_length)) 5472 ret = 0; 5473 } 5474 else 5475 { 5476 /* 5477 * Assume address is 'mailbox@domainname'. 5478 * The mailbox part is case-sensitive, 5479 * the domainname is not. (RFC 2821) 5480 */ 5481 const char* tmp_email = uid->email + 1; 5482 const char* tmp_sender = sender->mailbox; 5483 /* length of mailbox part including '@' */ 5484 int mailbox_length = at_sign - tmp_email + 1; 5485 int domainname_length = sender_length - mailbox_length; 5486 int mailbox_match, domainname_match; 5487 5488 mailbox_match = (! strncmp (tmp_email, tmp_sender, 5489 mailbox_length)); 5490 tmp_email += mailbox_length; 5491 tmp_sender += mailbox_length; 5492 domainname_match = (! strncasecmp (tmp_email, tmp_sender, 5493 domainname_length)); 5494 if (mailbox_match && domainname_match) 5495 ret = 0; 5496 } 5497 } 5498 } 5499 } 5500 else 5501 mutt_any_key_to_continue (_("Failed to verify sender")); 5502 } 5503 else 5504 mutt_any_key_to_continue (_("Failed to figure out sender")); 5505 5506 if (signature_key) 5507 { 5508 gpgme_key_unref (signature_key); 5509 signature_key = NULL; 5510 } 5511 5512 return ret; 5513} 5514 5515int smime_gpgme_verify_sender (HEADER *h) 5516{ 5517 return verify_sender (h, GPGME_PROTOCOL_CMS); 5518} 5519 5520void mutt_gpgme_set_sender (const char *sender) 5521{ 5522 dprint (2, (debugfile, "mutt_gpgme_set_sender: setting to: %s\n", sender)); 5523 FREE (&current_sender); 5524 current_sender = safe_strdup (sender); 5525} 5526 5527 5528#endif