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