caba82117bb3b4741f99100c77570f9941758599
[apps/madmutt.git] / lib-crypt / crypt-gpgme.c
1 /*
2  * Copyright notice from original mutt:
3  * crypt-gpgme.c - GPGME based crypto operations
4  * Copyright (C) 1996,1997 Michael R. Elkins <me@cs.hmc.edu>
5  * Copyright (C) 1998,1999,2000 Thomas Roessler <roessler@guug.de>
6  * Copyright (C) 2001  Thomas Roessler <roessler@guug.de>
7  *                     Oliver Ehli <elmy@acm.org>
8  * Copyright (C) 2002, 2003, 2004 g10 Code GmbH
9  *
10  * This file is part of mutt-ng, see http://www.muttng.org/.
11  * It's licensed under the GNU General Public License,
12  * please see the file GPL in the top level source directory.
13  */
14
15 #include <lib-lib/lib-lib.h>
16
17 #ifdef HAVE_LOCALE_H
18 #  include <locale.h>
19 #endif
20 #ifdef HAVE_LANGINFO_D_T_FMT
21 #  include <langinfo.h>
22 #endif
23 #ifdef HAVE_SYS_RESOURCE_H
24 #  include <sys/resource.h>
25 #endif
26
27 #include <gpgme.h>
28
29 #include <lib-mime/mime.h>
30 #include <lib-ui/curses.h>
31 #include <lib-ui/enter.h>
32 #include <lib-ui/menu.h>
33
34 #include "crypt.h"
35
36 #include "lib.h"
37 #include "alias.h"
38 #include "handler.h"
39 #include "copy.h"
40 #include "pager.h"
41 #include "recvattach.h"
42 #include "sort.h"
43
44 /* Values used for comparing addresses. */
45 #define CRYPT_KV_VALID    1
46 #define CRYPT_KV_ADDR     2
47 #define CRYPT_KV_STRING   4
48 #define CRYPT_KV_STRONGID 8
49 #define CRYPT_KV_MATCH (CRYPT_KV_ADDR|CRYPT_KV_STRING)
50
51 /*
52  * Type definitions.
53  */
54
55 struct crypt_cache {
56   char *what;
57   char *dflt;
58   struct crypt_cache *next;
59 };
60
61 struct dn_array_s {
62   char *key;
63   char *value;
64 };
65
66 /* We work based on user IDs, getting from a user ID to the key is
67    check and does not need any memory (gpgme uses reference counting). */
68 typedef struct crypt_keyinfo {
69   struct crypt_keyinfo *next;
70   gpgme_key_t kobj;
71   int idx;                      /* and the user ID at this index */
72   const char *uid;              /* and for convenience point to this user ID */
73   unsigned int flags;           /* global and per uid flags (for convenience) */
74 } crypt_key_t;
75
76 typedef struct crypt_entry {
77   ssize_t num;
78   crypt_key_t *key;
79 } crypt_entry_t;
80
81
82 static struct crypt_cache *id_defaults = NULL;
83 static gpgme_key_t signature_key = NULL;
84
85 /* Show a message that a backend will be invoked. */
86 void crypt_invoke_message (int type)
87 {
88     if (type & APPLICATION_PGP) {
89         mutt_message _("Invoking PGP...");
90     }
91     else if (type & APPLICATION_SMIME) {
92         mutt_message _("Invoking S/MIME...");
93     }
94 }
95
96 /*
97  * General helper functions.
98  */
99
100 /* return true when S points to a didgit or letter. */
101 static int digit_or_letter (const unsigned char *s)
102 {
103   return ((*s >= '0' && *s <= '9')
104           || (*s >= 'A' && *s <= 'Z')
105           || (*s >= 'a' && *s <= 'z'));
106 }
107
108
109 /* Print the utf-8 encoded string BUF of length LEN bytes to stream
110    FP. Convert the character set. */
111 static void print_utf8 (FILE * fp, const char *buf, ssize_t len)
112 {
113   char *tstr;
114
115   tstr = p_dupstr(buf, len);
116   mutt_convert_string (&tstr, "utf-8", MCharset.charset, M_ICONV_HOOK_FROM);
117   fputs (tstr, fp);
118   p_delete(&tstr);
119 }
120
121
122 /*
123  * Key management.
124  */
125
126 /* Return the keyID for the key K.  Note that this string is valid as
127    long as K is valid */
128 static const char *crypt_keyid (crypt_key_t * k)
129 {
130   const char *s = "????????";
131
132   if (k->kobj && k->kobj->subkeys) {
133     s = k->kobj->subkeys->keyid;
134     if ((!option (OPTPGPLONGIDS)) && (m_strlen(s) == 16))
135       /* Return only the short keyID.  */
136       s += 8;
137   }
138
139   return s;
140 }
141
142 /* Return the hexstring fingerprint from the key K. */
143 static const char *crypt_fpr (crypt_key_t * k)
144 {
145   const char *s = "";
146
147   if (k->kobj && k->kobj->subkeys)
148     s = k->kobj->subkeys->fpr;
149
150   return s;
151 }
152
153 /* Parse FLAGS and return a statically allocated(!) string with them. */
154 static char *crypt_key_abilities (int flags)
155 {
156   static char buff[3];
157
158   if (!(flags & KEYFLAG_CANENCRYPT))
159     buff[0] = '-';
160   else if (flags & KEYFLAG_PREFER_SIGNING)
161     buff[0] = '.';
162   else
163     buff[0] = 'e';
164
165   if (!(flags & KEYFLAG_CANSIGN))
166     buff[1] = '-';
167   else if (flags & KEYFLAG_PREFER_ENCRYPTION)
168     buff[1] = '.';
169   else
170     buff[1] = 's';
171
172   buff[2] = '\0';
173
174   return buff;
175 }
176
177 /* Parse FLAGS and return a character describing the most important flag. */
178 static char crypt_flags (int flags)
179 {
180   if (flags & KEYFLAG_REVOKED)
181     return 'R';
182   else if (flags & KEYFLAG_EXPIRED)
183     return 'X';
184   else if (flags & KEYFLAG_DISABLED)
185     return 'd';
186   else if (flags & KEYFLAG_CRITICAL)
187     return 'c';
188   else
189     return ' ';
190 }
191
192 /* Return a copy of KEY. */
193 static crypt_key_t *crypt_copy_key (crypt_key_t *key)
194 {
195   crypt_key_t *k;
196
197   k = p_new(crypt_key_t, 1);
198   k->kobj = key->kobj;
199   gpgme_key_ref (key->kobj);
200   k->idx = key->idx;
201   k->uid = key->uid;
202   k->flags = key->flags;
203
204   return k;
205 }
206
207 /* Release all the keys at the address of KEYLIST and set the address
208    to NULL. */
209 static void crypt_free_key (crypt_key_t ** keylist)
210 {
211   while (*keylist) {
212     crypt_key_t *k = (*keylist)->next;
213
214     p_delete(&k);
215     *keylist = k;
216   }
217 }
218
219 /* Return trute when key K is valid. */
220 static int crypt_key_is_valid (crypt_key_t * k)
221 {
222   if (k->flags & KEYFLAG_CANTUSE)
223     return 0;
224   return 1;
225 }
226
227 /* Return true whe validity of KEY is sufficient. */
228 static int crypt_id_is_strong (crypt_key_t * key)
229 {
230   gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
231   gpgme_user_id_t uid = NULL;
232   int is_strong = 0;
233   int i = 0;
234
235   if ((key->flags & KEYFLAG_ISX509))
236     return 1;
237
238   for (i = 0, uid = key->kobj->uids; (i < key->idx) && uid;
239        i++, uid = uid->next);
240   if (uid)
241     val = uid->validity;
242
243   switch (val) {
244   case GPGME_VALIDITY_UNKNOWN:
245   case GPGME_VALIDITY_UNDEFINED:
246   case GPGME_VALIDITY_NEVER:
247   case GPGME_VALIDITY_MARGINAL:
248     is_strong = 0;
249     break;
250
251   case GPGME_VALIDITY_FULL:
252   case GPGME_VALIDITY_ULTIMATE:
253     is_strong = 1;
254     break;
255   }
256
257   return is_strong;
258 }
259
260 /* Return true when the KEY is valid, i.e. not marked as unusable. */
261 static int crypt_id_is_valid (crypt_key_t * key)
262 {
263   return !(key->flags & KEYFLAG_CANTUSE);
264 }
265
266 /* Return a bit vector describing how well the addresses ADDR and
267    U_ADDR match and whether KEY is valid. */
268 static int crypt_id_matches_addr (address_t * addr, address_t * u_addr,
269                                   crypt_key_t * key)
270 {
271   int rv = 0;
272
273   if (crypt_id_is_valid (key))
274     rv |= CRYPT_KV_VALID;
275
276   if (crypt_id_is_strong (key))
277     rv |= CRYPT_KV_STRONGID;
278
279   if (addr->mailbox && u_addr->mailbox
280       && m_strcasecmp(addr->mailbox, u_addr->mailbox) == 0)
281     rv |= CRYPT_KV_ADDR;
282
283   if (addr->personal && u_addr->personal
284       && m_strcasecmp(addr->personal, u_addr->personal) == 0)
285     rv |= CRYPT_KV_STRING;
286
287   return rv;
288 }
289
290
291 /*
292  * GPGME convenient functions.
293  */
294
295 /* Create a new gpgme context and return it.  With FOR_SMIME set to
296    true, the protocol of the context is set to CMS. */
297 static gpgme_ctx_t create_gpgme_context (int for_smime)
298 {
299   gpgme_error_t err;
300   gpgme_ctx_t ctx;
301
302   err = gpgme_new (&ctx);
303   if (err) {
304     mutt_error (_("error creating gpgme context: %s\n"), gpgme_strerror (err));
305     sleep (2);
306     mutt_exit (1);
307   }
308
309   if (for_smime) {
310     err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
311     if (err) {
312       mutt_error (_("error enabling CMS protocol: %s\n"), gpgme_strerror (err));
313       sleep (2);
314       mutt_exit (1);
315     }
316   }
317
318   return ctx;
319 }
320
321 /* Create a new gpgme data object.  This is a wrapper to die on
322    error. */
323 static gpgme_data_t create_gpgme_data (void)
324 {
325   gpgme_error_t err;
326   gpgme_data_t data;
327
328   err = gpgme_data_new (&data);
329   if (err) {
330     mutt_error (_("error creating gpgme data object: %s\n"),
331                 gpgme_strerror (err));
332     sleep (2);
333     mutt_exit (1);
334   }
335   return data;
336 }
337
338 /* Create a new GPGME Data object from the mail body A.  With CONVERT
339    passed as true, the lines are converted to CR,LF if required.
340    Return NULL on error or the gpgme_data_t object on success. */
341 static gpgme_data_t body_to_data_object (BODY * a, int convert)
342 {
343   char tempfile[_POSIX_PATH_MAX];
344   FILE *fptmp;
345   int err = 0;
346   gpgme_data_t data;
347
348   fptmp = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
349   if (!fptmp) {
350     mutt_perror (_("Can't create temporary file"));
351     return NULL;
352   }
353
354   mutt_write_mime_header (a, fptmp);
355   fputc ('\n', fptmp);
356   mutt_write_mime_body (a, fptmp);
357
358   if (convert) {
359     int c, hadcr = 0;
360     unsigned char buf[1];
361
362     data = create_gpgme_data ();
363     rewind (fptmp);
364     while ((c = fgetc (fptmp)) != EOF) {
365       if (c == '\r')
366         hadcr = 1;
367       else {
368         if (c == '\n' && !hadcr) {
369           buf[0] = '\r';
370           gpgme_data_write (data, buf, 1);
371         }
372
373         hadcr = 0;
374       }
375       /* FIXME: This is quite suboptimal */
376       buf[0] = c;
377       gpgme_data_write (data, buf, 1);
378     }
379     gpgme_data_seek (data, 0, SEEK_SET);
380   } else {
381     err = gpgme_data_new_from_file (&data, tempfile, 1);
382   }
383   m_fclose(&fptmp);
384   unlink (tempfile);
385   if (err) {
386     mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
387     return NULL;
388   }
389
390   return data;
391 }
392
393 /* Create a GPGME data object from the stream FP but limit the object
394    to LENGTH bytes starting at OFFSET bytes from the beginning of the
395    file. */
396 static gpgme_data_t file_to_data_object (FILE * fp, long offset, long length)
397 {
398   int err = 0;
399   gpgme_data_t data;
400
401   err = gpgme_data_new_from_filepart (&data, NULL, fp, offset, length);
402   if (err) {
403     mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
404     return NULL;
405   }
406
407   return data;
408 }
409
410 /* Write a GPGME data object to the stream FP. */
411 static int data_object_to_stream (gpgme_data_t data, FILE * fp)
412 {
413   int err;
414   char buf[4096], *p;
415   ssize_t nread;
416
417   err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1)
418          ? gpgme_error_from_errno (errno) : 0);
419   if (err) {
420     mutt_error (_("error rewinding data object: %s\n"), gpgme_strerror (err));
421     return -1;
422   }
423
424   while ((nread = gpgme_data_read (data, buf, sizeof (buf)))) {
425     /* fixme: we are not really converting CRLF to LF but just
426        skipping CR. Doing it correctly needs a more complex logic */
427     for (p = buf; nread; p++, nread--) {
428       if (*p != '\r')
429         putc (*p, fp);
430     }
431
432     if (ferror (fp)) {
433       mutt_perror ("[tempfile]");
434       return -1;
435     }
436   }
437   if (nread == -1) {
438     mutt_error (_("error reading data object: %s\n"), strerror (errno));
439     return -1;
440   }
441   return 0;
442 }
443
444 /* Copy a data object to a newly created temporay file and return that
445    filename. Caller must free.  With RET_FP not NULL, don't close the
446    stream but return it there. */
447 static char *data_object_to_tempfile (gpgme_data_t data, FILE ** ret_fp)
448 {
449   int err;
450   char tempfile[_POSIX_PATH_MAX];
451   FILE *fp;
452   ssize_t nread = 0;
453
454   fp = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
455   if (!fp) {
456     mutt_perror (_("Can't create temporary file"));
457     return NULL;
458   }
459
460   err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1)
461          ? gpgme_error_from_errno (errno) : 0);
462   if (!err) {
463     char buf[4096];
464
465     while ((nread = gpgme_data_read (data, buf, sizeof (buf)))) {
466       if (fwrite (buf, nread, 1, fp) != 1) {
467         mutt_perror (_("Can't create temporary file"));
468         m_fclose(&fp);
469         unlink (tempfile);
470         return NULL;
471       }
472     }
473   }
474   if (ret_fp)
475     rewind (fp);
476   else
477     m_fclose(&fp);
478   if (nread == -1) {
479     mutt_error (_("error reading data object: %s\n"), gpgme_strerror (err));
480     unlink (tempfile);
481     m_fclose(&fp);
482     return NULL;
483   }
484   if (ret_fp)
485     *ret_fp = fp;
486   return m_strdup(tempfile);
487 }
488
489
490 /* FIXME: stolen from gpgme to avoid "ambiguous identity" errors */
491 static gpgme_error_t
492 gpgme_get_key2 (gpgme_ctx_t ctx, const char *fpr, gpgme_key_t *r_key,
493                int secret)
494 {
495   gpgme_ctx_t listctx;
496   gpgme_error_t err;
497   gpgme_key_t key;
498
499   if (!ctx || !r_key || !fpr)
500     return gpg_error (GPG_ERR_INV_VALUE);
501
502   if (strlen (fpr) < 8) /* We have at least a key ID.  */
503     return gpg_error (GPG_ERR_INV_VALUE);
504
505   /* FIXME: We use our own context because we have to avoid the user's
506      I/O callback handlers.  */
507   err = gpgme_new (&listctx);
508   if (err)
509     return err;
510   gpgme_set_protocol (listctx, gpgme_get_protocol (ctx));
511   err = gpgme_op_keylist_start (listctx, fpr, secret);
512   if (!err)
513     err = gpgme_op_keylist_next (listctx, r_key);
514   gpgme_release (listctx);
515   return err;
516 }
517
518 /* Create a GpgmeRecipientSet from the keys in the string KEYLIST.
519    The keys must be space delimited. */
520 static gpgme_key_t *create_recipient_set (const char *keylist,
521                                           gpgme_protocol_t protocol)
522 {
523   int err;
524   const char *s;
525   char buf[100];
526   int i;
527   gpgme_key_t *rset = NULL;
528   unsigned int rset_n = 0;
529   gpgme_key_t key = NULL;
530   gpgme_ctx_t context = NULL;
531
532   err = gpgme_new (&context);
533   if (!err)
534     err = gpgme_set_protocol (context, protocol);
535
536   if (!err) {
537     s = keylist;
538     do {
539       while (*s == ' ')
540         s++;
541       for (i = 0; *s && *s != ' ' && i < ssizeof(buf) - 1;)
542         buf[i++] = *s++;
543       buf[i] = 0;
544       if (*buf) {
545         if (i > 1 && buf[i - 1] == '!') {
546           /* The user selected to override the valididy of that
547              key. */
548           buf[i - 1] = 0;
549
550           err = gpgme_get_key2 (context, buf, &key, 0);
551           if (!err)
552             key->uids->validity = GPGME_VALIDITY_FULL;
553           buf[i - 1] = '!';
554         }
555         else
556           err = gpgme_get_key2 (context, buf, &key, 0);
557
558         if (!err) {
559           p_realloc(&rset, rset_n + 1);
560           rset[rset_n++] = key;
561         }
562         else {
563           mutt_error (_("error adding recipient `%s': %s\n"),
564                       buf, gpgme_strerror (err));
565           p_delete(&rset);
566           return NULL;
567         }
568       }
569     } while (*s);
570   }
571
572   /* NULL terminate.  */
573   p_realloc(&rset, rset_n + 1);
574   rset[rset_n++] = NULL;
575
576   if (context)
577     gpgme_release (context);
578
579   return rset;
580 }
581
582
583 /* Make sure that the correct signer is set. Returns 0 on success. */
584 static int set_signer (gpgme_ctx_t ctx, int for_smime)
585 {
586   char *signid = for_smime ? SmimeDefaultKey : PgpSignAs;
587   gpgme_error_t err;
588   gpgme_ctx_t listctx;
589   gpgme_key_t key, key2;
590
591   if (!signid || !*signid)
592     return 0;
593
594   listctx = create_gpgme_context (for_smime);
595   err = gpgme_op_keylist_start (listctx, signid, 1);
596   if (!err)
597     err = gpgme_op_keylist_next (listctx, &key);
598   if (err) {
599     gpgme_release (listctx);
600     mutt_error (_("secret key `%s' not found: %s\n"),
601                 signid, gpgme_strerror (err));
602     return -1;
603   }
604   err = gpgme_op_keylist_next (listctx, &key2);
605   if (!err) {
606     gpgme_key_release (key);
607     gpgme_key_release (key2);
608     gpgme_release (listctx);
609     mutt_error (_("ambiguous specification of secret key `%s'\n"), signid);
610     return -1;
611   }
612   gpgme_op_keylist_end (listctx);
613   gpgme_release (listctx);
614
615   gpgme_signers_clear (ctx);
616   err = gpgme_signers_add (ctx, key);
617   gpgme_key_release (key);
618   if (err) {
619     mutt_error (_("error setting secret key `%s': %s\n"),
620                 signid, gpgme_strerror (err));
621     return -1;
622   }
623   return 0;
624 }
625
626
627 /* Encrypt the gpgme data object PLAINTEXT to the recipients in RSET
628    and return an allocated filename to a temporary file containing the
629    enciphered text.  With USE_SMIME set to true, the smime backend is
630    used.  With COMBINED_SIGNED a PGP message is signed and
631    encrypted.  Returns NULL in case of error */
632 static char *encrypt_gpgme_object (gpgme_data_t plaintext, gpgme_key_t * rset,
633                                    int use_smime, int combined_signed)
634 {
635   int err;
636   gpgme_ctx_t ctx;
637   gpgme_data_t ciphertext;
638   char *outfile;
639
640   ctx = create_gpgme_context (use_smime);
641   if (!use_smime)
642     gpgme_set_armor (ctx, 1);
643
644   ciphertext = create_gpgme_data ();
645
646   if (combined_signed) {
647     if (set_signer (ctx, use_smime)) {
648       gpgme_data_release (ciphertext);
649       gpgme_release (ctx);
650       return NULL;
651     }
652     err = gpgme_op_encrypt_sign (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST,
653                                  plaintext, ciphertext);
654   }
655   else
656     err = gpgme_op_encrypt (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST,
657                             plaintext, ciphertext);
658   mutt_need_hard_redraw ();
659   if (err) {
660     mutt_error (_("error encrypting data: %s\n"), gpgme_strerror (err));
661     gpgme_data_release (ciphertext);
662     gpgme_release (ctx);
663     return NULL;
664   }
665
666   gpgme_release (ctx);
667
668   outfile = data_object_to_tempfile (ciphertext, NULL);
669   gpgme_data_release (ciphertext);
670   return outfile;
671 }
672
673 /* Find the "micalg" parameter from the last Gpgme operation on
674    context CTX.  It is expected that this operation was a sign
675    operation.  Return the algorithm name as a C string in buffer BUF
676    which must have been allocated by the caller with size BUFLEN.
677    Returns 0 on success or -1 in case of an error.  The return string
678    is truncted to BUFLEN - 1. */
679 static int get_micalg (gpgme_ctx_t ctx, char *buf, ssize_t buflen)
680 {
681   gpgme_sign_result_t result = NULL;
682   const char *algorithm_name = NULL;
683
684   if (!buflen)
685     return -1;
686
687   *buf = 0;
688   result = gpgme_op_sign_result (ctx);
689   if (result) {
690     algorithm_name = gpgme_hash_algo_name (result->signatures->hash_algo);
691     if (algorithm_name) {
692       m_strcpy(buf, buflen, algorithm_name);
693     }
694   }
695
696   return *buf ? 0 : -1;
697 }
698
699 static void print_time (time_t t, STATE * s)
700 {
701   char p[STRING];
702
703   setlocale (LC_TIME, "");
704 #ifdef HAVE_LANGINFO_D_T_FMT
705   strftime (p, sizeof (p), nl_langinfo (D_T_FMT), localtime (&t));
706 #else
707   strftime (p, sizeof (p), "%c", localtime (&t));
708 #endif
709   setlocale (LC_TIME, "C");
710   state_attach_puts (p, s);
711 }
712
713 /* Implementation of `sign_message'. */
714
715 /* Sign the MESSAGE in body A either using OpenPGP or S/MIME when
716    USE_SMIME is passed as true.  Returns the new body or NULL on
717    error. */
718 static BODY *sign_message (BODY * a, int use_smime)
719 {
720   BODY *t;
721   char *sigfile;
722   int err = 0;
723   char buf[100];
724   gpgme_ctx_t ctx;
725   gpgme_data_t message, signature;
726
727   convert_to_7bit (a);          /* Signed data _must_ be in 7-bit format. */
728
729   message = body_to_data_object (a, 1);
730   if (!message)
731     return NULL;
732   signature = create_gpgme_data ();
733
734   ctx = create_gpgme_context (use_smime);
735   if (!use_smime)
736     gpgme_set_armor (ctx, 1);
737
738   if (set_signer (ctx, use_smime)) {
739     gpgme_data_release (signature);
740     gpgme_release (ctx);
741     return NULL;
742   }
743
744   err = gpgme_op_sign (ctx, message, signature, GPGME_SIG_MODE_DETACH);
745   mutt_need_hard_redraw ();
746   gpgme_data_release (message);
747   if (err) {
748     gpgme_data_release (signature);
749     gpgme_release (ctx);
750     mutt_error (_("error signing data: %s\n"), gpgme_strerror (err));
751     return NULL;
752   }
753
754   sigfile = data_object_to_tempfile (signature, NULL);
755   gpgme_data_release (signature);
756   if (!sigfile) {
757     gpgme_release (ctx);
758     return NULL;
759   }
760
761   t = body_new();
762   t->type = TYPEMULTIPART;
763   t->subtype = m_strdup("signed");
764   t->encoding = ENC7BIT;
765   t->use_disp = 0;
766   t->disposition = DISPINLINE;
767
768   parameter_set_boundary(&t->parameter);
769   parameter_setval(&t->parameter, "protocol",
770                    use_smime ? "application/pkcs7-signature"
771                              : "application/pgp-signature");
772   /* Get the micalg from gpgme.  Old gpgme versions don't support this
773      for S/MIME so we assume sha-1 in this case. */
774   if (!get_micalg (ctx, buf, sizeof buf))
775     parameter_setval(&t->parameter, "micalg", buf);
776   else if (use_smime)
777     parameter_setval(&t->parameter, "micalg", "sha1");
778   gpgme_release (ctx);
779
780   t->parts = a;
781   a = t;
782
783   t->parts->next = body_new();
784   t = t->parts->next;
785   t->type = TYPEAPPLICATION;
786   if (use_smime) {
787     t->subtype = m_strdup("pkcs7-signature");
788     parameter_setval(&t->parameter, "name", "smime.p7s");
789     t->encoding = ENCBASE64;
790     t->use_disp = 1;
791     t->disposition = DISPATTACH;
792     t->d_filename = m_strdup("smime.p7s");
793   }
794   else {
795     t->subtype = m_strdup("pgp-signature");
796     t->use_disp = 0;
797     t->disposition = DISPINLINE;
798     t->encoding = ENC7BIT;
799   }
800   t->filename = sigfile;
801   t->unlink = 1;                /* ok to remove this file after sending. */
802
803   return a;
804 }
805
806
807 BODY *crypt_pgp_sign_message (BODY * a)
808 {
809   return sign_message (a, 0);
810 }
811
812 BODY *crypt_smime_sign_message (BODY * a)
813 {
814   return sign_message (a, 1);
815 }
816
817 /*
818  * Implementation of `encrypt_message'.
819  */
820
821 /* Encrypt the mail body A to all keys given as space separated keyids
822    or fingerprints in KEYLIST and return the encrypted body.  */
823 BODY *crypt_pgp_encrypt_message (BODY * a, char *keylist, int sign)
824 {
825   char *outfile = NULL;
826   BODY *t;
827   gpgme_key_t *rset = NULL;
828   gpgme_data_t plaintext;
829
830   rset = create_recipient_set (keylist, GPGME_PROTOCOL_OpenPGP);
831   if (!rset)
832     return NULL;
833
834   if (sign)
835     convert_to_7bit (a);
836   plaintext = body_to_data_object (a, 0);
837   if (!plaintext) {
838     p_delete(&rset);
839     return NULL;
840   }
841
842   outfile = encrypt_gpgme_object (plaintext, rset, 0, sign);
843   gpgme_data_release (plaintext);
844   p_delete(&rset);
845   if (!outfile)
846     return NULL;
847
848   t = body_new();
849   t->type = TYPEMULTIPART;
850   t->subtype = m_strdup("encrypted");
851   t->encoding = ENC7BIT;
852   t->use_disp = 0;
853   t->disposition = DISPINLINE;
854
855   parameter_set_boundary(&t->parameter);
856   parameter_setval(&t->parameter, "protocol", "application/pgp-encrypted");
857
858   t->parts = body_new();
859   t->parts->type = TYPEAPPLICATION;
860   t->parts->subtype = m_strdup("pgp-encrypted");
861   t->parts->encoding = ENC7BIT;
862
863   t->parts->next = body_new();
864   t->parts->next->type = TYPEAPPLICATION;
865   t->parts->next->subtype = m_strdup("octet-stream");
866   t->parts->next->encoding = ENC7BIT;
867   t->parts->next->filename = outfile;
868   t->parts->next->use_disp = 1;
869   t->parts->next->disposition = DISPINLINE;
870   t->parts->next->unlink = 1;   /* delete after sending the message */
871   t->parts->next->d_filename = m_strdup("msg.asc"); /* non pgp/mime
872                                                            can save */
873
874   return t;
875 }
876
877 /*
878  * Implementation of `smime_build_smime_entity'.
879  */
880
881 /* Encrypt the mail body A to all keys given as space separated
882    fingerprints in KEYLIST and return the S/MIME encrypted body.  */
883 BODY *crypt_smime_build_smime_entity (BODY * a, char *keylist)
884 {
885   char *outfile = NULL;
886   BODY *t;
887   gpgme_key_t *rset = NULL;
888   gpgme_data_t plaintext;
889
890   rset = create_recipient_set (keylist, GPGME_PROTOCOL_CMS);
891   if (!rset)
892     return NULL;
893
894   plaintext = body_to_data_object (a, 0);
895   if (!plaintext) {
896     p_delete(&rset);
897     return NULL;
898   }
899
900   outfile = encrypt_gpgme_object (plaintext, rset, 1, 0);
901   gpgme_data_release (plaintext);
902   p_delete(&rset);
903   if (!outfile)
904     return NULL;
905
906   t = body_new();
907   t->type = TYPEAPPLICATION;
908   t->subtype = m_strdup("pkcs7-mime");
909   parameter_setval(&t->parameter, "name", "smime.p7m");
910   parameter_setval(&t->parameter, "smime-type", "enveloped-data");
911   t->encoding = ENCBASE64;      /* The output of OpenSSL SHOULD be binary */
912   t->use_disp = 1;
913   t->disposition = DISPATTACH;
914   t->d_filename = m_strdup("smime.p7m");
915   t->filename = outfile;
916   t->unlink = 1;                /*delete after sending the message */
917   t->parts = 0;
918   t->next = 0;
919
920   return t;
921 }
922
923
924 /* Implementation of `verify_one'. */
925
926 /* Display the common attributes of the signature summary SUM.
927    Return 1 if there is is a severe warning.
928  */
929 static int show_sig_summary (unsigned long sum,
930                              gpgme_ctx_t ctx, gpgme_key_t key, int idx,
931                              STATE * s)
932 {
933   int severe = 0;
934
935   if ((sum & GPGME_SIGSUM_KEY_REVOKED)) {
936     state_attach_puts (_("Warning: One of the keys has been revoked\n"), s);
937     severe = 1;
938   }
939
940   if ((sum & GPGME_SIGSUM_KEY_EXPIRED)) {
941     time_t at = key->subkeys->expires ? key->subkeys->expires : 0;
942
943     if (at) {
944       state_attach_puts (_("Warning: The key used to create the "
945                            "signature expired at: "), s);
946       print_time (at, s);
947       state_attach_puts ("\n", s);
948     }
949     else
950       state_attach_puts (_("Warning: At least one certification key "
951                            "has expired\n"), s);
952   }
953
954   if ((sum & GPGME_SIGSUM_SIG_EXPIRED)) {
955     gpgme_verify_result_t result;
956     gpgme_signature_t sig;
957     int i;
958
959     result = gpgme_op_verify_result (ctx);
960
961     for (sig = result->signatures, i = 0; sig && (i < idx);
962          sig = sig->next, i++);
963
964     state_attach_puts (_("Warning: The signature expired at: "), s);
965     print_time (sig ? sig->exp_timestamp : 0, s);
966     state_attach_puts ("\n", s);
967   }
968
969   if ((sum & GPGME_SIGSUM_KEY_MISSING))
970     state_attach_puts (_("Can't verify due to a missing "
971                          "key or certificate\n"), s);
972
973   if ((sum & GPGME_SIGSUM_CRL_MISSING)) {
974     state_attach_puts (_("The CRL is not available\n"), s);
975     severe = 1;
976   }
977
978   if ((sum & GPGME_SIGSUM_CRL_TOO_OLD)) {
979     state_attach_puts (_("Available CRL is too old\n"), s);
980     severe = 1;
981   }
982
983   if ((sum & GPGME_SIGSUM_BAD_POLICY))
984     state_attach_puts (_("A policy requirement was not met\n"), s);
985
986   if ((sum & GPGME_SIGSUM_SYS_ERROR)) {
987     const char *t0 = NULL, *t1 = NULL;
988     gpgme_verify_result_t result;
989     gpgme_signature_t sig;
990     int i;
991
992     state_attach_puts (_("A system error occurred"), s);
993
994     /* Try to figure out some more detailed system error information. */
995     result = gpgme_op_verify_result (ctx);
996     for (sig = result->signatures, i = 0; sig && (i < idx);
997          sig = sig->next, i++);
998     if (sig) {
999       t0 = "";
1000       t1 = sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
1001     }
1002
1003     if (t0 || t1) {
1004       state_attach_puts (": ", s);
1005       if (t0)
1006         state_attach_puts (t0, s);
1007       if (t1 && !(t0 && !m_strcmp(t0, t1))) {
1008         if (t0)
1009           state_attach_puts (",", s);
1010         state_attach_puts (t1, s);
1011       }
1012     }
1013     state_attach_puts ("\n", s);
1014   }
1015
1016   return severe;
1017 }
1018
1019
1020 static void show_fingerprint (gpgme_key_t key, STATE * state)
1021 {
1022   const char *s;
1023   int i, is_pgp;
1024   char *buf, *p;
1025   const char *prefix = _("Fingerprint: ");
1026   ssize_t bufsize;
1027
1028   if (!key)
1029     return;
1030   s = key->subkeys ? key->subkeys->fpr : NULL;
1031   if (!s)
1032     return;
1033   is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
1034
1035   bufsize = m_strlen(prefix) + m_strlen(s) * 4 + 2;
1036   buf = p_new(char, bufsize);
1037   m_strcpy(buf, bufsize, prefix);
1038   p = buf + m_strlen(buf);
1039   if (is_pgp && m_strlen(s) == 40) {     /* PGP v4 style formatted. */
1040     for (i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) {
1041       *p++ = s[0];
1042       *p++ = s[1];
1043       *p++ = s[2];
1044       *p++ = s[3];
1045       *p++ = ' ';
1046       if (i == 4)
1047         *p++ = ' ';
1048     }
1049   }
1050   else {
1051     for (i = 0; *s && s[1] && s[2]; s += 2, i++) {
1052       *p++ = s[0];
1053       *p++ = s[1];
1054       *p++ = is_pgp ? ' ' : ':';
1055       if (is_pgp && i == 7)
1056         *p++ = ' ';
1057     }
1058   }
1059
1060   /* just in case print remaining odd digits */
1061   for (; *s; s++)
1062     *p++ = *s;
1063   *p++ = '\n';
1064   *p = 0;
1065   state_attach_puts (buf, state);
1066   p_delete(&buf);
1067 }
1068
1069 /* Show the valididy of a key used for one signature. */
1070 static void show_one_sig_validity (gpgme_ctx_t ctx, int idx, STATE * s)
1071 {
1072   gpgme_verify_result_t result = NULL;
1073   gpgme_signature_t sig = NULL;
1074   const char *txt = NULL;
1075
1076   result = gpgme_op_verify_result (ctx);
1077   if (result)
1078     for (sig = result->signatures; sig && (idx > 0); sig = sig->next, idx--);
1079
1080   switch (sig ? sig->validity : 0) {
1081   case GPGME_VALIDITY_UNKNOWN:
1082     txt = _("WARNING: We have NO indication whether "
1083             "the key belongs to the person named " "as shown above\n");
1084     break;
1085   case GPGME_VALIDITY_UNDEFINED:
1086     break;
1087   case GPGME_VALIDITY_NEVER:
1088     txt = _("WARNING: The key does NOT BELONG to "
1089             "the person named as shown above\n");
1090     break;
1091   case GPGME_VALIDITY_MARGINAL:
1092     txt = _("WARNING: It is NOT certain that the key "
1093             "belongs to the person named as shown above\n");
1094     break;
1095   case GPGME_VALIDITY_FULL:
1096   case GPGME_VALIDITY_ULTIMATE:
1097     txt = NULL;
1098     break;
1099   }
1100   if (txt)
1101     state_attach_puts (txt, s);
1102 }
1103
1104 /* Show information about one signature.  This fucntion is called with
1105    the context CTX of a sucessful verification operation and the
1106    enumerator IDX which should start at 0 and incremete for each
1107    call/signature.
1108
1109    Return values are: 0 for normal procession, 1 for a bad signature,
1110    2 for a signature with a warning or -1 for no more signature.  */
1111 static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE * s)
1112 {
1113   time_t created;
1114   const char *fpr, *uid;
1115   gpgme_key_t key = NULL;
1116   int i, anybad = 0, anywarn = 0;
1117   unsigned int sum;
1118   gpgme_user_id_t uids = NULL;
1119   gpgme_verify_result_t result;
1120   gpgme_signature_t sig;
1121   gpgme_error_t err = GPG_ERR_NO_ERROR;
1122
1123   result = gpgme_op_verify_result (ctx);
1124   if (result) {
1125     /* FIXME: this code should use a static variable and remember
1126        the current position in the list of signatures, IMHO.
1127        -moritz.  */
1128
1129     for (i = 0, sig = result->signatures; sig && (i < idx);
1130          i++, sig = sig->next);
1131     if (!sig)
1132       return -1;                /* Signature not found.  */
1133
1134     if (signature_key) {
1135       gpgme_key_release (signature_key);
1136       signature_key = NULL;
1137     }
1138
1139     created = sig->timestamp;
1140     fpr = sig->fpr;
1141     sum = sig->summary;
1142
1143     if (gpg_err_code (sig->status) != GPG_ERR_NO_ERROR)
1144       anybad = 1;
1145
1146     err = gpgme_get_key2 (ctx, fpr, &key, 0);    /* secret key?  */
1147     if (!err) {
1148       uid = (key->uids && key->uids->uid) ? key->uids->uid : "[?]";
1149       if (!signature_key)
1150         signature_key = key;
1151     }
1152     else {
1153       key = NULL;               /* Old gpgme versions did not set KEY to NULL on
1154                                    error.   Do it here to avoid a double free. */
1155       uid = "[?]";
1156     }
1157
1158     if (!s || !s->fpout || !(s->flags & M_DISPLAY));    /* No state information so no way to print anything. */
1159     else if (err) {
1160       state_attach_puts (_("Error getting key information: "), s);
1161       state_attach_puts (gpg_strerror (err), s);
1162       state_attach_puts ("\n", s);
1163       anybad = 1;
1164     }
1165     else if ((sum & GPGME_SIGSUM_GREEN)) {
1166       state_attach_puts (_("Good signature from: "), s);
1167       state_attach_puts (uid, s);
1168       state_attach_puts ("\n", s);
1169       for (i = 1, uids = key->uids; uids; i++, uids = uids->next) {
1170         if (i == 1)
1171           /* Skip primary UID.  */
1172           continue;
1173         if (uids->revoked)
1174           continue;
1175         state_attach_puts (_("                aka: "), s);
1176         state_attach_puts (uids->uid, s);
1177         state_attach_puts ("\n", s);
1178       }
1179       state_attach_puts (_("            created: "), s);
1180       print_time (created, s);
1181       state_attach_puts ("\n", s);
1182       if (show_sig_summary (sum, ctx, key, idx, s))
1183         anywarn = 1;
1184       show_one_sig_validity (ctx, idx, s);
1185     }
1186     else if ((sum & GPGME_SIGSUM_RED)) {
1187       state_attach_puts (_("*BAD* signature claimed to be from: "), s);
1188       state_attach_puts (uid, s);
1189       state_attach_puts ("\n", s);
1190       show_sig_summary (sum, ctx, key, idx, s);
1191     }
1192     else if (!anybad && key && (key->protocol == GPGME_PROTOCOL_OpenPGP)) {     /* We can't decide (yellow) but this is a PGP key with a good
1193                                                                                    signature, so we display what a PGP user expects: The name,
1194                                                                                    fingerprint and the key validity (which is neither fully or
1195                                                                                    ultimate). */
1196       state_attach_puts (_("Good signature from: "), s);
1197       state_attach_puts (uid, s);
1198       state_attach_puts ("\n", s);
1199       state_attach_puts (_("            created: "), s);
1200       print_time (created, s);
1201       state_attach_puts ("\n", s);
1202       show_one_sig_validity (ctx, idx, s);
1203       show_fingerprint (key, s);
1204       if (show_sig_summary (sum, ctx, key, idx, s))
1205         anywarn = 1;
1206     }
1207     else {                      /* can't decide (yellow) */
1208
1209       state_attach_puts (_("Error checking signature"), s);
1210       state_attach_puts ("\n", s);
1211       show_sig_summary (sum, ctx, key, idx, s);
1212     }
1213
1214     if (key != signature_key)
1215       gpgme_key_release (key);
1216   }
1217
1218   return anybad ? 1 : anywarn ? 2 : 0;
1219 }
1220
1221 /* Do the actual verification step. With IS_SMIME set to true we
1222    assume S/MIME (surprise!) */
1223 static int verify_one (BODY * sigbdy, STATE * s,
1224                        const char *tempfile, int is_smime)
1225 {
1226   int badsig = -1;
1227   int anywarn = 0;
1228   int err;
1229   gpgme_ctx_t ctx;
1230   gpgme_data_t signature, message;
1231
1232   signature = file_to_data_object (s->fpin, sigbdy->offset, sigbdy->length);
1233   if (!signature)
1234     return -1;
1235
1236   /* We need to tell gpgme about the encoding because the backend can't
1237      auto-detect plain base-64 encoding which is used by S/MIME. */
1238   if (is_smime)
1239     gpgme_data_set_encoding (signature, GPGME_DATA_ENCODING_BASE64);
1240
1241   err = gpgme_data_new_from_file (&message, tempfile, 1);
1242   if (err) {
1243     gpgme_data_release (signature);
1244     mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
1245     return -1;
1246   }
1247   ctx = create_gpgme_context (is_smime);
1248
1249   /* Note: We don't need a current time output because GPGME avoids
1250      such an attack by separating the meta information from the
1251      data. */
1252   state_attach_puts (_("[-- Begin signature information --]\n"), s);
1253
1254   err = gpgme_op_verify (ctx, signature, message, NULL);
1255   mutt_need_hard_redraw ();
1256   if (err) {
1257     char buf[200];
1258
1259     snprintf (buf, sizeof (buf) - 1,
1260               _("Error: verification failed: %s\n"), gpgme_strerror (err));
1261     state_attach_puts (buf, s);
1262   }
1263   else {                        /* Verification succeeded, see what the result is. */
1264     int res, idx;
1265     int anybad = 0;
1266
1267     if (signature_key) {
1268       gpgme_key_release (signature_key);
1269       signature_key = NULL;
1270     }
1271
1272     for (idx = 0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) {
1273       if (res == 1)
1274         anybad = 1;
1275       else if (res == 2)
1276         anywarn = 2;
1277     }
1278     if (!anybad)
1279       badsig = 0;
1280   }
1281
1282   if (!badsig) {
1283     gpgme_verify_result_t result;
1284     gpgme_sig_notation_t notation;
1285     gpgme_signature_t sig;
1286
1287     result = gpgme_op_verify_result (ctx);
1288     if (result) {
1289       for (sig = result->signatures; sig; sig = sig->next) {
1290         if (sig->notations) {
1291           state_attach_puts ("*** Begin Notation (signature by: ", s);
1292           state_attach_puts (sig->fpr, s);
1293           state_attach_puts (") ***\n", s);
1294           for (notation = sig->notations; notation; notation = notation->next)
1295           {
1296             if (notation->name) {
1297               state_attach_puts (notation->name, s);
1298               state_attach_puts ("=", s);
1299             }
1300             if (notation->value) {
1301               state_attach_puts (notation->value, s);
1302               if (!(*notation->value
1303                     && (notation->value[m_strlen(notation->value) - 1] ==
1304                         '\n')))
1305                 state_attach_puts ("\n", s);
1306             }
1307           }
1308           state_attach_puts ("*** End Notation ***\n", s);
1309         }
1310       }
1311     }
1312   }
1313
1314   gpgme_release (ctx);
1315
1316   state_attach_puts (_("[-- End signature information --]\n\n"), s);
1317
1318   return badsig ? 1 : anywarn ? 2 : 0;
1319 }
1320
1321 int crypt_pgp_verify_one (BODY * sigbdy, STATE * s, const char *tempfile)
1322 {
1323   return verify_one (sigbdy, s, tempfile, 0);
1324 }
1325
1326 int crypt_smime_verify_one (BODY * sigbdy, STATE * s, const char *tempfile)
1327 {
1328   return verify_one (sigbdy, s, tempfile, 1);
1329 }
1330
1331 /*
1332  * Implementation of `decrypt_part'.
1333  */
1334
1335 /* Decrypt a PGP or SMIME message (depending on the boolean flag
1336    IS_SMIME) with body A described further by state S.  Write
1337    plaintext out to file FPOUT and return a new body.  For PGP returns
1338    a flag in R_IS_SIGNED to indicate whether this is a combined
1339    encrypted and signed message, for S/MIME it returns true when it is
1340    not a encrypted but a signed message.  */
1341 static BODY *decrypt_part (BODY * a, STATE * s, FILE * fpout, int is_smime,
1342                            int *r_is_signed)
1343 {
1344   struct stat info;
1345   BODY *tattach;
1346   int err = 0;
1347   gpgme_ctx_t ctx;
1348   gpgme_data_t ciphertext, plaintext;
1349   int maybe_signed = 0;
1350   int anywarn = 0;
1351   int sig_stat = 0;
1352
1353   if (r_is_signed)
1354     *r_is_signed = 0;
1355
1356   ctx = create_gpgme_context (is_smime);
1357
1358 restart:
1359   /* Make a data object from the body, create context etc. */
1360   ciphertext = file_to_data_object (s->fpin, a->offset, a->length);
1361   if (!ciphertext)
1362     return NULL;
1363   plaintext = create_gpgme_data ();
1364
1365   /* Do the decryption or the verification in case of the S/MIME hack. */
1366   if ((!is_smime) || maybe_signed) {
1367     if (!is_smime)
1368       err = gpgme_op_decrypt_verify (ctx, ciphertext, plaintext);
1369     else if (maybe_signed)
1370       err = gpgme_op_verify (ctx, ciphertext, NULL, plaintext);
1371
1372     {
1373       /* Check wether signatures have been verified.  */
1374       gpgme_verify_result_t verify_result = gpgme_op_verify_result (ctx);
1375
1376       if (verify_result->signatures)
1377         sig_stat = 1;
1378     }
1379   }
1380   else
1381     err = gpgme_op_decrypt (ctx, ciphertext, plaintext);
1382   gpgme_data_release (ciphertext);
1383   if (err) {
1384     if (is_smime && !maybe_signed && gpg_err_code (err) == GPG_ERR_NO_DATA) {
1385       /* Check whether this might be a signed message despite what
1386          the mime header told us.  Retry then.  gpgsm returns the
1387          error information "unsupported Algorithm '?'" but gpgme
1388          will not store this unknown algorithm, thus we test that
1389          it has not been set. */
1390       gpgme_decrypt_result_t result;
1391
1392       result = gpgme_op_decrypt_result (ctx);
1393       if (!result->unsupported_algorithm) {
1394         maybe_signed = 1;
1395         gpgme_data_release (plaintext);
1396         goto restart;
1397       }
1398     }
1399     mutt_need_hard_redraw ();
1400     if ((s->flags & M_DISPLAY)) {
1401       char buf[200];
1402
1403       snprintf (buf, sizeof (buf) - 1,
1404                 _("[-- Error: decryption failed: %s --]\n\n"),
1405                 gpgme_strerror (err));
1406       state_attach_puts (buf, s);
1407     }
1408     gpgme_data_release (plaintext);
1409     gpgme_release (ctx);
1410     return NULL;
1411   }
1412   mutt_need_hard_redraw ();
1413
1414   /* Read the output from GPGME, and make sure to change CRLF to LF,
1415      otherwise read_mime_header has a hard time parsing the message.  */
1416   if (data_object_to_stream (plaintext, fpout)) {
1417     gpgme_data_release (plaintext);
1418     gpgme_release (ctx);
1419     return NULL;
1420   }
1421   gpgme_data_release (plaintext);
1422
1423   a->is_signed_data = 0;
1424   if (sig_stat) {
1425     int res, idx;
1426     int anybad = 0;
1427
1428     if (maybe_signed)
1429       a->is_signed_data = 1;
1430     if (r_is_signed)
1431       *r_is_signed = -1;        /* A signature exists. */
1432
1433     if ((s->flags & M_DISPLAY))
1434       state_attach_puts (_("[-- Begin signature " "information --]\n"), s);
1435     for (idx = 0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) {
1436       if (res == 1)
1437         anybad = 1;
1438       else if (res == 2)
1439         anywarn = 1;
1440     }
1441     if (!anybad && idx && r_is_signed && *r_is_signed)
1442       *r_is_signed = anywarn ? 2 : 1;   /* Good signature. */
1443
1444     if ((s->flags & M_DISPLAY))
1445       state_attach_puts (_("[-- End signature " "information --]\n\n"), s);
1446   }
1447   gpgme_release (ctx);
1448   ctx = NULL;
1449
1450   fflush (fpout);
1451   rewind (fpout);
1452   tattach = mutt_read_mime_header (fpout, 0);
1453   if (tattach) {
1454     /*
1455      * Need to set the length of this body part.
1456      */
1457     fstat (fileno (fpout), &info);
1458     tattach->length = info.st_size - tattach->offset;
1459
1460     tattach->warnsig = anywarn;
1461
1462     /* See if we need to recurse on this MIME part.  */
1463     mutt_parse_part (fpout, tattach);
1464   }
1465
1466   return tattach;
1467 }
1468
1469 /* Decrypt a PGP/MIME message in FPIN and B and return a new body and
1470    the stream in CUR and FPOUT.  Returns 0 on success. */
1471 int crypt_pgp_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur)
1472 {
1473   char tempfile[_POSIX_PATH_MAX];
1474   STATE s;
1475   BODY *first_part = b;
1476   int is_signed;
1477
1478   first_part->goodsig = 0;
1479   first_part->warnsig = 0;
1480
1481   if (!mutt_is_multipart_encrypted (b))
1482     return -1;
1483
1484   if (!b->parts || !b->parts->next)
1485     return -1;
1486
1487   b = b->parts->next;
1488
1489   p_clear(&s, 1);
1490   s.fpin = fpin;
1491   *fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
1492   if (!*fpout) {
1493     mutt_perror (_("Can't create temporary file"));
1494     return -1;
1495   }
1496   unlink (tempfile);
1497
1498   *cur = decrypt_part (b, &s, *fpout, 0, &is_signed);
1499   rewind (*fpout);
1500   if (is_signed > 0)
1501     first_part->goodsig = 1;
1502
1503   return *cur ? 0 : -1;
1504 }
1505
1506
1507 /* Decrypt a S/MIME message in FPIN and B and return a new body and
1508    the stream in CUR and FPOUT.  Returns 0 on success. */
1509 int crypt_smime_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b,
1510                               BODY ** cur)
1511 {
1512   char tempfile[_POSIX_PATH_MAX];
1513   STATE s;
1514   FILE *tmpfp = NULL;
1515   int is_signed;
1516   long saved_b_offset;
1517   ssize_t saved_b_length;
1518   int saved_b_type;
1519
1520   if (!mutt_is_application_smime (b))
1521     return -1;
1522
1523   if (b->parts)
1524     return -1;
1525
1526   /* Decode the body - we need to pass binary CMS to the
1527      backend.  The backend allows for Base64 encoded data but it does
1528      not allow for QP which I have seen in some messages.  So better
1529      do it here. */
1530   saved_b_type = b->type;
1531   saved_b_offset = b->offset;
1532   saved_b_length = b->length;
1533   p_clear(&s, 1);
1534   s.fpin = fpin;
1535   fseeko (s.fpin, b->offset, 0);
1536   tmpfp = m_tempfile (tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
1537   if (!tmpfp) {
1538     mutt_perror (_("Can't create temporary file"));
1539     return -1;
1540   }
1541   mutt_unlink (tempfile);
1542
1543   s.fpout = tmpfp;
1544   mutt_decode_attachment (b, &s);
1545   fflush (tmpfp);
1546   b->length = ftello (s.fpout);
1547   b->offset = 0;
1548   rewind (tmpfp);
1549
1550   p_clear(&s, 1);
1551   s.fpin = tmpfp;
1552   s.fpout = 0;
1553   *fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
1554   if (!*fpout) {
1555     mutt_perror (_("Can't create temporary file"));
1556     return -1;
1557   }
1558   mutt_unlink (tempfile);
1559
1560   *cur = decrypt_part (b, &s, *fpout, 1, &is_signed);
1561   if (*cur)
1562     (*cur)->goodsig = is_signed > 0;
1563   b->type = saved_b_type;
1564   b->length = saved_b_length;
1565   b->offset = saved_b_offset;
1566   m_fclose(&tmpfp);
1567   rewind (*fpout);
1568   if (*cur && !is_signed && !(*cur)->parts
1569       && mutt_is_application_smime (*cur)) {
1570     /* Assume that this is a opaque signed s/mime message.  This is
1571        an ugly way of doing it but we have anyway a problem with
1572        arbitrary encoded S/MIME messages: Only the outer part may be
1573        encrypted.  The entire mime parsing should be revamped,
1574        probably by keeping the temportary files so that we don't
1575        need to decrypt them all the time.  Inner parts of an
1576        encrypted part can then pint into this file and tehre won't
1577        never be a need to decrypt again.  This needs a partial
1578        rewrite of the MIME engine. */
1579     BODY *bb = *cur;
1580     BODY *tmp_b;
1581
1582     saved_b_type = bb->type;
1583     saved_b_offset = bb->offset;
1584     saved_b_length = bb->length;
1585     p_clear(&s, 1);
1586     s.fpin = *fpout;
1587     fseeko (s.fpin, bb->offset, 0);
1588     tmpfp = m_tempfile (tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
1589     if (!tmpfp) {
1590       mutt_perror (_("Can't create temporary file"));
1591       return -1;
1592     }
1593     mutt_unlink (tempfile);
1594
1595     s.fpout = tmpfp;
1596     mutt_decode_attachment (bb, &s);
1597     fflush (tmpfp);
1598     bb->length = ftello (s.fpout);
1599     bb->offset = 0;
1600     rewind (tmpfp);
1601     m_fclose(&*fpout);
1602
1603     p_clear(&s, 1);
1604     s.fpin = tmpfp;
1605     s.fpout = 0;
1606     *fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
1607     if (!*fpout) {
1608       mutt_perror (_("Can't create temporary file"));
1609       return -1;
1610     }
1611     mutt_unlink (tempfile);
1612
1613     tmp_b = decrypt_part (bb, &s, *fpout, 1, &is_signed);
1614     if (tmp_b)
1615       tmp_b->goodsig = is_signed > 0;
1616     bb->type = saved_b_type;
1617     bb->length = saved_b_length;
1618     bb->offset = saved_b_offset;
1619     m_fclose(&tmpfp);
1620     rewind (*fpout);
1621     body_list_wipe(cur);
1622     *cur = tmp_b;
1623   }
1624   return *cur ? 0 : -1;
1625 }
1626
1627
1628 /*
1629  * Implementation of `pgp_check_traditional'.
1630  */
1631
1632 static int pgp_check_traditional_one_body (FILE * fp, BODY * b,
1633                                            int tagged_only)
1634 {
1635   char tempfile[_POSIX_PATH_MAX];
1636   char buf[HUGE_STRING];
1637   FILE *tfp;
1638   int tempfd;
1639
1640   short sgn = 0;
1641   short enc = 0;
1642
1643   if (b->type != TYPETEXT)
1644     return 0;
1645
1646   if (tagged_only && !b->tagged)
1647     return 0;
1648
1649   tempfd = m_tempfd(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
1650   if (mutt_decode_save_attachment (fp, b, tempfd, 0) != 0) {
1651     unlink (tempfile);
1652     return 0;
1653   }
1654
1655   if ((tfp = fopen(tempfile, "r")) == NULL) {
1656     unlink (tempfile);
1657     return 0;
1658   }
1659
1660   while (fgets (buf, sizeof (buf), tfp)) {
1661     if (!m_strncmp("-----BEGIN PGP ", buf, 15)) {
1662       if (!m_strcmp("MESSAGE-----\n", buf + 15))
1663         enc = 1;
1664       else if (!m_strcmp("SIGNED MESSAGE-----\n", buf + 15))
1665         sgn = 1;
1666     }
1667   }
1668   m_fclose(&tfp);
1669   unlink (tempfile);
1670
1671   if (!enc && !sgn)
1672     return 0;
1673
1674   /* fix the content type */
1675
1676   parameter_setval(&b->parameter, "format", "fixed");
1677   parameter_setval(&b->parameter, "x-action",
1678                    enc ? "pgp-encrypted" : "pgp-signed");
1679   return 1;
1680 }
1681
1682 int crypt_pgp_check_traditional (FILE * fp, BODY * b, int tagged_only)
1683 {
1684   int rv = 0;
1685   int r;
1686
1687   for (; b; b = b->next) {
1688     if (is_multipart (b))
1689       rv = (crypt_pgp_check_traditional (fp, b->parts, tagged_only) || rv);
1690     else if (b->type == TYPETEXT) {
1691       if ((r = mutt_is_application_pgp (b)))
1692         rv = (rv || r);
1693       else
1694         rv = (pgp_check_traditional_one_body (fp, b, tagged_only) || rv);
1695     }
1696   }
1697   return rv;
1698 }
1699
1700
1701 /* Implementation of `application_handler'. */
1702
1703 /*
1704   Copy a clearsigned message, and strip the signature and PGP's
1705   dash-escaping.
1706
1707   XXX - charset handling: We assume that it is safe to do
1708   character set decoding first, dash decoding second here, while
1709   we do it the other way around in the main handler.
1710
1711   (Note that we aren't worse than Outlook & Cie in this, and also
1712   note that we can successfully handle anything produced by any
1713   existing versions of mutt.)  */
1714
1715 static void copy_clearsigned (gpgme_data_t data, STATE * s, char *charset)
1716 {
1717   char buf[HUGE_STRING];
1718   short complete, armor_header;
1719   fgetconv_t *fc;
1720   char *fname;
1721   FILE *fp;
1722
1723   fname = data_object_to_tempfile (data, &fp);
1724   if (!fname)
1725     return;
1726   unlink (fname);
1727   p_delete(&fname);
1728
1729   fc = fgetconv_open (fp, charset, MCharset.charset, M_ICONV_HOOK_FROM);
1730
1731   for (complete = 1, armor_header = 1;
1732        fgetconvs (buf, sizeof (buf), fc) != NULL;
1733        complete = strchr (buf, '\n') != NULL) {
1734     if (!complete) {
1735       if (!armor_header)
1736         state_puts (buf, s);
1737       continue;
1738     }
1739
1740     if (!m_strcmp(buf, "-----BEGIN PGP SIGNATURE-----\n"))
1741       break;
1742
1743     if (armor_header) {
1744       if (buf[0] == '\n')
1745         armor_header = 0;
1746       continue;
1747     }
1748
1749     if (s->prefix)
1750       state_puts (s->prefix, s);
1751
1752     if (buf[0] == '-' && buf[1] == ' ')
1753       state_puts (buf + 2, s);
1754     else
1755       state_puts (buf, s);
1756   }
1757
1758   fgetconv_close (&fc);
1759   m_fclose(&fp);
1760 }
1761
1762
1763 /* Support for classic_application/pgp */
1764 int crypt_pgp_application_pgp_handler (BODY * m, STATE * s)
1765 {
1766   int needpass = -1, pgp_keyblock = 0;
1767   int clearsign = 0;
1768   long start_pos = 0;
1769   long bytes;
1770   off_t last_pos, offset;
1771   char buf[HUGE_STRING];
1772   FILE *pgpout = NULL;
1773
1774   gpgme_error_t err = 0;
1775   gpgme_data_t armored_data = NULL;
1776
1777   short maybe_goodsig = 1;
1778   short have_any_sigs = 0;
1779
1780   char body_charset[STRING];    /* Only used for clearsigned messages. */
1781
1782   /* For clearsigned messages we won't be able to get a character set
1783      but we know that this may only be text thus we assume Latin-1
1784      here. */
1785   if (!mutt_get_body_charset (body_charset, sizeof (body_charset), m))
1786     m_strcpy(body_charset, sizeof(body_charset), "iso-8859-1");
1787
1788   fseeko (s->fpin, m->offset, 0);
1789   last_pos = m->offset;
1790
1791   for (bytes = m->length; bytes > 0;) {
1792     if (fgets (buf, sizeof (buf), s->fpin) == NULL)
1793       break;
1794
1795     offset = ftello (s->fpin);
1796     bytes -= (offset - last_pos);       /* don't rely on m_strlen(buf) */
1797     last_pos = offset;
1798
1799     if (!m_strncmp("-----BEGIN PGP ", buf, 15)) {
1800       clearsign = 0;
1801       start_pos = last_pos;
1802
1803       if (!m_strcmp("MESSAGE-----\n", buf + 15))
1804         needpass = 1;
1805       else if (!m_strcmp("SIGNED MESSAGE-----\n", buf + 15)) {
1806         clearsign = 1;
1807         needpass = 0;
1808       }
1809       else if (!option (OPTDONTHANDLEPGPKEYS) &&
1810                !m_strcmp("PUBLIC KEY BLOCK-----\n", buf + 15)) {
1811         needpass = 0;
1812         pgp_keyblock = 1;
1813       }
1814       else {
1815         /* XXX - we may wish to recode here */
1816         if (s->prefix)
1817           state_puts (s->prefix, s);
1818         state_puts (buf, s);
1819         continue;
1820       }
1821
1822       have_any_sigs = (have_any_sigs || (clearsign && (s->flags & M_VERIFY)));
1823
1824       /* Copy PGP material to an data container */
1825       armored_data = create_gpgme_data ();
1826       gpgme_data_write (armored_data, buf, m_strlen(buf));
1827       while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL) {
1828         offset = ftello (s->fpin);
1829         bytes -= (offset - last_pos);   /* don't rely on m_strlen(buf) */
1830         last_pos = offset;
1831
1832         gpgme_data_write (armored_data, buf, m_strlen(buf));
1833
1834         if ((needpass && !m_strcmp("-----END PGP MESSAGE-----\n", buf))
1835             || (!needpass
1836                 && (!m_strcmp("-----END PGP SIGNATURE-----\n", buf)
1837                     || !m_strcmp("-----END PGP PUBLIC KEY BLOCK-----\n",
1838                                      buf))))
1839           break;
1840       }
1841
1842       /* Invoke PGP if needed */
1843       if (!clearsign || (s->flags & M_VERIFY)) {
1844         unsigned int sig_stat = 0;
1845         gpgme_data_t plaintext;
1846         gpgme_ctx_t ctx;
1847
1848         plaintext = create_gpgme_data ();
1849         ctx = create_gpgme_context (0);
1850
1851         if (clearsign)
1852           err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);
1853         else {
1854           err = gpgme_op_decrypt_verify (ctx, armored_data, plaintext);
1855           if (gpg_err_code (err) == GPG_ERR_NO_DATA) {
1856             /* Decrypt verify can't handle signed only messages. */
1857             err = (gpgme_data_seek (armored_data, 0, SEEK_SET) == -1)
1858               ? gpgme_error_from_errno (errno) : 0;
1859             /* Must release plaintext so that we supply an
1860                uninitialized object. */
1861             gpgme_data_release (plaintext);
1862             plaintext = create_gpgme_data ();
1863             err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);
1864           }
1865         }
1866
1867         if (err) {
1868           char errbuf[200];
1869
1870           snprintf (errbuf, sizeof (errbuf) - 1,
1871                     _("Error: decryption/verification failed: %s\n"),
1872                     gpgme_strerror (err));
1873           state_attach_puts (errbuf, s);
1874         }
1875         else {                  /* Decryption/Verification succeeded */
1876           char *tmpfname;
1877
1878           {
1879             /* Check wether signatures have been verified.  */
1880             gpgme_verify_result_t verify_result;
1881
1882             verify_result = gpgme_op_verify_result (ctx);
1883             if (verify_result->signatures)
1884               sig_stat = 1;
1885           }
1886
1887           have_any_sigs = 0;
1888           maybe_goodsig = 0;
1889           if ((s->flags & M_DISPLAY) && sig_stat) {
1890             int res, idx;
1891             int anybad = 0;
1892             int anywarn = 0;
1893
1894             state_attach_puts (_("[-- Begin signature "
1895                                  "information --]\n"), s);
1896             have_any_sigs = 1;
1897             for (idx = 0;
1898                  (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) {
1899               if (res == 1)
1900                 anybad = 1;
1901               else if (res == 2)
1902                 anywarn = 1;
1903             }
1904             if (!anybad && idx)
1905               maybe_goodsig = 1;
1906
1907             state_attach_puts (_("[-- End signature "
1908                                  "information --]\n\n"), s);
1909           }
1910
1911           tmpfname = data_object_to_tempfile (plaintext, &pgpout);
1912           if (!tmpfname) {
1913             pgpout = NULL;
1914             state_attach_puts (_("Error: copy data failed\n"), s);
1915           }
1916           else {
1917             unlink (tmpfname);
1918             p_delete(&tmpfname);
1919           }
1920         }
1921         gpgme_release (ctx);
1922       }
1923
1924       /*
1925        * Now, copy cleartext to the screen.  NOTE - we expect that PGP
1926        * outputs utf-8 cleartext.  This may not always be true, but it
1927        * seems to be a reasonable guess.
1928        */
1929
1930       if (s->flags & M_DISPLAY) {
1931         if (needpass)
1932           state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s);
1933         else if (pgp_keyblock)
1934           state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"), s);
1935         else
1936           state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"), s);
1937       }
1938
1939       if (clearsign) {
1940         copy_clearsigned (armored_data, s, body_charset);
1941       }
1942       else if (pgpout) {
1943         fgetconv_t *fc;
1944         int c;
1945
1946         rewind (pgpout);
1947         fc = fgetconv_open (pgpout, "utf-8", MCharset.charset, 0);
1948         while ((c = fgetconv (fc)) != EOF) {
1949           state_putc (c, s);
1950           if (c == '\n' && s->prefix)
1951             state_puts (s->prefix, s);
1952         }
1953         fgetconv_close (&fc);
1954       }
1955
1956       if (s->flags & M_DISPLAY) {
1957         state_putc ('\n', s);
1958         if (needpass)
1959           state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
1960         else if (pgp_keyblock)
1961           state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);
1962         else
1963           state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);
1964       }
1965
1966       if (pgpout) {
1967         m_fclose(&pgpout);
1968       }
1969     }
1970     else {
1971       /* XXX - we may wish to recode here */
1972       if (s->prefix)
1973         state_puts (s->prefix, s);
1974       state_puts (buf, s);
1975     }
1976   }
1977
1978   m->goodsig = (maybe_goodsig && have_any_sigs);
1979
1980   if (needpass == -1) {
1981     state_attach_puts (_("[-- Error: could not find beginning"
1982                          " of PGP message! --]\n\n"), s);
1983     return (-1);
1984   }
1985   return (err);
1986 }
1987
1988 /* Implementation of `encrypted_handler'. */
1989
1990 /* MIME handler for pgp/mime encrypted messages. */
1991 int crypt_pgp_encrypted_handler (BODY * a, STATE * s)
1992 {
1993   char tempfile[_POSIX_PATH_MAX];
1994   FILE *fpout;
1995   BODY *tattach;
1996   BODY *orig_body = a;
1997   int is_signed;
1998   int rc = 0;
1999
2000   a = a->parts;
2001   if (!a || a->type != TYPEAPPLICATION || !a->subtype
2002       || ascii_strcasecmp ("pgp-encrypted", a->subtype)
2003       || !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype
2004       || ascii_strcasecmp ("octet-stream", a->next->subtype)) {
2005     if (s->flags & M_DISPLAY)
2006       state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"),
2007                          s);
2008     return (-1);
2009   }
2010
2011   /* Move forward to the application/pgp-encrypted body. */
2012   a = a->next;
2013
2014   fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
2015   if (!fpout) {
2016     if (s->flags & M_DISPLAY)
2017       state_attach_puts (_("[-- Error: could not create temporary file! "
2018                            "--]\n"), s);
2019     return (-1);
2020   }
2021
2022   tattach = decrypt_part (a, s, fpout, 0, &is_signed);
2023   if (tattach) {
2024     tattach->goodsig = is_signed > 0;
2025
2026     if (s->flags & M_DISPLAY)
2027       state_attach_puts (is_signed ?
2028                          _
2029                          ("[-- The following data is PGP/MIME signed and encrypted --]\n\n") :
2030                          _("[-- The following data is PGP/MIME encrypted --]\n\n"), s);
2031
2032     {
2033       FILE *savefp = s->fpin;
2034
2035       s->fpin = fpout;
2036       rc = mutt_body_handler (tattach, s);
2037       s->fpin = savefp;
2038     }
2039
2040     /*
2041      * if a multipart/signed is the _only_ sub-part of a
2042      * multipart/encrypted, cache signature verification
2043      * status.
2044      */
2045     if (mutt_is_multipart_signed (tattach) && !tattach->next)
2046       orig_body->goodsig |= tattach->goodsig;
2047
2048     if (s->flags & M_DISPLAY) {
2049       state_puts ("\n", s);
2050       state_attach_puts (is_signed ?
2051                          _
2052                          ("[-- End of PGP/MIME signed and encrypted data --]\n")
2053                          : _("[-- End of PGP/MIME encrypted data --]\n"), s);
2054     }
2055
2056     body_list_wipe(&tattach);
2057   }
2058
2059   m_fclose(&fpout);
2060   mutt_unlink (tempfile);
2061   return (rc);
2062 }
2063
2064 /* Support for application/smime */
2065 int crypt_smime_application_smime_handler (BODY * a, STATE * s)
2066 {
2067   char tempfile[_POSIX_PATH_MAX];
2068   FILE *fpout;
2069   BODY *tattach;
2070   int is_signed;
2071   int rc = 0;
2072
2073   a->warnsig = 0;
2074   fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
2075   if (!fpout) {
2076     if (s->flags & M_DISPLAY)
2077       state_attach_puts (_("[-- Error: could not create temporary file! "
2078                            "--]\n"), s);
2079     return (-1);
2080   }
2081
2082   tattach = decrypt_part (a, s, fpout, 1, &is_signed);
2083   if (tattach) {
2084     tattach->goodsig = is_signed > 0;
2085
2086     if (s->flags & M_DISPLAY)
2087       state_attach_puts (is_signed ?
2088                          _("[-- The following data is S/MIME signed --]\n\n") :
2089                          _("[-- The following data is S/MIME encrypted --]\n\n"), s);
2090
2091     {
2092       FILE *savefp = s->fpin;
2093
2094       s->fpin = fpout;
2095       rc = mutt_body_handler (tattach, s);
2096       s->fpin = savefp;
2097     }
2098
2099     /*
2100      * if a multipart/signed is the _only_ sub-part of a
2101      * multipart/encrypted, cache signature verification
2102      * status.
2103      */
2104     if (mutt_is_multipart_signed (tattach) && !tattach->next) {
2105       if (!(a->goodsig = tattach->goodsig))
2106         a->warnsig = tattach->warnsig;
2107     }
2108     else if (tattach->goodsig) {
2109       a->goodsig = 1;
2110       a->warnsig = tattach->warnsig;
2111     }
2112
2113     if (s->flags & M_DISPLAY) {
2114       state_puts ("\n", s);
2115       state_attach_puts (is_signed ?
2116                          _("[-- End of S/MIME signed data --]\n") :
2117                          _("[-- End of S/MIME encrypted data --]\n"), s);
2118     }
2119
2120     body_list_wipe(&tattach);
2121   }
2122
2123   m_fclose(&fpout);
2124   mutt_unlink (tempfile);
2125   return (rc);
2126 }
2127
2128
2129 /*
2130  * Format an entry on the CRYPT key selection menu.
2131  *
2132  * %n   number
2133  * %k   key id          %K      key id of the principal key
2134  * %u   user id
2135  * %a   algorithm       %A      algorithm of the princ. key
2136  * %l   length          %L      length of the princ. key
2137  * %f   flags           %F      flags of the princ. key
2138  * %c   capabilities    %C      capabilities of the princ. key
2139  * %t   trust/validity of the key-uid association
2140  * %p           protocol
2141  * %[...] date of key using strftime(3)
2142  */
2143
2144 static const char *
2145 crypt_entry_fmt (char *dest, ssize_t destlen, char op,
2146                  const char *src, const char *prefix,
2147                  const char *ifstr, const char *elstr,
2148                  anytype data, format_flag flags)
2149 {
2150   char fmt[16];
2151   crypt_entry_t *entry;
2152   crypt_key_t *key;
2153   int kflags = 0;
2154   int optional = (flags & M_FORMAT_OPTIONAL);
2155   const char *s = NULL;
2156   unsigned long val;
2157
2158   entry = data.ptr;
2159   key = entry->key;
2160
2161 /*    if (isupper ((unsigned char) op)) */
2162 /*      key = pkey; */
2163
2164   kflags = (key->flags          /*| (pkey->flags & KEYFLAG_RESTRICTIONS)
2165                                    | uid->flags */ );
2166
2167   switch (ascii_tolower (op)) {
2168   case '[':
2169     {
2170       const char *cp;
2171       char buf2[STRING], *p;
2172       int do_locales;
2173       struct tm *tm;
2174       ssize_t len;
2175
2176       p = dest;
2177
2178       cp = src;
2179       if (*cp == '!') {
2180         do_locales = 0;
2181         cp++;
2182       }
2183       else
2184         do_locales = 1;
2185
2186       len = destlen - 1;
2187       while (len > 0 && *cp != ']') {
2188         if (*cp == '%') {
2189           cp++;
2190           if (len >= 2) {
2191             *p++ = '%';
2192             *p++ = *cp;
2193             len -= 2;
2194           }
2195           else
2196             break;              /* not enough space */
2197           cp++;
2198         }
2199         else {
2200           *p++ = *cp++;
2201           len--;
2202         }
2203       }
2204       *p = 0;
2205
2206       if (do_locales && Locale)
2207         setlocale (LC_TIME, Locale);
2208
2209       {
2210         time_t tt = 0;
2211
2212         if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
2213           tt = key->kobj->subkeys->timestamp;
2214
2215         tm = localtime (&tt);
2216       }
2217       strftime (buf2, sizeof (buf2), dest, tm);
2218
2219       if (do_locales)
2220         setlocale (LC_TIME, "C");
2221
2222       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2223       snprintf (dest, destlen, fmt, buf2);
2224       if (len > 0)
2225         src = cp + 1;
2226     }
2227     break;
2228   case 'n':
2229     if (!optional) {
2230       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
2231       snprintf (dest, destlen, fmt, entry->num);
2232     }
2233     break;
2234   case 'k':
2235     if (!optional) {
2236       /* fixme: we need a way to distinguish between main and subkeys.
2237          Store the idx in entry? */
2238       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2239       snprintf (dest, destlen, fmt, crypt_keyid (key));
2240     }
2241     break;
2242   case 'u':
2243     if (!optional) {
2244       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2245       snprintf (dest, destlen, fmt, key->uid);
2246     }
2247     break;
2248   case 'a':
2249     if (!optional) {
2250       snprintf (fmt, sizeof (fmt), "%%%s.3s", prefix);
2251       if (key->kobj->subkeys)
2252         s = gpgme_pubkey_algo_name (key->kobj->subkeys->pubkey_algo);
2253       else
2254         s = "?";
2255       snprintf (dest, destlen, fmt, s);
2256     }
2257     break;
2258   case 'l':
2259     if (!optional) {
2260       snprintf (fmt, sizeof (fmt), "%%%slu", prefix);
2261       if (key->kobj->subkeys)
2262         val = key->kobj->subkeys->length;
2263       else
2264         val = 0;
2265       snprintf (dest, destlen, fmt, val);
2266     }
2267     break;
2268   case 'f':
2269     if (!optional) {
2270       snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2271       snprintf (dest, destlen, fmt, crypt_flags (kflags));
2272     }
2273     else if (!(kflags & (KEYFLAG_RESTRICTIONS)))
2274       optional = 0;
2275     break;
2276   case 'c':
2277     if (!optional) {
2278       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2279       snprintf (dest, destlen, fmt, crypt_key_abilities (kflags));
2280     }
2281     else if (!(kflags & (KEYFLAG_ABILITIES)))
2282       optional = 0;
2283     break;
2284   case 't':
2285     if ((kflags & KEYFLAG_ISX509))
2286       s = "x";
2287     else {
2288       gpgme_user_id_t uid = NULL;
2289       int i = 0;
2290
2291       for (i = 0, uid = key->kobj->uids; uid && (i < key->idx);
2292            i++, uid = uid->next);
2293       if (uid)
2294         switch (uid->validity) {
2295         case GPGME_VALIDITY_UNDEFINED:
2296           s = "q";
2297           break;
2298         case GPGME_VALIDITY_NEVER:
2299           s = "n";
2300           break;
2301         case GPGME_VALIDITY_MARGINAL:
2302           s = "m";
2303           break;
2304         case GPGME_VALIDITY_FULL:
2305           s = "f";
2306           break;
2307         case GPGME_VALIDITY_ULTIMATE:
2308           s = "u";
2309           break;
2310         case GPGME_VALIDITY_UNKNOWN:
2311         default:
2312           s = "?";
2313           break;
2314         }
2315     }
2316     snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2317     snprintf (dest, destlen, fmt, s ? *s : 'B');
2318     break;
2319   case 'p':
2320     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2321     snprintf (dest, destlen, fmt,
2322               gpgme_get_protocol_name (key->kobj->protocol));
2323     break;
2324
2325   default:
2326     *dest = '\0';
2327   }
2328
2329   if (flags & M_FORMAT_OPTIONAL)
2330     m_strformat(dest, destlen, 0, optional ? ifstr: elstr,
2331                 mutt_attach_fmt, data, 0);
2332   return src;
2333 }
2334
2335 /* Used by the display fucntion to format a line. */
2336 static void crypt_entry (char *s, ssize_t l, MUTTMENU * menu, int num)
2337 {
2338   crypt_key_t **key_table = (crypt_key_t **) menu->data;
2339   crypt_entry_t entry;
2340
2341   entry.key = key_table[num];
2342   entry.num = num + 1;
2343
2344   m_strformat(s, l, COLS - SW, PgpEntryFormat, crypt_entry_fmt, &entry,
2345               option(OPTARROWCURSOR) ? M_FORMAT_ARROWCURSOR : 0);
2346 }
2347
2348 /* Compare two addresses and the keyid to be used for sorting. */
2349 static int _crypt_compare_address (const void *a, const void *b)
2350 {
2351   crypt_key_t **s = (crypt_key_t **) a;
2352   crypt_key_t **t = (crypt_key_t **) b;
2353   int r;
2354
2355   if ((r = m_strcasecmp((*s)->uid, (*t)->uid)))
2356     return r > 0;
2357   else
2358     return m_strcasecmp(crypt_keyid (*s), crypt_keyid (*t)) > 0;
2359 }
2360
2361 static int crypt_compare_address (const void *a, const void *b)
2362 {
2363   return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_address (a, b)
2364           : _crypt_compare_address (a, b));
2365 }
2366
2367
2368 /* Compare two key IDs and the addresses to be used for sorting. */
2369 static int _crypt_compare_keyid (const void *a, const void *b)
2370 {
2371   crypt_key_t **s = (crypt_key_t **) a;
2372   crypt_key_t **t = (crypt_key_t **) b;
2373   int r;
2374
2375   if ((r = m_strcasecmp(crypt_keyid (*s), crypt_keyid (*t))))
2376     return r > 0;
2377   else
2378     return m_strcasecmp((*s)->uid, (*t)->uid) > 0;
2379 }
2380
2381 static int crypt_compare_keyid (const void *a, const void *b)
2382 {
2383   return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_keyid (a, b)
2384           : _crypt_compare_keyid (a, b));
2385 }
2386
2387 /* Compare 2 creation dates and the addresses.  For sorting. */
2388 static int _crypt_compare_date (const void *a, const void *b)
2389 {
2390   crypt_key_t **s = (crypt_key_t **) a;
2391   crypt_key_t **t = (crypt_key_t **) b;
2392   unsigned long ts = 0, tt = 0;
2393
2394   if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2395     ts = (*s)->kobj->subkeys->timestamp;
2396   if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2397     tt = (*t)->kobj->subkeys->timestamp;
2398
2399   if (ts > tt)
2400     return 1;
2401   if (ts < tt)
2402     return 0;
2403
2404   return m_strcasecmp((*s)->uid, (*t)->uid) > 0;
2405 }
2406
2407 static int crypt_compare_date (const void *a, const void *b)
2408 {
2409   return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_date (a, b)
2410           : _crypt_compare_date (a, b));
2411 }
2412
2413 /* Compare two trust values, the key length, the creation dates. the
2414    addresses and the key IDs.  For sorting. */
2415 static int _crypt_compare_trust (const void *a, const void *b)
2416 {
2417   crypt_key_t **s = (crypt_key_t **) a;
2418   crypt_key_t **t = (crypt_key_t **) b;
2419   unsigned long ts = 0, tt = 0;
2420   int r;
2421
2422   if ((r = (((*s)->flags & (KEYFLAG_RESTRICTIONS))
2423             - ((*t)->flags & (KEYFLAG_RESTRICTIONS)))))
2424     return r > 0;
2425
2426   if ((*s)->kobj->uids)
2427     ts = (*s)->kobj->uids->validity;
2428   if ((*t)->kobj->uids)
2429     tt = (*t)->kobj->uids->validity;
2430   if ((r = (tt - ts)))
2431     return r < 0;
2432
2433   if ((*s)->kobj->subkeys)
2434     ts = (*s)->kobj->subkeys->length;
2435   if ((*t)->kobj->subkeys)
2436     tt = (*t)->kobj->subkeys->length;
2437   if (ts != tt)
2438     return ts > tt;
2439
2440   if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2441     ts = (*s)->kobj->subkeys->timestamp;
2442   if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2443     tt = (*t)->kobj->subkeys->timestamp;
2444   if (ts > tt)
2445     return 1;
2446   if (ts < tt)
2447     return 0;
2448
2449   if ((r = m_strcasecmp((*s)->uid, (*t)->uid)))
2450     return r > 0;
2451   return (m_strcasecmp(crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0;
2452 }
2453
2454 static int crypt_compare_trust (const void *a, const void *b)
2455 {
2456   return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_trust (a, b)
2457           : _crypt_compare_trust (a, b));
2458 }
2459
2460 /* Print the X.500 Distinguished Name part KEY from the array of parts
2461    DN to FP. */
2462 static int print_dn_part (FILE * fp, struct dn_array_s *dn, const char *key)
2463 {
2464   int any = 0;
2465
2466   for (; dn->key; dn++) {
2467     if (!m_strcmp(dn->key, key)) {
2468       if (any)
2469         fputs (" + ", fp);
2470       print_utf8 (fp, dn->value, m_strlen(dn->value));
2471       any = 1;
2472     }
2473   }
2474   return any;
2475 }
2476
2477 /* Print all parts of a DN in a standard sequence. */
2478 static void print_dn_parts (FILE * fp, struct dn_array_s *dn)
2479 {
2480   const char *stdpart[] = {
2481     "CN", "OU", "O", "STREET", "L", "ST", "C", NULL
2482   };
2483   int any = 0, any2 = 0, i;
2484
2485   for (i = 0; stdpart[i]; i++) {
2486     if (any)
2487       fputs (", ", fp);
2488     any = print_dn_part (fp, dn, stdpart[i]);
2489   }
2490   /* now print the rest without any specific ordering */
2491   for (; dn->key; dn++) {
2492     for (i = 0; stdpart[i]; i++) {
2493       if (!m_strcmp(dn->key, stdpart[i]))
2494         break;
2495     }
2496     if (!stdpart[i]) {
2497       if (any)
2498         fputs (", ", fp);
2499       if (!any2)
2500         fputs ("(", fp);
2501       any = print_dn_part (fp, dn, dn->key);
2502       any2 = 1;
2503     }
2504   }
2505   if (any2)
2506     fputs (")", fp);
2507 }
2508
2509
2510 /* Parse an RDN; this is a helper to parse_dn(). */
2511 static const unsigned char *parse_dn_part (struct dn_array_s *array,
2512                                            const unsigned char *string)
2513 {
2514   const unsigned char *s, *s1;
2515   ssize_t n;
2516   unsigned char *p;
2517
2518   /* parse attributeType */
2519   for (s = string + 1; *s && *s != '='; s++);
2520   if (!*s)
2521     return NULL;                /* error */
2522   n = s - string;
2523   if (!n)
2524     return NULL;                /* empty key */
2525   array->key = p_dupstr(string, n );
2526   p = (unsigned char *) array->key;
2527   string = s + 1;
2528
2529   if (*string == '#') {         /* hexstring */
2530     string++;
2531     for (s = string; hexval(*s) >= 0; s++)
2532       s++;
2533     n = s - string;
2534     if (!n || (n & 1))
2535       return NULL;              /* empty or odd number of digits */
2536     n /= 2;
2537     p = p_new(unsigned char, n + 1);
2538     array->value = (char *) p;
2539     for (s1 = string; n; s1 += 2, n--)
2540       *p++ = (hexval(*s1) << 8) | hexval(*s1);
2541     *p = 0;
2542   }
2543   else {                        /* regular v3 quoted string */
2544     for (n = 0, s = string; *s; s++) {
2545       if (*s == '\\') {         /* pair */
2546         s++;
2547         if (*s == ',' || *s == '=' || *s == '+'
2548             || *s == '<' || *s == '>' || *s == '#' || *s == ';'
2549             || *s == '\\' || *s == '\"' || *s == ' ')
2550           n++;
2551         else if (hexval(*s) >= 0 && hexval(*s + 1) >= 0) {
2552           s++;
2553           n++;
2554         }
2555         else
2556           return NULL;          /* invalid escape sequence */
2557       }
2558       else if (*s == '\"')
2559         return NULL;            /* invalid encoding */
2560       else if (*s == ',' || *s == '=' || *s == '+'
2561                || *s == '<' || *s == '>' || *s == '#' || *s == ';')
2562         break;
2563       else
2564         n++;
2565     }
2566
2567     p = p_new(unsigned char, n + 1);
2568     array->value = (char *) p;
2569     for (s = string; n; s++, n--) {
2570       if (*s == '\\') {
2571         s++;
2572         if (hexval(*s) >= 0) {
2573           *p++ = (hexval(*s) << 8) | hexval(*s + 1);
2574           s++;
2575         }
2576         else
2577           *p++ = *s;
2578       }
2579       else
2580         *p++ = *s;
2581     }
2582     *p = 0;
2583   }
2584   return s;
2585 }
2586
2587
2588 /* Parse a DN and return an array-ized one.  This is not a validating
2589    parser and it does not support any old-stylish syntax; gpgme is
2590    expected to return only rfc2253 compatible strings. */
2591 static struct dn_array_s *parse_dn (const unsigned char *string)
2592 {
2593   struct dn_array_s *array;
2594   ssize_t arrayidx, arraysize;
2595   int i;
2596
2597   arraysize = 7;                /* C,ST,L,O,OU,CN,email */
2598   array = p_new(struct dn_array_s, arraysize + 1);
2599   arrayidx = 0;
2600   while (*string) {
2601     while (*string == ' ')
2602       string++;
2603     if (!*string)
2604       break;                    /* ready */
2605     if (arrayidx >= arraysize) {        /* mutt lacks a real safe_realoc - so we need to copy */
2606       struct dn_array_s *a2;
2607
2608       arraysize += 5;
2609       a2 = p_new(struct dn_array_s, arraysize + 1);
2610       for (i = 0; i < arrayidx; i++) {
2611         a2[i].key = array[i].key;
2612         a2[i].value = array[i].value;
2613       }
2614       p_delete(&array);
2615       array = a2;
2616     }
2617     array[arrayidx].key = NULL;
2618     array[arrayidx].value = NULL;
2619     string = parse_dn_part (array + arrayidx, string);
2620     arrayidx++;
2621     if (!string)
2622       goto failure;
2623     while (*string == ' ')
2624       string++;
2625     if (*string && *string != ',' && *string != ';' && *string != '+')
2626       goto failure;             /* invalid delimiter */
2627     if (*string)
2628       string++;
2629   }
2630   array[arrayidx].key = NULL;
2631   array[arrayidx].value = NULL;
2632   return array;
2633
2634 failure:
2635   for (i = 0; i < arrayidx; i++) {
2636     p_delete(&array[i].key);
2637     p_delete(&array[i].value);
2638   }
2639   p_delete(&array);
2640   return NULL;
2641 }
2642
2643
2644 /* Print a nice representation of the USERID and make sure it is
2645    displayed in a proper way, which does mean to reorder some parts
2646    for S/MIME's DNs.  USERID is a string as returned by the gpgme key
2647    functions.  It is utf-8 encoded. */
2648 static void parse_and_print_user_id (FILE * fp, const char *userid)
2649 {
2650   const char *s;
2651   int i;
2652
2653   if (*userid == '<') {
2654     s = strchr (userid + 1, '>');
2655     if (s)
2656       print_utf8 (fp, userid + 1, s - userid - 1);
2657   }
2658   else if (*userid == '(')
2659     fputs (_("[Can't display this user ID (unknown encoding)]"), fp);
2660   else if (!digit_or_letter ((const unsigned char *) userid))
2661     fputs (_("[Can't display this user ID (invalid encoding)]"), fp);
2662   else {
2663     struct dn_array_s *dn = parse_dn ((const unsigned char *) userid);
2664
2665     if (!dn)
2666       fputs (_("[Can't display this user ID (invalid DN)]"), fp);
2667     else {
2668       print_dn_parts (fp, dn);
2669       for (i = 0; dn[i].key; i++) {
2670         p_delete(&dn[i].key);
2671         p_delete(&dn[i].value);
2672       }
2673       p_delete(&dn);
2674     }
2675   }
2676 }
2677
2678 typedef enum {
2679   KEY_CAP_CAN_ENCRYPT,
2680   KEY_CAP_CAN_SIGN,
2681   KEY_CAP_CAN_CERTIFY
2682 } key_cap_t;
2683
2684 static unsigned int key_check_cap (gpgme_key_t key, key_cap_t cap)
2685 {
2686   gpgme_subkey_t subkey = NULL;
2687   unsigned int ret = 0;
2688
2689   switch (cap) {
2690   case KEY_CAP_CAN_ENCRYPT:
2691     if (!(ret = key->can_encrypt))
2692       for (subkey = key->subkeys; subkey; subkey = subkey->next)
2693         if ((ret = subkey->can_encrypt))
2694           break;
2695     break;
2696   case KEY_CAP_CAN_SIGN:
2697     if (!(ret = key->can_sign))
2698       for (subkey = key->subkeys; subkey; subkey = subkey->next)
2699         if ((ret = subkey->can_sign))
2700           break;
2701     break;
2702   case KEY_CAP_CAN_CERTIFY:
2703     if (!(ret = key->can_certify))
2704       for (subkey = key->subkeys; subkey; subkey = subkey->next)
2705         if ((ret = subkey->can_certify))
2706           break;
2707     break;
2708   }
2709
2710   return ret;
2711 }
2712
2713
2714 /* Print verbose information about a key or certificate to FP. */
2715 static void print_key_info (gpgme_key_t key, FILE * fp)
2716 {
2717   int idx;
2718   const char *s = NULL, *s2 = NULL;
2719   time_t tt = 0;
2720   struct tm *tm;
2721   char shortbuf[STRING];
2722   unsigned long aval = 0;
2723   const char *delim;
2724   int is_pgp = 0;
2725   int i;
2726   gpgme_user_id_t uid = NULL;
2727
2728   if (Locale)
2729     setlocale (LC_TIME, Locale);
2730
2731   is_pgp = key->protocol == GPGME_PROTOCOL_OpenPGP;
2732
2733   for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
2734     if (uid->revoked)
2735       continue;
2736
2737     s = uid->uid;
2738     fputs (idx ? _(" aka ......: ") :_("Name ......: "), fp);
2739
2740     if (uid->invalid) {
2741       fputs (_("[Invalid]"), fp);
2742       putc (' ', fp);
2743     }
2744     if (is_pgp)
2745       print_utf8 (fp, s, m_strlen(s));
2746     else
2747       parse_and_print_user_id (fp, s);
2748     putc ('\n', fp);
2749   }
2750
2751   if (key->subkeys && (key->subkeys->timestamp > 0)) {
2752     tt = key->subkeys->timestamp;
2753
2754     tm = localtime (&tt);
2755 #ifdef HAVE_LANGINFO_D_T_FMT
2756     strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2757 #else
2758     strftime (shortbuf, sizeof shortbuf, "%c", tm);
2759 #endif
2760     fprintf (fp, _("Valid From : %s\n"), shortbuf);
2761   }
2762
2763   if (key->subkeys && (key->subkeys->expires > 0)) {
2764     tt = key->subkeys->expires;
2765
2766     tm = localtime (&tt);
2767 #ifdef HAVE_LANGINFO_D_T_FMT
2768     strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2769 #else
2770     strftime (shortbuf, sizeof shortbuf, "%c", tm);
2771 #endif
2772     fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
2773   }
2774
2775   if (key->subkeys)
2776     s = gpgme_pubkey_algo_name (key->subkeys->pubkey_algo);
2777   else
2778     s = "?";
2779
2780   s2 = is_pgp ? "PGP" : "X.509";
2781
2782   if (key->subkeys)
2783     aval = key->subkeys->length;
2784
2785   fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), s2, aval, s);
2786
2787   fprintf (fp, _("Key Usage .: "));
2788   delim = "";
2789
2790   if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) {
2791     fprintf (fp, "%s%s", delim, _("encryption"));
2792     delim = _(", ");
2793   }
2794   if (key_check_cap (key, KEY_CAP_CAN_SIGN)) {
2795     fprintf (fp, "%s%s", delim, _("signing"));
2796     delim = _(", ");
2797   }
2798   if (key_check_cap (key, KEY_CAP_CAN_CERTIFY)) {
2799     fprintf (fp, "%s%s", delim, _("certification"));
2800     delim = _(", ");
2801   }
2802   putc ('\n', fp);
2803
2804   if (key->subkeys) {
2805     s = key->subkeys->fpr;
2806     fputs (_("Fingerprint: "), fp);
2807     if (is_pgp && m_strlen(s) == 40) {
2808       for (i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) {
2809         putc (*s, fp);
2810         putc (s[1], fp);
2811         putc (s[2], fp);
2812         putc (s[3], fp);
2813         putc (is_pgp ? ' ' : ':', fp);
2814         if (is_pgp && i == 4)
2815           putc (' ', fp);
2816       }
2817     }
2818     else {
2819       for (i = 0; *s && s[1] && s[2]; s += 2, i++) {
2820         putc (*s, fp);
2821         putc (s[1], fp);
2822         putc (is_pgp ? ' ' : ':', fp);
2823         if (is_pgp && i == 7)
2824           putc (' ', fp);
2825       }
2826     }
2827     fprintf (fp, "%s\n", s);
2828   }
2829
2830   if (key->issuer_serial) {
2831     s = key->issuer_serial;
2832     if (s)
2833       fprintf (fp, _("Serial-No .: 0x%s\n"), s);
2834   }
2835
2836   if (key->issuer_name) {
2837     s = key->issuer_name;
2838     if (s) {
2839       fprintf (fp, _("Issued By .: "));
2840       parse_and_print_user_id (fp, s);
2841       putc ('\n', fp);
2842     }
2843   }
2844
2845   /* For PGP we list all subkeys. */
2846   if (is_pgp) {
2847     gpgme_subkey_t subkey = NULL;
2848
2849     for (idx = 1, subkey = key->subkeys; subkey; idx++, subkey = subkey->next) {
2850       s = subkey->keyid;
2851
2852       putc ('\n', fp);
2853       if (m_strlen(s) == 16)
2854         s += 8;                 /* display only the short keyID */
2855       fprintf (fp, _("Subkey ....: 0x%s"), s);
2856       if (subkey->revoked) {
2857         putc (' ', fp);
2858         fputs (_("[Revoked]"), fp);
2859       }
2860       if (subkey->invalid) {
2861         putc (' ', fp);
2862         fputs (_("[Invalid]"), fp);
2863       }
2864       if (subkey->expired) {
2865         putc (' ', fp);
2866         fputs (_("[Expired]"), fp);
2867       }
2868       if (subkey->disabled) {
2869         putc (' ', fp);
2870         fputs (_("[Disabled]"), fp);
2871       }
2872       putc ('\n', fp);
2873
2874       if (subkey->timestamp > 0) {
2875         tt = subkey->timestamp;
2876
2877         tm = localtime (&tt);
2878 #ifdef HAVE_LANGINFO_D_T_FMT
2879         strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2880 #else
2881         strftime (shortbuf, sizeof shortbuf, "%c", tm);
2882 #endif
2883         fprintf (fp, _("Valid From : %s\n"), shortbuf);
2884       }
2885
2886       if (subkey->expires > 0) {
2887         tt = subkey->expires;
2888
2889         tm = localtime (&tt);
2890 #ifdef HAVE_LANGINFO_D_T_FMT
2891         strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2892 #else
2893         strftime (shortbuf, sizeof shortbuf, "%c", tm);
2894 #endif
2895         fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
2896       }
2897
2898       if (subkey)
2899         s = gpgme_pubkey_algo_name (subkey->pubkey_algo);
2900       else
2901         s = "?";
2902
2903       if (subkey)
2904         aval = subkey->length;
2905       else
2906         aval = 0;
2907
2908       fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), "PGP", aval, s);
2909
2910       fprintf (fp, _("Key Usage .: "));
2911       delim = "";
2912
2913       if (subkey->can_encrypt) {
2914         fprintf (fp, "%s%s", delim, _("encryption"));
2915         delim = _(", ");
2916       }
2917       if (subkey->can_sign) {
2918         fprintf (fp, "%s%s", delim, _("signing"));
2919         delim = _(", ");
2920       }
2921       if (subkey->can_certify) {
2922         fprintf (fp, "%s%s", delim, _("certification"));
2923         delim = _(", ");
2924       }
2925       putc ('\n', fp);
2926     }
2927   }
2928
2929   if (Locale)
2930     setlocale (LC_TIME, "C");
2931 }
2932
2933
2934 /* Show detailed information about the selected key */
2935 static void verify_key (crypt_key_t * key)
2936 {
2937   FILE *fp;
2938   char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX];
2939   const char *s;
2940   gpgme_ctx_t listctx = NULL;
2941   gpgme_error_t err;
2942   gpgme_key_t k = NULL;
2943   int maxdepth = 100;
2944
2945   fp = m_tempfile (tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
2946   if (!fp) {
2947     mutt_perror (_("Can't create temporary file"));
2948     return;
2949   }
2950   mutt_message _("Collecting data...");
2951
2952   print_key_info (key->kobj, fp);
2953
2954   err = gpgme_new (&listctx);
2955   if (err) {
2956     fprintf (fp, "Internal error: can't create gpgme context: %s\n",
2957              gpgme_strerror (err));
2958     goto leave;
2959   }
2960   if ((key->flags & KEYFLAG_ISX509))
2961     gpgme_set_protocol (listctx, GPGME_PROTOCOL_CMS);
2962
2963   k = key->kobj;
2964   gpgme_key_ref (k);
2965   while ((s = k->chain_id) && k->subkeys && m_strcmp(s, k->subkeys->fpr)) {
2966     putc ('\n', fp);
2967     err = gpgme_op_keylist_start (listctx, s, 0);
2968     gpgme_key_release (k);
2969     k = NULL;
2970     if (!err)
2971       err = gpgme_op_keylist_next (listctx, &k);
2972     if (err) {
2973       fprintf (fp, _("Error finding issuer key: %s\n"), gpgme_strerror (err));
2974       goto leave;
2975     }
2976     gpgme_op_keylist_end (listctx);
2977
2978     print_key_info (k, fp);
2979     if (!--maxdepth) {
2980       putc ('\n', fp);
2981       fputs (_("Error: certification chain to long - stopping here\n"), fp);
2982       break;
2983     }
2984   }
2985
2986 leave:
2987   gpgme_key_release (k);
2988   gpgme_release (listctx);
2989   m_fclose(&fp);
2990   mutt_clear_error ();
2991   snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"), crypt_keyid (key));
2992   mutt_do_pager (cmd, tempfile, 0, NULL);
2993 }
2994
2995 /* Implementation of `findkeys'. */
2996
2997 /* Convert string_list_t into a pattern string suitable to be passed to GPGME.
2998    We need to convert spaces in an item into a '+' and '%' into
2999    "%25". */
3000 static char *list_to_pattern (string_list_t * list)
3001 {
3002   string_list_t *l;
3003   char *pattern, *p;
3004   const char *s;
3005   ssize_t n;
3006
3007   n = 0;
3008   for (l = list; l; l = l->next) {
3009     for (s = l->data; *s; s++) {
3010       if (*s == '%')
3011         n += 2;
3012       n++;
3013     }
3014     n++;                        /* delimiter or end of string */
3015   }
3016   n++;                          /* make sure to allocate at least one byte */
3017   pattern = p = p_new(char, n);
3018   for (l = list; l; l = l->next) {
3019     s = l->data;
3020     if (*s) {
3021       if (l != list)
3022         *p++ = ' ';
3023       for (s = l->data; *s; s++) {
3024         if (*s == '%') {
3025           *p++ = '%';
3026           *p++ = '2';
3027           *p++ = '5';
3028         }
3029         else if (*s == '+') {
3030           *p++ = '%';
3031           *p++ = '2';
3032           *p++ = 'B';
3033         }
3034         else if (*s == ' ')
3035           *p++ = '+';
3036         else
3037           *p++ = *s;
3038       }
3039     }
3040   }
3041   *p = 0;
3042   return pattern;
3043 }
3044
3045 /* Return a list of keys which are candidates for the selection.
3046    Select by looking at the HINTS list. */
3047 static crypt_key_t *get_candidates (string_list_t * hints, unsigned int app,
3048                                     int secret)
3049 {
3050   crypt_key_t *db, *k, **kend;
3051   char *pattern;
3052   gpgme_error_t err;
3053   gpgme_ctx_t ctx;
3054   gpgme_key_t key;
3055   int idx;
3056   gpgme_user_id_t uid = NULL;
3057
3058   pattern = list_to_pattern (hints);
3059   if (!pattern)
3060     return NULL;
3061
3062   err = gpgme_new (&ctx);
3063   if (err) {
3064     mutt_error (_("gpgme_new failed: %s"), gpgme_strerror (err));
3065     p_delete(&pattern);
3066     return NULL;
3067   }
3068
3069   db = NULL;
3070   kend = &db;
3071
3072   if ((app & APPLICATION_PGP)) {
3073     /* Its all a mess.  That old GPGME expects different things
3074        depending on the protocol.  For gpg we don' t need percent
3075        escaped pappert but simple strings passed in an array to the
3076        keylist_ext_start function. */
3077     string_list_t *l;
3078     ssize_t n;
3079     char **patarr;
3080
3081     for (l = hints, n = 0; l; l = l->next) {
3082       if (l->data && *l->data)
3083         n++;
3084     }
3085     if (!n)
3086       goto no_pgphints;
3087
3088     patarr = p_new(char *, n + 1);
3089     for (l = hints, n = 0; l; l = l->next) {
3090       if (l->data && *l->data)
3091         patarr[n++] = m_strdup(l->data);
3092     }
3093     patarr[n] = NULL;
3094     err = gpgme_op_keylist_ext_start (ctx, (const char **) patarr, secret, 0);
3095     for (n = 0; patarr[n]; n++)
3096       p_delete(&patarr[n]);
3097     p_delete(&patarr);
3098     if (err) {
3099       mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err));
3100       gpgme_release (ctx);
3101       p_delete(&pattern);
3102       return NULL;
3103     }
3104
3105     while (!(err = gpgme_op_keylist_next (ctx, &key))) {
3106       unsigned int flags = 0;
3107
3108       if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3109         flags |= KEYFLAG_CANENCRYPT;
3110       if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3111         flags |= KEYFLAG_CANSIGN;
3112
3113 #if 0                           /* DISABLED code */
3114       if (!flags) {
3115         /* Bug in gpg.  Capabilities are not listed for secret
3116            keys.  Try to deduce them from the algorithm. */
3117
3118         switch (key->subkeys[0].pubkey_algo) {
3119         case GPGME_PK_RSA:
3120           flags |= KEYFLAG_CANENCRYPT;
3121           flags |= KEYFLAG_CANSIGN;
3122           break;
3123         case GPGME_PK_ELG_E:
3124           flags |= KEYFLAG_CANENCRYPT;
3125           break;
3126         case GPGME_PK_DSA:
3127           flags |= KEYFLAG_CANSIGN;
3128           break;
3129         }
3130       }
3131 #endif /* DISABLED code */
3132
3133       for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
3134         k = p_new(crypt_key_t, 1);
3135         k->kobj = key;
3136         k->idx = idx;
3137         k->uid = uid->uid;
3138         k->flags = flags;
3139         *kend = k;
3140         kend = &k->next;
3141       }
3142     }
3143     if (gpg_err_code (err) != GPG_ERR_EOF)
3144       mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3145     gpgme_op_keylist_end (ctx);
3146   no_pgphints:
3147     ;
3148   }
3149
3150   if ((app & APPLICATION_SMIME)) {
3151     /* and now look for x509 certificates */
3152     gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
3153     err = gpgme_op_keylist_start (ctx, pattern, 0);
3154     if (err) {
3155       mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err));
3156       gpgme_release (ctx);
3157       p_delete(&pattern);
3158       return NULL;
3159     }
3160
3161     while (!(err = gpgme_op_keylist_next (ctx, &key))) {
3162       unsigned int flags = KEYFLAG_ISX509;
3163
3164       if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3165         flags |= KEYFLAG_CANENCRYPT;
3166       if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3167         flags |= KEYFLAG_CANSIGN;
3168
3169       for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
3170         k = p_new(crypt_key_t, 1);
3171         k->kobj = key;
3172         k->idx = idx;
3173         k->uid = uid->uid;
3174         k->flags = flags;
3175         *kend = k;
3176         kend = &k->next;
3177       }
3178     }
3179     if (gpg_err_code (err) != GPG_ERR_EOF)
3180       mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3181     gpgme_op_keylist_end (ctx);
3182   }
3183
3184   gpgme_release (ctx);
3185   p_delete(&pattern);
3186   return db;
3187 }
3188
3189 /* Add the string STR to the list HINTS.  This list is later used to
3190    match addresses. */
3191 static string_list_t *crypt_add_string_to_hints (string_list_t * hints, const char *str)
3192 {
3193   char *scratch;
3194   char *t;
3195
3196   if ((scratch = m_strdup(str)) == NULL)
3197     return hints;
3198
3199   for (t = strtok (scratch, " ,.:\"()<>\n"); t;
3200        t = strtok (NULL, " ,.:\"()<>\n")) {
3201     if (m_strlen(t) > 3)
3202       hints = mutt_add_list(hints, t);
3203   }
3204
3205   p_delete(&scratch);
3206   return hints;
3207 }
3208
3209 /* Display a menu to select a key from the array KEYS. FORCED_VALID
3210    will be set to true on return if the user did override the the
3211    key's validity. */
3212 static crypt_key_t *crypt_select_key (crypt_key_t * keys,
3213                                       address_t * p, const char *s,
3214                                       unsigned int app, int *forced_valid)
3215 {
3216   int keymax;
3217   crypt_key_t **key_table;
3218   MUTTMENU *menu;
3219   int i, done = 0;
3220   char helpstr[STRING], buf[LONG_STRING];
3221   crypt_key_t *k;
3222   int (*f) (const void *, const void *);
3223   int menu_to_use = 0;
3224   int unusable = 0;
3225
3226   *forced_valid = 0;
3227
3228   /* build the key table */
3229   keymax = i = 0;
3230   key_table = NULL;
3231   for (k = keys; k; k = k->next) {
3232     if (!option (OPTPGPSHOWUNUSABLE) && (k->flags & KEYFLAG_CANTUSE)) {
3233       unusable = 1;
3234       continue;
3235     }
3236
3237     if (i == keymax) {
3238       keymax += 20;
3239       p_realloc(&key_table, keymax);
3240     }
3241
3242     key_table[i++] = k;
3243   }
3244
3245   if (!i && unusable) {
3246     mutt_error _("All matching keys are marked expired/revoked.");
3247
3248     mutt_sleep (1);
3249     return NULL;
3250   }
3251
3252   switch (PgpSortKeys & SORT_MASK) {
3253   case SORT_DATE:
3254     f = crypt_compare_date;
3255     break;
3256   case SORT_KEYID:
3257     f = crypt_compare_keyid;
3258     break;
3259   case SORT_ADDRESS:
3260     f = crypt_compare_address;
3261     break;
3262   case SORT_TRUST:
3263   default:
3264     f = crypt_compare_trust;
3265     break;
3266   }
3267   qsort (key_table, i, sizeof (crypt_key_t *), f);
3268
3269   if (app & APPLICATION_PGP)
3270     menu_to_use = MENU_KEY_SELECT_PGP;
3271   else if (app & APPLICATION_SMIME)
3272     menu_to_use = MENU_KEY_SELECT_SMIME;
3273
3274   helpstr[0] = 0;
3275   mutt_make_help (buf, sizeof (buf), _("Exit  "), menu_to_use, OP_EXIT);
3276   m_strcat(helpstr, sizeof(helpstr), buf);
3277   mutt_make_help (buf, sizeof (buf), _("Select  "), menu_to_use,
3278                   OP_GENERIC_SELECT_ENTRY);
3279   m_strcat(helpstr, sizeof(helpstr), buf);
3280   mutt_make_help (buf, sizeof (buf), _("Check key  "),
3281                   menu_to_use, OP_VERIFY_KEY);
3282   m_strcat(helpstr, sizeof(helpstr), buf);
3283   mutt_make_help (buf, sizeof (buf), _("Help"), menu_to_use, OP_HELP);
3284   m_strcat(helpstr, sizeof(helpstr), buf);
3285
3286   menu = mutt_new_menu ();
3287   menu->max = i;
3288   menu->make_entry = crypt_entry;
3289   menu->menu = menu_to_use;
3290   menu->help = helpstr;
3291   menu->data = key_table;
3292
3293   {
3294     const char *ts;
3295
3296     if ((app & APPLICATION_PGP) && (app & APPLICATION_SMIME))
3297       ts = _("PGP and S/MIME keys matching");
3298     else if ((app & APPLICATION_PGP))
3299       ts = _("PGP keys matching");
3300     else if ((app & APPLICATION_SMIME))
3301       ts = _("S/MIME keys matching");
3302     else
3303       ts = _("keys matching");
3304
3305     if (p)
3306       snprintf (buf, sizeof (buf), _("%s <%s>."), ts, p->mailbox);
3307     else
3308       snprintf (buf, sizeof (buf), _("%s \"%s\"."), ts, s);
3309     menu->title = buf;
3310   }
3311
3312   mutt_clear_error ();
3313   k = NULL;
3314   while (!done) {
3315     *forced_valid = 0;
3316     switch (mutt_menuLoop (menu)) {
3317     case OP_VERIFY_KEY:
3318       verify_key (key_table[menu->current]);
3319       menu->redraw = REDRAW_FULL;
3320       break;
3321
3322     case OP_VIEW_ID:
3323       mutt_message ("%s", key_table[menu->current]->uid);
3324       break;
3325
3326     case OP_GENERIC_SELECT_ENTRY:
3327       /* FIXME make error reporting more verbose - this should be
3328          easy because gpgme provides more information */
3329       if (option (OPTPGPCHECKTRUST)) {
3330         if (!crypt_key_is_valid (key_table[menu->current])) {
3331           mutt_error _("This key can't be used: "
3332                        "expired/disabled/revoked.");
3333           break;
3334         }
3335       }
3336
3337       if (option (OPTPGPCHECKTRUST) &&
3338           (!crypt_id_is_valid (key_table[menu->current])
3339            || !crypt_id_is_strong (key_table[menu->current]))) {
3340         const char *warn_s;
3341         char buff[LONG_STRING];
3342
3343         if (key_table[menu->current]->flags & KEYFLAG_CANTUSE)
3344           s = N_("ID is expired/disabled/revoked.");
3345         else {
3346           gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
3347           gpgme_user_id_t uid = NULL;
3348           int j = 0;
3349
3350           warn_s = "??";
3351
3352           uid = key_table[menu->current]->kobj->uids;
3353           for (j = 0; (j < key_table[menu->current]->idx) && uid;
3354                j++, uid = uid->next);
3355           if (uid)
3356             val = uid->validity;
3357
3358           switch (val) {
3359           case GPGME_VALIDITY_UNKNOWN:
3360           case GPGME_VALIDITY_UNDEFINED:
3361             warn_s = N_("ID has undefined validity.");
3362             break;
3363           case GPGME_VALIDITY_NEVER:
3364             warn_s = N_("ID is not valid.");
3365             break;
3366           case GPGME_VALIDITY_MARGINAL:
3367             warn_s = N_("ID is only marginally valid.");
3368             break;
3369           case GPGME_VALIDITY_FULL:
3370           case GPGME_VALIDITY_ULTIMATE:
3371             break;
3372           }
3373
3374           snprintf (buff, sizeof (buff),
3375                     _("%s Do you really want to use the key?"), _(warn_s));
3376
3377           if (mutt_yesorno (buff, 0) != 1) {
3378             mutt_clear_error ();
3379             break;
3380           }
3381           *forced_valid = 1;
3382         }
3383       }
3384
3385       k = crypt_copy_key (key_table[menu->current]);
3386       done = 1;
3387       break;
3388
3389     case OP_EXIT:
3390       k = NULL;
3391       done = 1;
3392       break;
3393     }
3394   }
3395
3396   mutt_menuDestroy (&menu);
3397   p_delete(&key_table);
3398
3399   set_option (OPTNEEDREDRAW);
3400
3401   return k;
3402 }
3403
3404 static crypt_key_t *crypt_getkeybyaddr (address_t * a, short abilities,
3405                                         unsigned int app, int *forced_valid)
3406 {
3407   address_t *r, *p;
3408   string_list_t *hints = NULL;
3409
3410   int weak = 0;
3411   int invalid = 0;
3412   int multi = 0;
3413   int this_key_has_strong;
3414   int this_key_has_weak;
3415   int this_key_has_invalid;
3416   int match;
3417
3418   crypt_key_t *keys, *k;
3419   crypt_key_t *the_valid_key = NULL;
3420   crypt_key_t *matches = NULL;
3421   crypt_key_t **matches_endp = &matches;
3422
3423   *forced_valid = 0;
3424
3425   if (a && a->mailbox)
3426     hints = crypt_add_string_to_hints (hints, a->mailbox);
3427   if (a && a->personal)
3428     hints = crypt_add_string_to_hints (hints, a->personal);
3429
3430   mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
3431   keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
3432
3433   string_list_wipe(&hints);
3434
3435   if (!keys)
3436     return NULL;
3437
3438   for (k = keys; k; k = k->next) {
3439     if (abilities && !(k->flags & abilities)) {
3440       continue;
3441     }
3442
3443     this_key_has_weak = 0;      /* weak but valid match   */
3444     this_key_has_invalid = 0;   /* invalid match          */
3445     this_key_has_strong = 0;    /* strong and valid match */
3446     match = 0;                  /* any match            */
3447
3448     r = rfc822_parse_adrlist (NULL, k->uid);
3449     for (p = r; p; p = p->next) {
3450       int validity = crypt_id_matches_addr (a, p, k);
3451
3452       if (validity & CRYPT_KV_MATCH)    /* something matches */
3453         match = 1;
3454
3455       /* is this key a strong candidate? */
3456       if ((validity & CRYPT_KV_VALID)
3457           && (validity & CRYPT_KV_STRONGID)
3458           && (validity & CRYPT_KV_ADDR)) {
3459         if (the_valid_key && the_valid_key != k)
3460           multi = 1;
3461         the_valid_key = k;
3462         this_key_has_strong = 1;
3463       }
3464       else if ((validity & CRYPT_KV_MATCH)
3465                && !(validity & CRYPT_KV_VALID))
3466         this_key_has_invalid = 1;
3467       else if ((validity & CRYPT_KV_MATCH)
3468                && (!(validity & CRYPT_KV_STRONGID)
3469                    || !(validity & CRYPT_KV_ADDR)))
3470         this_key_has_weak = 1;
3471     }
3472     address_list_wipe(&r);
3473
3474     if (match) {
3475       crypt_key_t *tmp;
3476
3477       if (!this_key_has_strong && this_key_has_invalid)
3478         invalid = 1;
3479       if (!this_key_has_strong && this_key_has_weak)
3480         weak = 1;
3481
3482       *matches_endp = tmp = crypt_copy_key (k);
3483       matches_endp = &tmp->next;
3484       the_valid_key = tmp;
3485     }
3486   }
3487
3488   crypt_free_key (&keys);
3489
3490   if (matches) {
3491     if (the_valid_key && !multi && !weak
3492         && !(invalid && option (OPTPGPSHOWUNUSABLE))) {
3493       /*
3494        * There was precisely one strong match on a valid ID, there
3495        * were no valid keys with weak matches, and we aren't
3496        * interested in seeing invalid keys.
3497        *
3498        * Proceed without asking the user.
3499        */
3500       k = crypt_copy_key (the_valid_key);
3501     }
3502     else {
3503       /*
3504        * Else: Ask the user.
3505        */
3506       k = crypt_select_key (matches, a, NULL, app, forced_valid);
3507     }
3508     crypt_free_key (&matches);
3509   }
3510   else
3511     k = NULL;
3512
3513   return k;
3514 }
3515
3516
3517 static crypt_key_t *crypt_getkeybystr (const char *p, short abilities,
3518                                        unsigned int app, int *forced_valid)
3519 {
3520   string_list_t *hints = NULL;
3521   crypt_key_t *keys;
3522   crypt_key_t *matches = NULL;
3523   crypt_key_t **matches_endp = &matches;
3524   crypt_key_t *k;
3525   int match;
3526
3527   mutt_message (_("Looking for keys matching \"%s\"..."), p);
3528
3529   *forced_valid = 0;
3530
3531   hints = crypt_add_string_to_hints (hints, p);
3532   keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
3533   string_list_wipe(&hints);
3534
3535   if (!keys)
3536     return NULL;
3537
3538   for (k = keys; k; k = k->next) {
3539     if (abilities && !(k->flags & abilities))
3540       continue;
3541
3542     match = 0;
3543
3544     if (!*p || !m_strcasecmp(p, crypt_keyid (k))
3545         || (!m_strncasecmp(p, "0x", 2)
3546             && !m_strcasecmp(p + 2, crypt_keyid (k)))
3547         || (option (OPTPGPLONGIDS)
3548             && !m_strncasecmp(p, "0x", 2)
3549             && !m_strcasecmp(p + 2, crypt_keyid (k) + 8))
3550         || m_stristr(k->uid, p)) {
3551       crypt_key_t *tmp;
3552
3553       *matches_endp = tmp = crypt_copy_key (k);
3554       matches_endp = &tmp->next;
3555     }
3556   }
3557
3558   crypt_free_key (&keys);
3559
3560   if (matches) {
3561     k = crypt_select_key (matches, NULL, p, app, forced_valid);
3562     crypt_free_key (&matches);
3563     return k;
3564   }
3565
3566   return NULL;
3567 }
3568
3569 /* Display TAG as a prompt to ask for a key.  If WHATFOR is not null
3570    use it as default and store it under that label as the next
3571    default.  ABILITIES describe the required key abilities (sign,
3572    encrypt) and APP the type of the requested key; ether S/MIME or
3573    PGP.  Return a copy of the key or NULL if not found. */
3574 static crypt_key_t *crypt_ask_for_key (char *tag,
3575                                        char *whatfor,
3576                                        short abilities,
3577                                        unsigned int app, int *forced_valid)
3578 {
3579   crypt_key_t *key;
3580   char resp[STRING];
3581   struct crypt_cache *l = NULL;
3582   int dummy;
3583
3584   if (!forced_valid)
3585     forced_valid = &dummy;
3586
3587   mutt_clear_error ();
3588
3589   *forced_valid = 0;
3590   resp[0] = 0;
3591   if (whatfor) {
3592
3593     for (l = id_defaults; l; l = l->next)
3594       if (!m_strcasecmp(whatfor, l->what)) {
3595         m_strcpy(resp, sizeof(resp), NONULL(l->dflt));
3596         break;
3597       }
3598   }
3599
3600
3601   for (;;) {
3602     resp[0] = 0;
3603     if (mutt_get_field (tag, resp, sizeof (resp), M_CLEAR) != 0)
3604       return NULL;
3605
3606     if (whatfor) {
3607       if (l)
3608         m_strreplace(&l->dflt, resp);
3609       else {
3610         l = p_new(struct crypt_cache, 1);
3611         l->next = id_defaults;
3612         id_defaults = l;
3613         l->what = m_strdup(whatfor);
3614         l->dflt = m_strdup(resp);
3615       }
3616     }
3617
3618     if ((key = crypt_getkeybystr (resp, abilities, app, forced_valid)))
3619       return key;
3620
3621     BEEP ();
3622   }
3623   /* not reached */
3624 }
3625
3626 /* This routine attempts to find the keyids of the recipients of a
3627    message.  It returns NULL if any of the keys can not be found.  */
3628 static char *find_keys (address_t * to, address_t * cc, address_t * bcc,
3629                         unsigned int app)
3630 {
3631   char *keylist = NULL, *t;
3632   const char *keyID;
3633   ssize_t keylist_size = 0;
3634   ssize_t keylist_used = 0;
3635   address_t *tmp = NULL, *addr = NULL;
3636   address_t **last = &tmp;
3637   address_t *p, *q;
3638   int i;
3639   crypt_key_t *k_info, *key;
3640   const char *fqdn = mutt_fqdn (1);
3641
3642 #if 0
3643   *r_application = APPLICATION_PGP | APPLICATION_SMIME;
3644 #endif
3645
3646   for (i = 0; i < 3; i++) {
3647     switch (i) {
3648     case 0:
3649       p = to;
3650       break;
3651     case 1:
3652       p = cc;
3653       break;
3654     case 2:
3655       p = bcc;
3656       break;
3657     default:
3658       abort ();
3659     }
3660
3661     *last = address_list_dup (p);
3662     while (*last)
3663       last = &((*last)->next);
3664   }
3665
3666   rfc822_qualify(tmp, fqdn);
3667   address_list_uniq(tmp);
3668
3669   for (p = tmp; p; p = p->next) {
3670     char buf[LONG_STRING];
3671     int forced_valid = 0;
3672
3673     q = p;
3674     k_info = NULL;
3675
3676     if ((keyID = mutt_crypt_hook (p)) != NULL) {
3677       int r;
3678
3679       snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"),
3680                 keyID, p->mailbox);
3681       if ((r = mutt_yesorno (buf, M_YES)) == M_YES) {
3682         /* check for e-mail address */
3683         if ((t = strchr (keyID, '@')) &&
3684             (addr = rfc822_parse_adrlist (NULL, keyID))) {
3685           rfc822_qualify(addr, fqdn);
3686           q = addr;
3687         }
3688         else {
3689           k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
3690                                       app, &forced_valid);
3691         }
3692       }
3693       else if (r == -1) {
3694         p_delete(&keylist);
3695         address_list_wipe(&tmp);
3696         address_list_wipe(&addr);
3697         return NULL;
3698       }
3699     }
3700
3701     if (k_info == NULL
3702         && (k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT,
3703                                          app, &forced_valid)) == NULL) {
3704       snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
3705
3706       if ((key = crypt_ask_for_key (buf, q->mailbox, KEYFLAG_CANENCRYPT,
3707                                     app,
3708                                     &forced_valid)) == NULL) {
3709         p_delete(&keylist);
3710         address_list_wipe(&tmp);
3711         address_list_wipe(&addr);
3712         return NULL;
3713       }
3714     }
3715     else
3716       key = k_info;
3717
3718     {
3719       const char *s = crypt_fpr (key);
3720
3721       keylist_size += m_strlen(s) + 4 + 1;
3722       p_realloc(&keylist, keylist_size);
3723       sprintf (keylist + keylist_used, "%s0x%s%s",
3724                keylist_used ? " " : "", s, forced_valid ? "!" : "");
3725     }
3726     keylist_used = m_strlen(keylist);
3727
3728     crypt_free_key (&key);
3729     address_list_wipe(&addr);
3730   }
3731   address_list_wipe(&tmp);
3732   return (keylist);
3733 }
3734
3735 char *crypt_pgp_findkeys (address_t * to, address_t * cc, address_t * bcc)
3736 {
3737   return find_keys (to, cc, bcc, APPLICATION_PGP);
3738 }
3739
3740 char *crypt_smime_findkeys (address_t * to, address_t * cc, address_t * bcc)
3741 {
3742   return find_keys (to, cc, bcc, APPLICATION_SMIME);
3743 }
3744
3745 static int gpgme_send_menu (HEADER * msg, int *redraw, int is_smime)
3746 {
3747   crypt_key_t *p;
3748   char input_signas[STRING];
3749   int choice;
3750
3751   if (msg->security & APPLICATION_PGP)
3752     is_smime = 0;
3753   else if (msg->security & APPLICATION_SMIME)
3754     is_smime = 1;
3755
3756   if (is_smime)
3757     choice =
3758       mutt_multi_choice (_
3759                          ("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?"),
3760                          _("esabpfc"));
3761   else
3762     choice =
3763       mutt_multi_choice (_
3764                          ("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?"),
3765                          _("esabmfc"));
3766
3767   switch (choice) {
3768   case 1:                      /* (e)ncrypt */
3769     msg->security |= (is_smime ? SMIMEENCRYPT : PGPENCRYPT);
3770     msg->security &= ~(is_smime ? SMIMESIGN : PGPSIGN);
3771     break;
3772
3773   case 2:                      /* (s)ign */
3774     msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
3775     msg->security &= ~(is_smime ? SMIMEENCRYPT : PGPENCRYPT);
3776     break;
3777
3778   case 3:                      /* sign (a)s */
3779 /*      unset_option(OPTCRYPTCHECKTRUST); */
3780     if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
3781                                 is_smime ? APPLICATION_SMIME :
3782                                 APPLICATION_PGP, NULL))) {
3783       snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p));
3784       m_strreplace(is_smime ? &SmimeDefaultKey : &PgpSignAs,
3785                         input_signas);
3786       crypt_free_key (&p);
3787
3788       msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
3789     }
3790     *redraw = REDRAW_FULL;
3791     break;
3792
3793   case 4:                      /* (b)oth */
3794     msg->security =
3795       (is_smime ? (SMIMEENCRYPT | SMIMESIGN) : (PGPENCRYPT | PGPSIGN));
3796     break;
3797
3798   case 5:                      /* (p)gp or s/(m)ime */
3799     is_smime = !is_smime;
3800     break;
3801
3802   case 6:                      /* (c)lear */
3803     msg->security = 0;
3804     break;
3805   }
3806
3807   if (choice == 6 || choice == 7);
3808   else if (is_smime) {
3809     msg->security &= ~APPLICATION_PGP;
3810     msg->security |= APPLICATION_SMIME;
3811   }
3812   else {
3813     msg->security &= ~APPLICATION_SMIME;
3814     msg->security |= APPLICATION_PGP;
3815   }
3816
3817   return (msg->security);
3818 }
3819
3820 int crypt_pgp_send_menu(HEADER * msg, int *redraw)
3821 {
3822   return gpgme_send_menu(msg, redraw, 0);
3823 }
3824
3825 int crypt_smime_send_menu(HEADER * msg, int *redraw)
3826 {
3827   return gpgme_send_menu (msg, redraw, 1);
3828 }
3829
3830 int crypt_smime_verify_sender (HEADER * h)
3831 {
3832   address_t *sender = NULL;
3833   unsigned int ret = 1;
3834
3835   if (h->env->from) {
3836     h->env->from = mutt_expand_aliases (h->env->from);
3837     sender = h->env->from;
3838   }
3839   else if (h->env->sender) {
3840     h->env->sender = mutt_expand_aliases (h->env->sender);
3841     sender = h->env->sender;
3842   }
3843
3844   if (sender) {
3845     if (signature_key) {
3846       gpgme_key_t key = signature_key;
3847       gpgme_user_id_t uid = NULL;
3848       int sender_length = 0;
3849       int uid_length = 0;
3850
3851       sender_length = m_strlen(sender->mailbox);
3852       for (uid = key->uids; uid && ret; uid = uid->next) {
3853         uid_length = m_strlen(uid->email);
3854         if (1 && (uid->email[0] == '<')
3855             && (uid->email[uid_length - 1] == '>')
3856             && (uid_length == sender_length + 2)
3857             && (!m_strncmp (uid->email + 1, sender->mailbox, sender_length)))
3858           ret = 0;
3859       }
3860     }
3861     else
3862       mutt_any_key_to_continue ("Failed to verify sender");
3863   }
3864   else
3865     mutt_any_key_to_continue ("Failed to figure out sender");
3866
3867   if (signature_key) {
3868     gpgme_key_release (signature_key);
3869     signature_key = NULL;
3870   }
3871
3872   return ret;
3873 }
3874
3875 static void invoke_import(const char *fname, int smime)
3876 {
3877     gpgme_ctx_t ctx = create_gpgme_context(smime);
3878     gpgme_data_t data;
3879     gpgme_error_t err;
3880
3881     err = gpgme_data_new_from_file(&data, fname, 1);
3882     if (err) {
3883         mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
3884         gpgme_release(ctx);
3885         return;
3886     }
3887
3888     err = gpgme_op_import(ctx, data);
3889     if (err) {
3890         mutt_error(_("error importing gpg data: %s\n"), gpgme_strerror(err));
3891         gpgme_data_release(data);
3892         gpgme_release(ctx);
3893         return;
3894     }
3895
3896     gpgme_data_release(data);
3897     gpgme_release(ctx);
3898     return;
3899 }
3900
3901 void crypt_pgp_invoke_import(const char *fname)
3902 {
3903     invoke_import(fname, 0);
3904 }
3905
3906 void crypt_smime_invoke_import(const char *fname)
3907 {
3908     invoke_import(fname, 1);
3909 }
3910
3911 static void pgp_extract_keys_from_attachment (FILE * fp, BODY * top)
3912 {
3913   STATE s;
3914   FILE *tempfp;
3915   char tempfname[_POSIX_PATH_MAX];
3916
3917   tempfp = m_tempfile(tempfname, sizeof(tempfname), NONULL(MCore.tmpdir), NULL);
3918   if (tempfp == NULL) {
3919     mutt_perror (_("Can't create temporary file"));
3920     return;
3921   }
3922
3923   p_clear(&s, 1);
3924
3925   s.fpin = fp;
3926   s.fpout = tempfp;
3927
3928   mutt_body_handler (top, &s);
3929
3930   m_fclose(&tempfp);
3931   crypt_pgp_invoke_import(tempfname);
3932   mutt_unlink (tempfname);
3933 }
3934
3935 void crypt_pgp_extract_keys_from_attachment_list(FILE * fp, int tag, BODY * top)
3936 {
3937   mutt_endwin (NULL);
3938   set_option (OPTDONTHANDLEPGPKEYS);
3939
3940   for (; top; top = top->next) {
3941     if (!tag || top->tagged)
3942       pgp_extract_keys_from_attachment (fp, top);
3943
3944     if (!tag)
3945       break;
3946   }
3947
3948   unset_option (OPTDONTHANDLEPGPKEYS);
3949 }
3950