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