mutt stable branch with some hacks
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 (¤t_sender);
5524 current_sender = safe_strdup (sender);
5525}
5526
5527
5528#endif