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