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