use a proper "hack" for iconv functions:
[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   fseeko (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 = ftello (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     fseeko (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 = ftello (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;
1775   LOFF_T last_pos, offset;
1776   char buf[HUGE_STRING];
1777   FILE *pgpout = NULL;
1778
1779   gpgme_error_t err = 0;
1780   gpgme_data_t armored_data = NULL;
1781
1782   short maybe_goodsig = 1;
1783   short have_any_sigs = 0;
1784
1785   char body_charset[STRING];    /* Only used for clearsigned messages. */
1786
1787   debug_print (2, ("Entering pgp_application_pgp handler\n"));
1788
1789   /* For clearsigned messages we won't be able to get a character set
1790      but we know that this may only be text thus we assume Latin-1
1791      here. */
1792   if (!mutt_get_body_charset (body_charset, sizeof (body_charset), m))
1793     strfcpy (body_charset, "iso-8859-1", sizeof body_charset);
1794
1795   fseeko (s->fpin, m->offset, 0);
1796   last_pos = m->offset;
1797
1798   for (bytes = m->length; bytes > 0;) {
1799     if (fgets (buf, sizeof (buf), s->fpin) == NULL)
1800       break;
1801
1802     offset = ftello (s->fpin);
1803     bytes -= (offset - last_pos);       /* don't rely on str_len(buf) */
1804     last_pos = offset;
1805
1806     if (!str_ncmp ("-----BEGIN PGP ", buf, 15)) {
1807       clearsign = 0;
1808       start_pos = last_pos;
1809
1810       if (!str_cmp ("MESSAGE-----\n", buf + 15))
1811         needpass = 1;
1812       else if (!str_cmp ("SIGNED MESSAGE-----\n", buf + 15)) {
1813         clearsign = 1;
1814         needpass = 0;
1815       }
1816       else if (!option (OPTDONTHANDLEPGPKEYS) &&
1817                !str_cmp ("PUBLIC KEY BLOCK-----\n", buf + 15)) {
1818         needpass = 0;
1819         pgp_keyblock = 1;
1820       }
1821       else {
1822         /* XXX - we may wish to recode here */
1823         if (s->prefix)
1824           state_puts (s->prefix, s);
1825         state_puts (buf, s);
1826         continue;
1827       }
1828
1829       have_any_sigs = (have_any_sigs || (clearsign && (s->flags & M_VERIFY)));
1830
1831       /* Copy PGP material to an data container */
1832       armored_data = create_gpgme_data ();
1833       gpgme_data_write (armored_data, buf, str_len (buf));
1834       while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL) {
1835         offset = ftello (s->fpin);
1836         bytes -= (offset - last_pos);   /* don't rely on str_len(buf) */
1837         last_pos = offset;
1838
1839         gpgme_data_write (armored_data, buf, str_len (buf));
1840
1841         if ((needpass && !str_cmp ("-----END PGP MESSAGE-----\n", buf))
1842             || (!needpass
1843                 && (!str_cmp ("-----END PGP SIGNATURE-----\n", buf)
1844                     || !str_cmp ("-----END PGP PUBLIC KEY BLOCK-----\n",
1845                                      buf))))
1846           break;
1847       }
1848
1849       /* Invoke PGP if needed */
1850       if (!clearsign || (s->flags & M_VERIFY)) {
1851         unsigned int sig_stat = 0;
1852         gpgme_data_t plaintext;
1853         gpgme_ctx_t ctx;
1854
1855         plaintext = create_gpgme_data ();
1856         ctx = create_gpgme_context (0);
1857
1858         if (clearsign)
1859           err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);
1860         else {
1861           err = gpgme_op_decrypt_verify (ctx, armored_data, plaintext);
1862           if (gpg_err_code (err) == GPG_ERR_NO_DATA) {
1863             /* Decrypt verify can't handle signed only messages. */
1864             err = (gpgme_data_seek (armored_data, 0, SEEK_SET) == -1)
1865               ? gpgme_error_from_errno (errno) : 0;
1866             /* Must release plaintext so that we supply an
1867                uninitialized object. */
1868             gpgme_data_release (plaintext);
1869             plaintext = create_gpgme_data ();
1870             err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);
1871           }
1872         }
1873
1874         if (err) {
1875           char errbuf[200];
1876
1877           snprintf (errbuf, sizeof (errbuf) - 1,
1878                     _("Error: decryption/verification failed: %s\n"),
1879                     gpgme_strerror (err));
1880           state_attach_puts (errbuf, s);
1881         }
1882         else {                  /* Decryption/Verification succeeded */
1883           char *tmpfname;
1884
1885           {
1886             /* Check wether signatures have been verified.  */
1887             gpgme_verify_result_t verify_result;
1888
1889             verify_result = gpgme_op_verify_result (ctx);
1890             if (verify_result->signatures)
1891               sig_stat = 1;
1892           }
1893
1894           have_any_sigs = 0;
1895           maybe_goodsig = 0;
1896           if ((s->flags & M_DISPLAY) && sig_stat) {
1897             int res, idx;
1898             int anybad = 0;
1899             int anywarn = 0;
1900
1901             state_attach_puts (_("[-- Begin signature "
1902                                  "information --]\n"), s);
1903             have_any_sigs = 1;
1904             for (idx = 0;
1905                  (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) {
1906               if (res == 1)
1907                 anybad = 1;
1908               else if (res == 2)
1909                 anywarn = 1;
1910             }
1911             if (!anybad && idx)
1912               maybe_goodsig = 1;
1913
1914             state_attach_puts (_("[-- End signature "
1915                                  "information --]\n\n"), s);
1916           }
1917
1918           tmpfname = data_object_to_tempfile (plaintext, &pgpout);
1919           if (!tmpfname) {
1920             pgpout = NULL;
1921             state_attach_puts (_("Error: copy data failed\n"), s);
1922           }
1923           else {
1924             unlink (tmpfname);
1925             mem_free (&tmpfname);
1926           }
1927         }
1928         gpgme_release (ctx);
1929       }
1930
1931       /*
1932        * Now, copy cleartext to the screen.  NOTE - we expect that PGP
1933        * outputs utf-8 cleartext.  This may not always be true, but it 
1934        * seems to be a reasonable guess.
1935        */
1936
1937       if (s->flags & M_DISPLAY) {
1938         if (needpass)
1939           state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s);
1940         else if (pgp_keyblock)
1941           state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"), s);
1942         else
1943           state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"), s);
1944       }
1945
1946       if (clearsign) {
1947         copy_clearsigned (armored_data, s, body_charset);
1948       }
1949       else if (pgpout) {
1950         FGETCONV *fc;
1951         int c;
1952
1953         rewind (pgpout);
1954         fc = fgetconv_open (pgpout, "utf-8", Charset, 0);
1955         while ((c = fgetconv (fc)) != EOF) {
1956           state_putc (c, s);
1957           if (c == '\n' && s->prefix)
1958             state_puts (s->prefix, s);
1959         }
1960         fgetconv_close (&fc);
1961       }
1962
1963       if (s->flags & M_DISPLAY) {
1964         state_putc ('\n', s);
1965         if (needpass)
1966           state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
1967         else if (pgp_keyblock)
1968           state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);
1969         else
1970           state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);
1971       }
1972
1973       if (pgpout) {
1974         safe_fclose (&pgpout);
1975       }
1976     }
1977     else {
1978       /* XXX - we may wish to recode here */
1979       if (s->prefix)
1980         state_puts (s->prefix, s);
1981       state_puts (buf, s);
1982     }
1983   }
1984
1985   m->goodsig = (maybe_goodsig && have_any_sigs);
1986
1987   if (needpass == -1) {
1988     state_attach_puts (_("[-- Error: could not find beginning"
1989                          " of PGP message! --]\n\n"), s);
1990     return (-1);
1991   }
1992   debug_print (2, ("Leaving pgp_application_pgp handler\n"));
1993   return (err);
1994 }
1995
1996 /* 
1997  * Implementation of `encrypted_handler'.
1998  */
1999
2000 /* MIME handler for pgp/mime encrypted messages. */
2001 int pgp_gpgme_encrypted_handler (BODY * a, STATE * s)
2002 {
2003   char tempfile[_POSIX_PATH_MAX];
2004   FILE *fpout;
2005   BODY *tattach;
2006   BODY *orig_body = a;
2007   int is_signed;
2008   int rc = 0;
2009
2010   debug_print (2, ("Entering pgp_encrypted handler\n"));
2011   a = a->parts;
2012   if (!a || a->type != TYPEAPPLICATION || !a->subtype
2013       || ascii_strcasecmp ("pgp-encrypted", a->subtype)
2014       || !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype
2015       || ascii_strcasecmp ("octet-stream", a->next->subtype)) {
2016     if (s->flags & M_DISPLAY)
2017       state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"),
2018                          s);
2019     return (-1);
2020   }
2021
2022   /* Move forward to the application/pgp-encrypted body. */
2023   a = a->next;
2024
2025   mutt_mktemp (tempfile);
2026   if (!(fpout = safe_fopen (tempfile, "w+"))) {
2027     if (s->flags & M_DISPLAY)
2028       state_attach_puts (_("[-- Error: could not create temporary file! "
2029                            "--]\n"), s);
2030     return (-1);
2031   }
2032
2033   tattach = decrypt_part (a, s, fpout, 0, &is_signed);
2034   if (tattach) {
2035     tattach->goodsig = is_signed > 0;
2036
2037     if (s->flags & M_DISPLAY)
2038       state_attach_puts (is_signed ?
2039                          _
2040                          ("[-- The following data is PGP/MIME signed and encrypted --]\n\n") :
2041                          _("[-- The following data is PGP/MIME encrypted --]\n\n"), s);
2042
2043     {
2044       FILE *savefp = s->fpin;
2045
2046       s->fpin = fpout;
2047       rc = mutt_body_handler (tattach, s);
2048       s->fpin = savefp;
2049     }
2050
2051     /* 
2052      * if a multipart/signed is the _only_ sub-part of a
2053      * multipart/encrypted, cache signature verification
2054      * status.
2055      */
2056     if (mutt_is_multipart_signed (tattach) && !tattach->next)
2057       orig_body->goodsig |= tattach->goodsig;
2058
2059     if (s->flags & M_DISPLAY) {
2060       state_puts ("\n", s);
2061       state_attach_puts (is_signed ?
2062                          _
2063                          ("[-- End of PGP/MIME signed and encrypted data --]\n")
2064                          : _("[-- End of PGP/MIME encrypted data --]\n"), s);
2065     }
2066
2067     mutt_free_body (&tattach);
2068   }
2069
2070   fclose (fpout);
2071   mutt_unlink (tempfile);
2072   debug_print (2, ("Leaving pgp_encrypted handler\n"));
2073   return (rc);
2074 }
2075
2076 /* Support for application/smime */
2077 int smime_gpgme_application_handler (BODY * a, STATE * s)
2078 {
2079   char tempfile[_POSIX_PATH_MAX];
2080   FILE *fpout;
2081   BODY *tattach;
2082   int is_signed;
2083   int rc = 0;
2084
2085   debug_print (2, ("Entering smime_encrypted handler\n"));
2086
2087   a->warnsig = 0;
2088   mutt_mktemp (tempfile);
2089   if (!(fpout = safe_fopen (tempfile, "w+"))) {
2090     if (s->flags & M_DISPLAY)
2091       state_attach_puts (_("[-- Error: could not create temporary file! "
2092                            "--]\n"), s);
2093     return (-1);
2094   }
2095
2096   tattach = decrypt_part (a, s, fpout, 1, &is_signed);
2097   if (tattach) {
2098     tattach->goodsig = is_signed > 0;
2099
2100     if (s->flags & M_DISPLAY)
2101       state_attach_puts (is_signed ?
2102                          _("[-- The following data is S/MIME signed --]\n\n") :
2103                          _("[-- The following data is S/MIME encrypted --]\n\n"), s);
2104
2105     {
2106       FILE *savefp = s->fpin;
2107
2108       s->fpin = fpout;
2109       rc = mutt_body_handler (tattach, s);
2110       s->fpin = savefp;
2111     }
2112
2113     /* 
2114      * if a multipart/signed is the _only_ sub-part of a
2115      * multipart/encrypted, cache signature verification
2116      * status.
2117      */
2118     if (mutt_is_multipart_signed (tattach) && !tattach->next) {
2119       if (!(a->goodsig = tattach->goodsig))
2120         a->warnsig = tattach->warnsig;
2121     }
2122     else if (tattach->goodsig) {
2123       a->goodsig = 1;
2124       a->warnsig = tattach->warnsig;
2125     }
2126
2127     if (s->flags & M_DISPLAY) {
2128       state_puts ("\n", s);
2129       state_attach_puts (is_signed ?
2130                          _("[-- End of S/MIME signed data --]\n") :
2131                          _("[-- End of S/MIME encrypted data --]\n"), s);
2132     }
2133
2134     mutt_free_body (&tattach);
2135   }
2136
2137   fclose (fpout);
2138   mutt_unlink (tempfile);
2139   debug_print (2, ("Leaving smime_encrypted handler\n"));
2140   return (rc);
2141 }
2142
2143
2144 /*
2145  * Format an entry on the CRYPT key selection menu.
2146  * 
2147  * %n   number
2148  * %k   key id          %K      key id of the principal key
2149  * %u   user id
2150  * %a   algorithm       %A      algorithm of the princ. key
2151  * %l   length          %L      length of the princ. key
2152  * %f   flags           %F      flags of the princ. key
2153  * %c   capabilities    %C      capabilities of the princ. key
2154  * %t   trust/validity of the key-uid association
2155  * %p           protocol
2156  * %[...] date of key using strftime(3)
2157  */
2158
2159 static const char *crypt_entry_fmt (char *dest,
2160                                     size_t destlen,
2161                                     char op,
2162                                     const char *src,
2163                                     const char *prefix,
2164                                     const char *ifstring,
2165                                     const char *elsestring,
2166                                     unsigned long data, format_flag flags)
2167 {
2168   char fmt[16];
2169   crypt_entry_t *entry;
2170   crypt_key_t *key;
2171   int kflags = 0;
2172   int optional = (flags & M_FORMAT_OPTIONAL);
2173   const char *s = NULL;
2174   unsigned long val;
2175
2176   entry = (crypt_entry_t *) data;
2177   key = entry->key;
2178
2179 /*    if (isupper ((unsigned char) op)) */
2180 /*      key = pkey; */
2181
2182   kflags = (key->flags          /*| (pkey->flags & KEYFLAG_RESTRICTIONS)
2183                                    | uid->flags */ );
2184
2185   switch (ascii_tolower (op)) {
2186   case '[':
2187     {
2188       const char *cp;
2189       char buf2[SHORT_STRING], *p;
2190       int do_locales;
2191       struct tm *tm;
2192       size_t len;
2193
2194       p = dest;
2195
2196       cp = src;
2197       if (*cp == '!') {
2198         do_locales = 0;
2199         cp++;
2200       }
2201       else
2202         do_locales = 1;
2203
2204       len = destlen - 1;
2205       while (len > 0 && *cp != ']') {
2206         if (*cp == '%') {
2207           cp++;
2208           if (len >= 2) {
2209             *p++ = '%';
2210             *p++ = *cp;
2211             len -= 2;
2212           }
2213           else
2214             break;              /* not enough space */
2215           cp++;
2216         }
2217         else {
2218           *p++ = *cp++;
2219           len--;
2220         }
2221       }
2222       *p = 0;
2223
2224       if (do_locales && Locale)
2225         setlocale (LC_TIME, Locale);
2226
2227       {
2228         time_t tt = 0;
2229
2230         if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
2231           tt = key->kobj->subkeys->timestamp;
2232
2233         tm = localtime (&tt);
2234       }
2235       strftime (buf2, sizeof (buf2), dest, tm);
2236
2237       if (do_locales)
2238         setlocale (LC_TIME, "C");
2239
2240       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2241       snprintf (dest, destlen, fmt, buf2);
2242       if (len > 0)
2243         src = cp + 1;
2244     }
2245     break;
2246   case 'n':
2247     if (!optional) {
2248       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
2249       snprintf (dest, destlen, fmt, entry->num);
2250     }
2251     break;
2252   case 'k':
2253     if (!optional) {
2254       /* fixme: we need a way to distinguish between main and subkeys.
2255          Store the idx in entry? */
2256       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2257       snprintf (dest, destlen, fmt, crypt_keyid (key));
2258     }
2259     break;
2260   case 'u':
2261     if (!optional) {
2262       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2263       snprintf (dest, destlen, fmt, key->uid);
2264     }
2265     break;
2266   case 'a':
2267     if (!optional) {
2268       snprintf (fmt, sizeof (fmt), "%%%s.3s", prefix);
2269       if (key->kobj->subkeys)
2270         s = gpgme_pubkey_algo_name (key->kobj->subkeys->pubkey_algo);
2271       else
2272         s = "?";
2273       snprintf (dest, destlen, fmt, s);
2274     }
2275     break;
2276   case 'l':
2277     if (!optional) {
2278       snprintf (fmt, sizeof (fmt), "%%%slu", prefix);
2279       if (key->kobj->subkeys)
2280         val = key->kobj->subkeys->length;
2281       else
2282         val = 0;
2283       snprintf (dest, destlen, fmt, val);
2284     }
2285     break;
2286   case 'f':
2287     if (!optional) {
2288       snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2289       snprintf (dest, destlen, fmt, crypt_flags (kflags));
2290     }
2291     else if (!(kflags & (KEYFLAG_RESTRICTIONS)))
2292       optional = 0;
2293     break;
2294   case 'c':
2295     if (!optional) {
2296       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2297       snprintf (dest, destlen, fmt, crypt_key_abilities (kflags));
2298     }
2299     else if (!(kflags & (KEYFLAG_ABILITIES)))
2300       optional = 0;
2301     break;
2302   case 't':
2303     if ((kflags & KEYFLAG_ISX509))
2304       s = "x";
2305     else {
2306       gpgme_user_id_t uid = NULL;
2307       unsigned int i = 0;
2308
2309       for (i = 0, uid = key->kobj->uids; uid && (i < key->idx);
2310            i++, uid = uid->next);
2311       if (uid)
2312         switch (uid->validity) {
2313         case GPGME_VALIDITY_UNDEFINED:
2314           s = "q";
2315           break;
2316         case GPGME_VALIDITY_NEVER:
2317           s = "n";
2318           break;
2319         case GPGME_VALIDITY_MARGINAL:
2320           s = "m";
2321           break;
2322         case GPGME_VALIDITY_FULL:
2323           s = "f";
2324           break;
2325         case GPGME_VALIDITY_ULTIMATE:
2326           s = "u";
2327           break;
2328         case GPGME_VALIDITY_UNKNOWN:
2329         default:
2330           s = "?";
2331           break;
2332         }
2333     }
2334     snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2335     snprintf (dest, destlen, fmt, s ? *s : 'B');
2336     break;
2337   case 'p':
2338     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2339     snprintf (dest, destlen, fmt,
2340               gpgme_get_protocol_name (key->kobj->protocol));
2341     break;
2342
2343   default:
2344     *dest = '\0';
2345   }
2346
2347   if (optional)
2348     mutt_FormatString (dest, destlen, ifstring, mutt_attach_fmt, data, 0);
2349   else if (flags & M_FORMAT_OPTIONAL)
2350     mutt_FormatString (dest, destlen, elsestring, mutt_attach_fmt, data, 0);
2351   return (src);
2352 }
2353
2354 /* Used by the display fucntion to format a line. */
2355 static void crypt_entry (char *s, size_t l, MUTTMENU * menu, int num)
2356 {
2357   crypt_key_t **key_table = (crypt_key_t **) menu->data;
2358   crypt_entry_t entry;
2359
2360   entry.key = key_table[num];
2361   entry.num = num + 1;
2362
2363   mutt_FormatString (s, l, NONULL (PgpEntryFormat), crypt_entry_fmt,
2364                      (unsigned long) &entry, M_FORMAT_ARROWCURSOR);
2365 }
2366
2367 /* Compare two addresses and the keyid to be used for sorting. */
2368 static int _crypt_compare_address (const void *a, const void *b)
2369 {
2370   crypt_key_t **s = (crypt_key_t **) a;
2371   crypt_key_t **t = (crypt_key_t **) b;
2372   int r;
2373
2374   if ((r = str_casecmp ((*s)->uid, (*t)->uid)))
2375     return r > 0;
2376   else
2377     return str_casecmp (crypt_keyid (*s), crypt_keyid (*t)) > 0;
2378 }
2379
2380 static int crypt_compare_address (const void *a, const void *b)
2381 {
2382   return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_address (a, b)
2383           : _crypt_compare_address (a, b));
2384 }
2385
2386
2387 /* Compare two key IDs and the addresses to be used for sorting. */
2388 static int _crypt_compare_keyid (const void *a, const void *b)
2389 {
2390   crypt_key_t **s = (crypt_key_t **) a;
2391   crypt_key_t **t = (crypt_key_t **) b;
2392   int r;
2393
2394   if ((r = str_casecmp (crypt_keyid (*s), crypt_keyid (*t))))
2395     return r > 0;
2396   else
2397     return str_casecmp ((*s)->uid, (*t)->uid) > 0;
2398 }
2399
2400 static int crypt_compare_keyid (const void *a, const void *b)
2401 {
2402   return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_keyid (a, b)
2403           : _crypt_compare_keyid (a, b));
2404 }
2405
2406 /* Compare 2 creation dates and the addresses.  For sorting. */
2407 static int _crypt_compare_date (const void *a, const void *b)
2408 {
2409   crypt_key_t **s = (crypt_key_t **) a;
2410   crypt_key_t **t = (crypt_key_t **) b;
2411   unsigned long ts = 0, tt = 0;
2412
2413   if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2414     ts = (*s)->kobj->subkeys->timestamp;
2415   if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2416     tt = (*t)->kobj->subkeys->timestamp;
2417
2418   if (ts > tt)
2419     return 1;
2420   if (ts < tt)
2421     return 0;
2422
2423   return str_casecmp ((*s)->uid, (*t)->uid) > 0;
2424 }
2425
2426 static int crypt_compare_date (const void *a, const void *b)
2427 {
2428   return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_date (a, b)
2429           : _crypt_compare_date (a, b));
2430 }
2431
2432 /* Compare two trust values, the key length, the creation dates. the
2433    addresses and the key IDs.  For sorting. */
2434 static int _crypt_compare_trust (const void *a, const void *b)
2435 {
2436   crypt_key_t **s = (crypt_key_t **) a;
2437   crypt_key_t **t = (crypt_key_t **) b;
2438   unsigned long ts = 0, tt = 0;
2439   int r;
2440
2441   if ((r = (((*s)->flags & (KEYFLAG_RESTRICTIONS))
2442             - ((*t)->flags & (KEYFLAG_RESTRICTIONS)))))
2443     return r > 0;
2444
2445   if ((*s)->kobj->uids)
2446     ts = (*s)->kobj->uids->validity;
2447   if ((*t)->kobj->uids)
2448     tt = (*t)->kobj->uids->validity;
2449   if ((r = (tt - ts)))
2450     return r < 0;
2451
2452   if ((*s)->kobj->subkeys)
2453     ts = (*s)->kobj->subkeys->length;
2454   if ((*t)->kobj->subkeys)
2455     tt = (*t)->kobj->subkeys->length;
2456   if (ts != tt)
2457     return ts > tt;
2458
2459   if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2460     ts = (*s)->kobj->subkeys->timestamp;
2461   if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2462     tt = (*t)->kobj->subkeys->timestamp;
2463   if (ts > tt)
2464     return 1;
2465   if (ts < tt)
2466     return 0;
2467
2468   if ((r = str_casecmp ((*s)->uid, (*t)->uid)))
2469     return r > 0;
2470   return (str_casecmp (crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0;
2471 }
2472
2473 static int crypt_compare_trust (const void *a, const void *b)
2474 {
2475   return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_trust (a, b)
2476           : _crypt_compare_trust (a, b));
2477 }
2478
2479 /* Print the X.500 Distinguished Name part KEY from the array of parts
2480    DN to FP. */
2481 static int print_dn_part (FILE * fp, struct dn_array_s *dn, const char *key)
2482 {
2483   int any = 0;
2484
2485   for (; dn->key; dn++) {
2486     if (!str_cmp (dn->key, key)) {
2487       if (any)
2488         fputs (" + ", fp);
2489       print_utf8 (fp, dn->value, str_len (dn->value));
2490       any = 1;
2491     }
2492   }
2493   return any;
2494 }
2495
2496 /* Print all parts of a DN in a standard sequence. */
2497 static void print_dn_parts (FILE * fp, struct dn_array_s *dn)
2498 {
2499   const char *stdpart[] = {
2500     "CN", "OU", "O", "STREET", "L", "ST", "C", NULL
2501   };
2502   int any = 0, any2 = 0, i;
2503
2504   for (i = 0; stdpart[i]; i++) {
2505     if (any)
2506       fputs (", ", fp);
2507     any = print_dn_part (fp, dn, stdpart[i]);
2508   }
2509   /* now print the rest without any specific ordering */
2510   for (; dn->key; dn++) {
2511     for (i = 0; stdpart[i]; i++) {
2512       if (!str_cmp (dn->key, stdpart[i]))
2513         break;
2514     }
2515     if (!stdpart[i]) {
2516       if (any)
2517         fputs (", ", fp);
2518       if (!any2)
2519         fputs ("(", fp);
2520       any = print_dn_part (fp, dn, dn->key);
2521       any2 = 1;
2522     }
2523   }
2524   if (any2)
2525     fputs (")", fp);
2526 }
2527
2528
2529 /* Parse an RDN; this is a helper to parse_dn(). */
2530 static const unsigned char *parse_dn_part (struct dn_array_s *array,
2531                                            const unsigned char *string)
2532 {
2533   const unsigned char *s, *s1;
2534   size_t n;
2535   unsigned char *p;
2536
2537   /* parse attributeType */
2538   for (s = string + 1; *s && *s != '='; s++);
2539   if (!*s)
2540     return NULL;                /* error */
2541   n = s - string;
2542   if (!n)
2543     return NULL;                /* empty key */
2544   array->key = mem_malloc (n + 1);
2545   p = (unsigned char *) array->key;
2546   memcpy (p, string, n);        /* fixme: trim trailing spaces */
2547   p[n] = 0;
2548   string = s + 1;
2549
2550   if (*string == '#') {         /* hexstring */
2551     string++;
2552     for (s = string; hexdigitp (s); s++)
2553       s++;
2554     n = s - string;
2555     if (!n || (n & 1))
2556       return NULL;              /* empty or odd number of digits */
2557     n /= 2;
2558     p = mem_malloc (n + 1);
2559     array->value = (char *) p;
2560     for (s1 = string; n; s1 += 2, n--)
2561       *p++ = xtoi_2 (s1);
2562     *p = 0;
2563   }
2564   else {                        /* regular v3 quoted string */
2565     for (n = 0, s = string; *s; s++) {
2566       if (*s == '\\') {         /* pair */
2567         s++;
2568         if (*s == ',' || *s == '=' || *s == '+'
2569             || *s == '<' || *s == '>' || *s == '#' || *s == ';'
2570             || *s == '\\' || *s == '\"' || *s == ' ')
2571           n++;
2572         else if (hexdigitp (s) && hexdigitp (s + 1)) {
2573           s++;
2574           n++;
2575         }
2576         else
2577           return NULL;          /* invalid escape sequence */
2578       }
2579       else if (*s == '\"')
2580         return NULL;            /* invalid encoding */
2581       else if (*s == ',' || *s == '=' || *s == '+'
2582                || *s == '<' || *s == '>' || *s == '#' || *s == ';')
2583         break;
2584       else
2585         n++;
2586     }
2587
2588     p = mem_malloc (n + 1);
2589     array->value = (char *) p;
2590     for (s = string; n; s++, n--) {
2591       if (*s == '\\') {
2592         s++;
2593         if (hexdigitp (s)) {
2594           *p++ = xtoi_2 (s);
2595           s++;
2596         }
2597         else
2598           *p++ = *s;
2599       }
2600       else
2601         *p++ = *s;
2602     }
2603     *p = 0;
2604   }
2605   return s;
2606 }
2607
2608
2609 /* Parse a DN and return an array-ized one.  This is not a validating
2610    parser and it does not support any old-stylish syntax; gpgme is
2611    expected to return only rfc2253 compatible strings. */
2612 static struct dn_array_s *parse_dn (const unsigned char *string)
2613 {
2614   struct dn_array_s *array;
2615   size_t arrayidx, arraysize;
2616   int i;
2617
2618   arraysize = 7;                /* C,ST,L,O,OU,CN,email */
2619   array = mem_malloc ((arraysize + 1) * sizeof *array);
2620   arrayidx = 0;
2621   while (*string) {
2622     while (*string == ' ')
2623       string++;
2624     if (!*string)
2625       break;                    /* ready */
2626     if (arrayidx >= arraysize) {        /* mutt lacks a real safe_realoc - so we need to copy */
2627       struct dn_array_s *a2;
2628
2629       arraysize += 5;
2630       a2 = mem_malloc ((arraysize + 1) * sizeof *array);
2631       for (i = 0; i < arrayidx; i++) {
2632         a2[i].key = array[i].key;
2633         a2[i].value = array[i].value;
2634       }
2635       mem_free (&array);
2636       array = a2;
2637     }
2638     array[arrayidx].key = NULL;
2639     array[arrayidx].value = NULL;
2640     string = parse_dn_part (array + arrayidx, string);
2641     arrayidx++;
2642     if (!string)
2643       goto failure;
2644     while (*string == ' ')
2645       string++;
2646     if (*string && *string != ',' && *string != ';' && *string != '+')
2647       goto failure;             /* invalid delimiter */
2648     if (*string)
2649       string++;
2650   }
2651   array[arrayidx].key = NULL;
2652   array[arrayidx].value = NULL;
2653   return array;
2654
2655 failure:
2656   for (i = 0; i < arrayidx; i++) {
2657     mem_free (&array[i].key);
2658     mem_free (&array[i].value);
2659   }
2660   mem_free (&array);
2661   return NULL;
2662 }
2663
2664
2665 /* Print a nice representation of the USERID and make sure it is
2666    displayed in a proper way, which does mean to reorder some parts
2667    for S/MIME's DNs.  USERID is a string as returned by the gpgme key
2668    functions.  It is utf-8 encoded. */
2669 static void parse_and_print_user_id (FILE * fp, const char *userid)
2670 {
2671   const char *s;
2672   int i;
2673
2674   if (*userid == '<') {
2675     s = strchr (userid + 1, '>');
2676     if (s)
2677       print_utf8 (fp, userid + 1, s - userid - 1);
2678   }
2679   else if (*userid == '(')
2680     fputs (_("[Can't display this user ID (unknown encoding)]"), fp);
2681   else if (!digit_or_letter ((const unsigned char *) userid))
2682     fputs (_("[Can't display this user ID (invalid encoding)]"), fp);
2683   else {
2684     struct dn_array_s *dn = parse_dn ((const unsigned char *) userid);
2685
2686     if (!dn)
2687       fputs (_("[Can't display this user ID (invalid DN)]"), fp);
2688     else {
2689       print_dn_parts (fp, dn);
2690       for (i = 0; dn[i].key; i++) {
2691         mem_free (&dn[i].key);
2692         mem_free (&dn[i].value);
2693       }
2694       mem_free (&dn);
2695     }
2696   }
2697 }
2698
2699 typedef enum {
2700   KEY_CAP_CAN_ENCRYPT,
2701   KEY_CAP_CAN_SIGN,
2702   KEY_CAP_CAN_CERTIFY
2703 } key_cap_t;
2704
2705 static unsigned int key_check_cap (gpgme_key_t key, key_cap_t cap)
2706 {
2707   gpgme_subkey_t subkey = NULL;
2708   unsigned int ret = 0;
2709
2710   switch (cap) {
2711   case KEY_CAP_CAN_ENCRYPT:
2712     if (!(ret = key->can_encrypt))
2713       for (subkey = key->subkeys; subkey; subkey = subkey->next)
2714         if ((ret = subkey->can_encrypt))
2715           break;
2716     break;
2717   case KEY_CAP_CAN_SIGN:
2718     if (!(ret = key->can_sign))
2719       for (subkey = key->subkeys; subkey; subkey = subkey->next)
2720         if ((ret = subkey->can_sign))
2721           break;
2722     break;
2723   case KEY_CAP_CAN_CERTIFY:
2724     if (!(ret = key->can_certify))
2725       for (subkey = key->subkeys; subkey; subkey = subkey->next)
2726         if ((ret = subkey->can_certify))
2727           break;
2728     break;
2729   }
2730
2731   return ret;
2732 }
2733
2734
2735 /* Print verbose information about a key or certificate to FP. */
2736 static void print_key_info (gpgme_key_t key, FILE * fp)
2737 {
2738   int idx;
2739   const char *s = NULL, *s2 = NULL;
2740   time_t tt = 0;
2741   struct tm *tm;
2742   char shortbuf[SHORT_STRING];
2743   unsigned long aval = 0;
2744   const char *delim;
2745   int is_pgp = 0;
2746   int i;
2747   gpgme_user_id_t uid = NULL;
2748
2749   if (Locale)
2750     setlocale (LC_TIME, Locale);
2751
2752   is_pgp = key->protocol == GPGME_PROTOCOL_OpenPGP;
2753
2754   for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
2755     if (uid->revoked)
2756       continue;
2757
2758     s = uid->uid;
2759     fputs (idx ? _(" aka ......: ") :_("Name ......: "), fp);
2760
2761     if (uid->invalid) {
2762       fputs (_("[Invalid]"), fp);
2763       putc (' ', fp);
2764     }
2765     if (is_pgp)
2766       print_utf8 (fp, s, str_len (s));
2767     else
2768       parse_and_print_user_id (fp, s);
2769     putc ('\n', fp);
2770   }
2771
2772   if (key->subkeys && (key->subkeys->timestamp > 0)) {
2773     tt = key->subkeys->timestamp;
2774
2775     tm = localtime (&tt);
2776 #ifdef HAVE_LANGINFO_D_T_FMT
2777     strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2778 #else
2779     strftime (shortbuf, sizeof shortbuf, "%c", tm);
2780 #endif
2781     fprintf (fp, _("Valid From : %s\n"), shortbuf);
2782   }
2783
2784   if (key->subkeys && (key->subkeys->expires > 0)) {
2785     tt = key->subkeys->expires;
2786
2787     tm = localtime (&tt);
2788 #ifdef HAVE_LANGINFO_D_T_FMT
2789     strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2790 #else
2791     strftime (shortbuf, sizeof shortbuf, "%c", tm);
2792 #endif
2793     fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
2794   }
2795
2796   if (key->subkeys)
2797     s = gpgme_pubkey_algo_name (key->subkeys->pubkey_algo);
2798   else
2799     s = "?";
2800
2801   s2 = is_pgp ? "PGP" : "X.509";
2802
2803   if (key->subkeys)
2804     aval = key->subkeys->length;
2805
2806   fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), s2, aval, s);
2807
2808   fprintf (fp, _("Key Usage .: "));
2809   delim = "";
2810
2811   if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) {
2812     fprintf (fp, "%s%s", delim, _("encryption"));
2813     delim = _(", ");
2814   }
2815   if (key_check_cap (key, KEY_CAP_CAN_SIGN)) {
2816     fprintf (fp, "%s%s", delim, _("signing"));
2817     delim = _(", ");
2818   }
2819   if (key_check_cap (key, KEY_CAP_CAN_CERTIFY)) {
2820     fprintf (fp, "%s%s", delim, _("certification"));
2821     delim = _(", ");
2822   }
2823   putc ('\n', fp);
2824
2825   if (key->subkeys) {
2826     s = key->subkeys->fpr;
2827     fputs (_("Fingerprint: "), fp);
2828     if (is_pgp && str_len (s) == 40) {
2829       for (i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) {
2830         putc (*s, fp);
2831         putc (s[1], fp);
2832         putc (s[2], fp);
2833         putc (s[3], fp);
2834         putc (is_pgp ? ' ' : ':', fp);
2835         if (is_pgp && i == 4)
2836           putc (' ', fp);
2837       }
2838     }
2839     else {
2840       for (i = 0; *s && s[1] && s[2]; s += 2, i++) {
2841         putc (*s, fp);
2842         putc (s[1], fp);
2843         putc (is_pgp ? ' ' : ':', fp);
2844         if (is_pgp && i == 7)
2845           putc (' ', fp);
2846       }
2847     }
2848     fprintf (fp, "%s\n", s);
2849   }
2850
2851   if (key->issuer_serial) {
2852     s = key->issuer_serial;
2853     if (s)
2854       fprintf (fp, _("Serial-No .: 0x%s\n"), s);
2855   }
2856
2857   if (key->issuer_name) {
2858     s = key->issuer_name;
2859     if (s) {
2860       fprintf (fp, _("Issued By .: "));
2861       parse_and_print_user_id (fp, s);
2862       putc ('\n', fp);
2863     }
2864   }
2865
2866   /* For PGP we list all subkeys. */
2867   if (is_pgp) {
2868     gpgme_subkey_t subkey = NULL;
2869
2870     for (idx = 1, subkey = key->subkeys; subkey; idx++, subkey = subkey->next) {
2871       s = subkey->keyid;
2872
2873       putc ('\n', fp);
2874       if (str_len (s) == 16)
2875         s += 8;                 /* display only the short keyID */
2876       fprintf (fp, _("Subkey ....: 0x%s"), s);
2877       if (subkey->revoked) {
2878         putc (' ', fp);
2879         fputs (_("[Revoked]"), fp);
2880       }
2881       if (subkey->invalid) {
2882         putc (' ', fp);
2883         fputs (_("[Invalid]"), fp);
2884       }
2885       if (subkey->expired) {
2886         putc (' ', fp);
2887         fputs (_("[Expired]"), fp);
2888       }
2889       if (subkey->disabled) {
2890         putc (' ', fp);
2891         fputs (_("[Disabled]"), fp);
2892       }
2893       putc ('\n', fp);
2894
2895       if (subkey->timestamp > 0) {
2896         tt = subkey->timestamp;
2897
2898         tm = localtime (&tt);
2899 #ifdef HAVE_LANGINFO_D_T_FMT
2900         strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2901 #else
2902         strftime (shortbuf, sizeof shortbuf, "%c", tm);
2903 #endif
2904         fprintf (fp, _("Valid From : %s\n"), shortbuf);
2905       }
2906
2907       if (subkey->expires > 0) {
2908         tt = subkey->expires;
2909
2910         tm = localtime (&tt);
2911 #ifdef HAVE_LANGINFO_D_T_FMT
2912         strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2913 #else
2914         strftime (shortbuf, sizeof shortbuf, "%c", tm);
2915 #endif
2916         fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
2917       }
2918
2919       if (subkey)
2920         s = gpgme_pubkey_algo_name (subkey->pubkey_algo);
2921       else
2922         s = "?";
2923
2924       if (subkey)
2925         aval = subkey->length;
2926       else
2927         aval = 0;
2928
2929       fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), "PGP", aval, s);
2930
2931       fprintf (fp, _("Key Usage .: "));
2932       delim = "";
2933
2934       if (subkey->can_encrypt) {
2935         fprintf (fp, "%s%s", delim, _("encryption"));
2936         delim = _(", ");
2937       }
2938       if (subkey->can_sign) {
2939         fprintf (fp, "%s%s", delim, _("signing"));
2940         delim = _(", ");
2941       }
2942       if (subkey->can_certify) {
2943         fprintf (fp, "%s%s", delim, _("certification"));
2944         delim = _(", ");
2945       }
2946       putc ('\n', fp);
2947     }
2948   }
2949
2950   if (Locale)
2951     setlocale (LC_TIME, "C");
2952 }
2953
2954
2955 /* Show detailed information about the selected key */
2956 static void verify_key (crypt_key_t * key)
2957 {
2958   FILE *fp;
2959   char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX];
2960   const char *s;
2961   gpgme_ctx_t listctx = NULL;
2962   gpgme_error_t err;
2963   gpgme_key_t k = NULL;
2964   int maxdepth = 100;
2965
2966   mutt_mktemp (tempfile);
2967   if (!(fp = safe_fopen (tempfile, "w"))) {
2968     mutt_perror (_("Can't create temporary file"));
2969
2970     return;
2971   }
2972   mutt_message _("Collecting data...");
2973
2974   print_key_info (key->kobj, fp);
2975
2976   err = gpgme_new (&listctx);
2977   if (err) {
2978     fprintf (fp, "Internal error: can't create gpgme context: %s\n",
2979              gpgme_strerror (err));
2980     goto leave;
2981   }
2982   if ((key->flags & KEYFLAG_ISX509))
2983     gpgme_set_protocol (listctx, GPGME_PROTOCOL_CMS);
2984
2985   k = key->kobj;
2986   gpgme_key_ref (k);
2987   while ((s = k->chain_id) && k->subkeys && str_cmp (s, k->subkeys->fpr)) {
2988     putc ('\n', fp);
2989     err = gpgme_op_keylist_start (listctx, s, 0);
2990     gpgme_key_release (k);
2991     k = NULL;
2992     if (!err)
2993       err = gpgme_op_keylist_next (listctx, &k);
2994     if (err) {
2995       fprintf (fp, _("Error finding issuer key: %s\n"), gpgme_strerror (err));
2996       goto leave;
2997     }
2998     gpgme_op_keylist_end (listctx);
2999
3000     print_key_info (k, fp);
3001     if (!--maxdepth) {
3002       putc ('\n', fp);
3003       fputs (_("Error: certification chain to long - stopping here\n"), fp);
3004       break;
3005     }
3006   }
3007
3008 leave:
3009   gpgme_key_release (k);
3010   gpgme_release (listctx);
3011   fclose (fp);
3012   mutt_clear_error ();
3013   snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"), crypt_keyid (key));
3014   mutt_do_pager (cmd, tempfile, 0, NULL);
3015 }
3016
3017 /* 
3018  * Implementation of `findkeys'.
3019  */
3020
3021
3022 /* Convert LIST into a pattern string suitable to be passed to GPGME.
3023    We need to convert spaces in an item into a '+' and '%' into
3024    "%25". */
3025 static char *list_to_pattern (LIST * list)
3026 {
3027   LIST *l;
3028   char *pattern, *p;
3029   const char *s;
3030   size_t n;
3031
3032   n = 0;
3033   for (l = list; l; l = l->next) {
3034     for (s = l->data; *s; s++) {
3035       if (*s == '%')
3036         n += 2;
3037       n++;
3038     }
3039     n++;                        /* delimiter or end of string */
3040   }
3041   n++;                          /* make sure to allocate at least one byte */
3042   pattern = p = mem_calloc (1, n);
3043   for (l = list; l; l = l->next) {
3044     s = l->data;
3045     if (*s) {
3046       if (l != list)
3047         *p++ = ' ';
3048       for (s = l->data; *s; s++) {
3049         if (*s == '%') {
3050           *p++ = '%';
3051           *p++ = '2';
3052           *p++ = '5';
3053         }
3054         else if (*s == '+') {
3055           *p++ = '%';
3056           *p++ = '2';
3057           *p++ = 'B';
3058         }
3059         else if (*s == ' ')
3060           *p++ = '+';
3061         else
3062           *p++ = *s;
3063       }
3064     }
3065   }
3066   *p = 0;
3067   return pattern;
3068 }
3069
3070 /* Return a list of keys which are candidates for the selection.
3071    Select by looking at the HINTS list. */
3072 static crypt_key_t *get_candidates (LIST * hints, unsigned int app,
3073                                     int secret)
3074 {
3075   crypt_key_t *db, *k, **kend;
3076   char *pattern;
3077   gpgme_error_t err;
3078   gpgme_ctx_t ctx;
3079   gpgme_key_t key;
3080   int idx;
3081   gpgme_user_id_t uid = NULL;
3082
3083   pattern = list_to_pattern (hints);
3084   if (!pattern)
3085     return NULL;
3086
3087   err = gpgme_new (&ctx);
3088   if (err) {
3089     mutt_error (_("gpgme_new failed: %s"), gpgme_strerror (err));
3090     mem_free (&pattern);
3091     return NULL;
3092   }
3093
3094   db = NULL;
3095   kend = &db;
3096
3097   if ((app & APPLICATION_PGP)) {
3098     /* Its all a mess.  That old GPGME expects different things
3099        depending on the protocol.  For gpg we don' t need percent
3100        escaped pappert but simple strings passed in an array to the
3101        keylist_ext_start function. */
3102     LIST *l;
3103     size_t n;
3104     char **patarr;
3105
3106     for (l = hints, n = 0; l; l = l->next) {
3107       if (l->data && *l->data)
3108         n++;
3109     }
3110     if (!n)
3111       goto no_pgphints;
3112
3113     patarr = mem_calloc (n + 1, sizeof *patarr);
3114     for (l = hints, n = 0; l; l = l->next) {
3115       if (l->data && *l->data)
3116         patarr[n++] = str_dup (l->data);
3117     }
3118     patarr[n] = NULL;
3119     err = gpgme_op_keylist_ext_start (ctx, (const char **) patarr, secret, 0);
3120     for (n = 0; patarr[n]; n++)
3121       mem_free (&patarr[n]);
3122     mem_free (&patarr);
3123     if (err) {
3124       mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err));
3125       gpgme_release (ctx);
3126       mem_free (&pattern);
3127       return NULL;
3128     }
3129
3130     while (!(err = gpgme_op_keylist_next (ctx, &key))) {
3131       unsigned int flags = 0;
3132
3133       if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3134         flags |= KEYFLAG_CANENCRYPT;
3135       if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3136         flags |= KEYFLAG_CANSIGN;
3137
3138 #if 0                           /* DISABLED code */
3139       if (!flags) {
3140         /* Bug in gpg.  Capabilities are not listed for secret
3141            keys.  Try to deduce them from the algorithm. */
3142
3143         switch (key->subkeys[0].pubkey_algo) {
3144         case GPGME_PK_RSA:
3145           flags |= KEYFLAG_CANENCRYPT;
3146           flags |= KEYFLAG_CANSIGN;
3147           break;
3148         case GPGME_PK_ELG_E:
3149           flags |= KEYFLAG_CANENCRYPT;
3150           break;
3151         case GPGME_PK_DSA:
3152           flags |= KEYFLAG_CANSIGN;
3153           break;
3154         }
3155       }
3156 #endif /* DISABLED code */
3157
3158       for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
3159         k = mem_calloc (1, sizeof *k);
3160         k->kobj = key;
3161         k->idx = idx;
3162         k->uid = uid->uid;
3163         k->flags = flags;
3164         *kend = k;
3165         kend = &k->next;
3166       }
3167     }
3168     if (gpg_err_code (err) != GPG_ERR_EOF)
3169       mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3170     gpgme_op_keylist_end (ctx);
3171   no_pgphints:
3172     ;
3173   }
3174
3175   if ((app & APPLICATION_SMIME)) {
3176     /* and now look for x509 certificates */
3177     gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
3178     err = gpgme_op_keylist_start (ctx, pattern, 0);
3179     if (err) {
3180       mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err));
3181       gpgme_release (ctx);
3182       mem_free (&pattern);
3183       return NULL;
3184     }
3185
3186     while (!(err = gpgme_op_keylist_next (ctx, &key))) {
3187       unsigned int flags = KEYFLAG_ISX509;
3188
3189       if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3190         flags |= KEYFLAG_CANENCRYPT;
3191       if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3192         flags |= KEYFLAG_CANSIGN;
3193
3194       for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
3195         k = mem_calloc (1, sizeof *k);
3196         k->kobj = key;
3197         k->idx = idx;
3198         k->uid = uid->uid;
3199         k->flags = flags;
3200         *kend = k;
3201         kend = &k->next;
3202       }
3203     }
3204     if (gpg_err_code (err) != GPG_ERR_EOF)
3205       mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3206     gpgme_op_keylist_end (ctx);
3207   }
3208
3209   gpgme_release (ctx);
3210   mem_free (&pattern);
3211   return db;
3212 }
3213
3214 /* Add the string STR to the list HINTS.  This list is later used to
3215    match addresses. */
3216 static LIST *crypt_add_string_to_hints (LIST * hints, const char *str)
3217 {
3218   char *scratch;
3219   char *t;
3220
3221   if ((scratch = str_dup (str)) == NULL)
3222     return hints;
3223
3224   for (t = strtok (scratch, " ,.:\"()<>\n"); t;
3225        t = strtok (NULL, " ,.:\"()<>\n")) {
3226     if (str_len (t) > 3)
3227       hints = mutt_add_list (hints, t);
3228   }
3229
3230   mem_free (&scratch);
3231   return hints;
3232 }
3233
3234 /* Display a menu to select a key from the array KEYS. FORCED_VALID
3235    will be set to true on return if the user did override the the
3236    key's validity. */
3237 static crypt_key_t *crypt_select_key (crypt_key_t * keys,
3238                                       ADDRESS * p, const char *s,
3239                                       unsigned int app, int *forced_valid)
3240 {
3241   int keymax;
3242   crypt_key_t **key_table;
3243   MUTTMENU *menu;
3244   int i, done = 0;
3245   char helpstr[SHORT_STRING], buf[LONG_STRING];
3246   crypt_key_t *k;
3247   int (*f) (const void *, const void *);
3248   int menu_to_use = 0;
3249   int unusable = 0;
3250
3251   *forced_valid = 0;
3252
3253   /* build the key table */
3254   keymax = i = 0;
3255   key_table = NULL;
3256   for (k = keys; k; k = k->next) {
3257     if (!option (OPTPGPSHOWUNUSABLE) && (k->flags & KEYFLAG_CANTUSE)) {
3258       unusable = 1;
3259       continue;
3260     }
3261
3262     if (i == keymax) {
3263       keymax += 20;
3264       mem_realloc (&key_table, sizeof (crypt_key_t *) * keymax);
3265     }
3266
3267     key_table[i++] = k;
3268   }
3269
3270   if (!i && unusable) {
3271     mutt_error _("All matching keys are marked expired/revoked.");
3272
3273     mutt_sleep (1);
3274     return NULL;
3275   }
3276
3277   switch (PgpSortKeys & SORT_MASK) {
3278   case SORT_DATE:
3279     f = crypt_compare_date;
3280     break;
3281   case SORT_KEYID:
3282     f = crypt_compare_keyid;
3283     break;
3284   case SORT_ADDRESS:
3285     f = crypt_compare_address;
3286     break;
3287   case SORT_TRUST:
3288   default:
3289     f = crypt_compare_trust;
3290     break;
3291   }
3292   qsort (key_table, i, sizeof (crypt_key_t *), f);
3293
3294   if (app & APPLICATION_PGP)
3295     menu_to_use = MENU_KEY_SELECT_PGP;
3296   else if (app & APPLICATION_SMIME)
3297     menu_to_use = MENU_KEY_SELECT_SMIME;
3298
3299   helpstr[0] = 0;
3300   mutt_make_help (buf, sizeof (buf), _("Exit  "), menu_to_use, OP_EXIT);
3301   strcat (helpstr, buf);        /* __STRCAT_CHECKED__ */
3302   mutt_make_help (buf, sizeof (buf), _("Select  "), menu_to_use,
3303                   OP_GENERIC_SELECT_ENTRY);
3304   strcat (helpstr, buf);        /* __STRCAT_CHECKED__ */
3305   mutt_make_help (buf, sizeof (buf), _("Check key  "),
3306                   menu_to_use, OP_VERIFY_KEY);
3307   strcat (helpstr, buf);        /* __STRCAT_CHECKED__ */
3308   mutt_make_help (buf, sizeof (buf), _("Help"), menu_to_use, OP_HELP);
3309   strcat (helpstr, buf);        /* __STRCAT_CHECKED__ */
3310
3311   menu = mutt_new_menu ();
3312   menu->max = i;
3313   menu->make_entry = crypt_entry;
3314   menu->menu = menu_to_use;
3315   menu->help = helpstr;
3316   menu->data = key_table;
3317
3318   {
3319     const char *ts;
3320
3321     if ((app & APPLICATION_PGP) && (app & APPLICATION_SMIME))
3322       ts = _("PGP and S/MIME keys matching");
3323     else if ((app & APPLICATION_PGP))
3324       ts = _("PGP keys matching");
3325     else if ((app & APPLICATION_SMIME))
3326       ts = _("S/MIME keys matching");
3327     else
3328       ts = _("keys matching");
3329
3330     if (p)
3331       snprintf (buf, sizeof (buf), _("%s <%s>."), ts, p->mailbox);
3332     else
3333       snprintf (buf, sizeof (buf), _("%s \"%s\"."), ts, s);
3334     menu->title = buf;
3335   }
3336
3337   mutt_clear_error ();
3338   k = NULL;
3339   while (!done) {
3340     *forced_valid = 0;
3341     switch (mutt_menuLoop (menu)) {
3342     case OP_VERIFY_KEY:
3343       verify_key (key_table[menu->current]);
3344       menu->redraw = REDRAW_FULL;
3345       break;
3346
3347     case OP_VIEW_ID:
3348       mutt_message ("%s", key_table[menu->current]->uid);
3349       break;
3350
3351     case OP_GENERIC_SELECT_ENTRY:
3352       /* FIXME make error reporting more verbose - this should be
3353          easy because gpgme provides more information */
3354       if (option (OPTPGPCHECKTRUST)) {
3355         if (!crypt_key_is_valid (key_table[menu->current])) {
3356           mutt_error _("This key can't be used: "
3357                        "expired/disabled/revoked.");
3358           break;
3359         }
3360       }
3361
3362       if (option (OPTPGPCHECKTRUST) &&
3363           (!crypt_id_is_valid (key_table[menu->current])
3364            || !crypt_id_is_strong (key_table[menu->current]))) {
3365         const char *warn_s;
3366         char buff[LONG_STRING];
3367
3368         if (key_table[menu->current]->flags & KEYFLAG_CANTUSE)
3369           s = N_("ID is expired/disabled/revoked.");
3370         else {
3371           gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
3372           gpgme_user_id_t uid = NULL;
3373           unsigned int j = 0;
3374
3375           warn_s = "??";
3376
3377           uid = key_table[menu->current]->kobj->uids;
3378           for (j = 0; (j < key_table[menu->current]->idx) && uid;
3379                j++, uid = uid->next);
3380           if (uid)
3381             val = uid->validity;
3382
3383           switch (val) {
3384           case GPGME_VALIDITY_UNKNOWN:
3385           case GPGME_VALIDITY_UNDEFINED:
3386             warn_s = N_("ID has undefined validity.");
3387             break;
3388           case GPGME_VALIDITY_NEVER:
3389             warn_s = N_("ID is not valid.");
3390             break;
3391           case GPGME_VALIDITY_MARGINAL:
3392             warn_s = N_("ID is only marginally valid.");
3393             break;
3394           case GPGME_VALIDITY_FULL:
3395           case GPGME_VALIDITY_ULTIMATE:
3396             break;
3397           }
3398
3399           snprintf (buff, sizeof (buff),
3400                     _("%s Do you really want to use the key?"), _(warn_s));
3401
3402           if (mutt_yesorno (buff, 0) != 1) {
3403             mutt_clear_error ();
3404             break;
3405           }
3406           *forced_valid = 1;
3407         }
3408       }
3409
3410       k = crypt_copy_key (key_table[menu->current]);
3411       done = 1;
3412       break;
3413
3414     case OP_EXIT:
3415       k = NULL;
3416       done = 1;
3417       break;
3418     }
3419   }
3420
3421   mutt_menuDestroy (&menu);
3422   mem_free (&key_table);
3423
3424   set_option (OPTNEEDREDRAW);
3425
3426   return k;
3427 }
3428
3429 static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
3430                                         unsigned int app, int *forced_valid)
3431 {
3432   ADDRESS *r, *p;
3433   LIST *hints = NULL;
3434
3435   int weak = 0;
3436   int invalid = 0;
3437   int multi = 0;
3438   int this_key_has_strong;
3439   int this_key_has_weak;
3440   int this_key_has_invalid;
3441   int match;
3442
3443   crypt_key_t *keys, *k;
3444   crypt_key_t *the_valid_key = NULL;
3445   crypt_key_t *matches = NULL;
3446   crypt_key_t **matches_endp = &matches;
3447
3448   *forced_valid = 0;
3449
3450   if (a && a->mailbox)
3451     hints = crypt_add_string_to_hints (hints, a->mailbox);
3452   if (a && a->personal)
3453     hints = crypt_add_string_to_hints (hints, a->personal);
3454
3455   mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
3456   keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
3457
3458   mutt_free_list (&hints);
3459
3460   if (!keys)
3461     return NULL;
3462
3463   debug_print (5, ("looking for %s <%s>.\n", a->personal, a->mailbox));
3464
3465   for (k = keys; k; k = k->next) {
3466     debug_print (5, ("  looking at key: %s `%.15s'\n", crypt_keyid (k), k->uid));
3467
3468     if (abilities && !(k->flags & abilities)) {
3469       debug_print (5, ("  insufficient abilities: Has %x, want %x\n", k->flags, abilities));
3470       continue;
3471     }
3472
3473     this_key_has_weak = 0;      /* weak but valid match   */
3474     this_key_has_invalid = 0;   /* invalid match          */
3475     this_key_has_strong = 0;    /* strong and valid match */
3476     match = 0;                  /* any match            */
3477
3478     r = rfc822_parse_adrlist (NULL, k->uid);
3479     for (p = r; p; p = p->next) {
3480       int validity = crypt_id_matches_addr (a, p, k);
3481
3482       if (validity & CRYPT_KV_MATCH)    /* something matches */
3483         match = 1;
3484
3485       /* is this key a strong candidate? */
3486       if ((validity & CRYPT_KV_VALID)
3487           && (validity & CRYPT_KV_STRONGID)
3488           && (validity & CRYPT_KV_ADDR)) {
3489         if (the_valid_key && the_valid_key != k)
3490           multi = 1;
3491         the_valid_key = k;
3492         this_key_has_strong = 1;
3493       }
3494       else if ((validity & CRYPT_KV_MATCH)
3495                && !(validity & CRYPT_KV_VALID))
3496         this_key_has_invalid = 1;
3497       else if ((validity & CRYPT_KV_MATCH)
3498                && (!(validity & CRYPT_KV_STRONGID)
3499                    || !(validity & CRYPT_KV_ADDR)))
3500         this_key_has_weak = 1;
3501     }
3502     rfc822_free_address (&r);
3503
3504     if (match) {
3505       crypt_key_t *tmp;
3506
3507       if (!this_key_has_strong && this_key_has_invalid)
3508         invalid = 1;
3509       if (!this_key_has_strong && this_key_has_weak)
3510         weak = 1;
3511
3512       *matches_endp = tmp = crypt_copy_key (k);
3513       matches_endp = &tmp->next;
3514       the_valid_key = tmp;
3515     }
3516   }
3517
3518   crypt_free_key (&keys);
3519
3520   if (matches) {
3521     if (the_valid_key && !multi && !weak
3522         && !(invalid && option (OPTPGPSHOWUNUSABLE))) {
3523       /* 
3524        * There was precisely one strong match on a valid ID, there
3525        * were no valid keys with weak matches, and we aren't
3526        * interested in seeing invalid keys.
3527        * 
3528        * Proceed without asking the user.
3529        */
3530       k = crypt_copy_key (the_valid_key);
3531     }
3532     else {
3533       /* 
3534        * Else: Ask the user.
3535        */
3536       k = crypt_select_key (matches, a, NULL, app, forced_valid);
3537     }
3538     crypt_free_key (&matches);
3539   }
3540   else
3541     k = NULL;
3542
3543   return k;
3544 }
3545
3546
3547 static crypt_key_t *crypt_getkeybystr (char *p, short abilities,
3548                                        unsigned int app, int *forced_valid)
3549 {
3550   LIST *hints = NULL;
3551   crypt_key_t *keys;
3552   crypt_key_t *matches = NULL;
3553   crypt_key_t **matches_endp = &matches;
3554   crypt_key_t *k;
3555   int match;
3556
3557   mutt_message (_("Looking for keys matching \"%s\"..."), p);
3558
3559   *forced_valid = 0;
3560
3561   hints = crypt_add_string_to_hints (hints, p);
3562   keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
3563   mutt_free_list (&hints);
3564
3565   if (!keys)
3566     return NULL;
3567
3568   for (k = keys; k; k = k->next) {
3569     if (abilities && !(k->flags & abilities))
3570       continue;
3571
3572     match = 0;
3573     debug_print (5, ("matching \"%s\" against " "key %s, \"%s\":\n", p, crypt_keyid (k), k->uid));
3574
3575     if (!*p || !str_casecmp (p, crypt_keyid (k))
3576         || (!str_ncasecmp (p, "0x", 2)
3577             && !str_casecmp (p + 2, crypt_keyid (k)))
3578         || (option (OPTPGPLONGIDS)
3579             && !str_ncasecmp (p, "0x", 2)
3580             && !str_casecmp (p + 2, crypt_keyid (k) + 8))
3581         || str_isstr (k->uid, p)) {
3582       crypt_key_t *tmp;
3583
3584       debug_print (5, ("match.\n"));
3585
3586       *matches_endp = tmp = crypt_copy_key (k);
3587       matches_endp = &tmp->next;
3588     }
3589   }
3590
3591   crypt_free_key (&keys);
3592
3593   if (matches) {
3594     k = crypt_select_key (matches, NULL, p, app, forced_valid);
3595     crypt_free_key (&matches);
3596     return k;
3597   }
3598
3599   return NULL;
3600 }
3601
3602 /* Display TAG as a prompt to ask for a key.  If WHATFOR is not null
3603    use it as default and store it under that label as the next
3604    default.  ABILITIES describe the required key abilities (sign,
3605    encrypt) and APP the type of the requested key; ether S/MIME or
3606    PGP.  Return a copy of the key or NULL if not found. */
3607 static crypt_key_t *crypt_ask_for_key (char *tag,
3608                                        char *whatfor,
3609                                        short abilities,
3610                                        unsigned int app, int *forced_valid)
3611 {
3612   crypt_key_t *key;
3613   char resp[SHORT_STRING];
3614   struct crypt_cache *l = NULL;
3615   int dummy;
3616
3617   if (!forced_valid)
3618     forced_valid = &dummy;
3619
3620   mutt_clear_error ();
3621
3622   *forced_valid = 0;
3623   resp[0] = 0;
3624   if (whatfor) {
3625
3626     for (l = id_defaults; l; l = l->next)
3627       if (!str_casecmp (whatfor, l->what)) {
3628         strfcpy (resp, NONULL (l->dflt), sizeof (resp));
3629         break;
3630       }
3631   }
3632
3633
3634   for (;;) {
3635     resp[0] = 0;
3636     if (mutt_get_field (tag, resp, sizeof (resp), M_CLEAR) != 0)
3637       return NULL;
3638
3639     if (whatfor) {
3640       if (l)
3641         str_replace (&l->dflt, resp);
3642       else {
3643         l = mem_malloc (sizeof (struct crypt_cache));
3644         l->next = id_defaults;
3645         id_defaults = l;
3646         l->what = str_dup (whatfor);
3647         l->dflt = str_dup (resp);
3648       }
3649     }
3650
3651     if ((key = crypt_getkeybystr (resp, abilities, app, forced_valid)))
3652       return key;
3653
3654     BEEP ();
3655   }
3656   /* not reached */
3657 }
3658
3659 /* This routine attempts to find the keyids of the recipients of a
3660    message.  It returns NULL if any of the keys can not be found.  */
3661 static char *find_keys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc,
3662                         unsigned int app)
3663 {
3664   char *keyID, *keylist = NULL, *t;
3665   size_t keylist_size = 0;
3666   size_t keylist_used = 0;
3667   ADDRESS *tmp = NULL, *addr = NULL;
3668   ADDRESS **last = &tmp;
3669   ADDRESS *p, *q;
3670   int i;
3671   crypt_key_t *k_info, *key;
3672   const char *fqdn = mutt_fqdn (1);
3673
3674 #if 0
3675   *r_application = APPLICATION_PGP | APPLICATION_SMIME;
3676 #endif
3677
3678   for (i = 0; i < 3; i++) {
3679     switch (i) {
3680     case 0:
3681       p = to;
3682       break;
3683     case 1:
3684       p = cc;
3685       break;
3686     case 2:
3687       p = bcc;
3688       break;
3689     default:
3690       abort ();
3691     }
3692
3693     *last = rfc822_cpy_adr (p);
3694     while (*last)
3695       last = &((*last)->next);
3696   }
3697
3698   if (fqdn)
3699     rfc822_qualify (tmp, fqdn);
3700
3701   tmp = mutt_remove_duplicates (tmp);
3702
3703   for (p = tmp; p; p = p->next) {
3704     char buf[LONG_STRING];
3705     int forced_valid = 0;
3706
3707     q = p;
3708     k_info = NULL;
3709
3710     if ((keyID = mutt_crypt_hook (p)) != NULL) {
3711       int r;
3712
3713       snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"),
3714                 keyID, p->mailbox);
3715       if ((r = mutt_yesorno (buf, M_YES)) == M_YES) {
3716         /* check for e-mail address */
3717         if ((t = strchr (keyID, '@')) &&
3718             (addr = rfc822_parse_adrlist (NULL, keyID))) {
3719           if (fqdn)
3720             rfc822_qualify (addr, fqdn);
3721           q = addr;
3722         }
3723         else {
3724 #if 0
3725           k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
3726                                       *r_application, &forced_valid);
3727 #else
3728           k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
3729                                       app, &forced_valid);
3730 #endif
3731         }
3732       }
3733       else if (r == -1) {
3734         mem_free (&keylist);
3735         rfc822_free_address (&tmp);
3736         rfc822_free_address (&addr);
3737         return NULL;
3738       }
3739     }
3740
3741     if (k_info == NULL
3742         && (k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT,
3743                                          app, &forced_valid)) == NULL) {
3744       snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
3745
3746       if ((key = crypt_ask_for_key (buf, q->mailbox, KEYFLAG_CANENCRYPT,
3747 #if 0
3748                                     *r_application,
3749 #else
3750                                     app,
3751 #endif
3752                                     &forced_valid)) == NULL) {
3753         mem_free (&keylist);
3754         rfc822_free_address (&tmp);
3755         rfc822_free_address (&addr);
3756         return NULL;
3757       }
3758     }
3759     else
3760       key = k_info;
3761
3762     {
3763       const char *s = crypt_fpr (key);
3764
3765 #if 0
3766       if (key->flags & KEYFLAG_ISX509)
3767         *r_application &= ~APPLICATION_PGP;
3768       if (!(key->flags & KEYFLAG_ISX509))
3769         *r_application &= ~APPLICATION_SMIME;
3770 #endif
3771
3772       keylist_size += str_len (s) + 4 + 1;
3773       mem_realloc (&keylist, keylist_size);
3774       sprintf (keylist + keylist_used, "%s0x%s%s",      /* __SPRINTF_CHECKED__ */
3775                keylist_used ? " " : "", s, forced_valid ? "!" : "");
3776     }
3777     keylist_used = str_len (keylist);
3778
3779     crypt_free_key (&key);
3780     rfc822_free_address (&addr);
3781   }
3782   rfc822_free_address (&tmp);
3783   return (keylist);
3784 }
3785
3786 char *pgp_gpgme_findkeys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc)
3787 {
3788   return find_keys (to, cc, bcc, APPLICATION_PGP);
3789 }
3790
3791 char *smime_gpgme_findkeys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc)
3792 {
3793   return find_keys (to, cc, bcc, APPLICATION_SMIME);
3794 }
3795
3796 /*
3797  * Implementation of `init'.
3798  */
3799
3800 /* Initialization.  */
3801 static void init_gpgme (void)
3802 {
3803   /* Make sure that gpg-agent is running.  */
3804   if (!getenv ("GPG_AGENT_INFO")) {
3805     mutt_error ("\nUsing GPGME backend, although no gpg-agent is running");
3806     if (mutt_any_key_to_continue (NULL) == -1)
3807       mutt_exit (1);
3808   }
3809 }
3810
3811 void pgp_gpgme_init (void)
3812 {
3813   init_gpgme ();
3814 }
3815
3816 void smime_gpgme_init (void)
3817 {
3818 }
3819
3820 static int gpgme_send_menu (HEADER * msg, int *redraw, int is_smime)
3821 {
3822   crypt_key_t *p;
3823   char input_signas[SHORT_STRING];
3824   int choice;
3825
3826   if (msg->security & APPLICATION_PGP)
3827     is_smime = 0;
3828   else if (msg->security & APPLICATION_SMIME)
3829     is_smime = 1;
3830
3831   if (is_smime)
3832     choice =
3833       mutt_multi_choice (_
3834                          ("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?"),
3835                          _("esabpfc"));
3836   else
3837     choice =
3838       mutt_multi_choice (_
3839                          ("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?"),
3840                          _("esabmfc"));
3841
3842   switch (choice) {
3843   case 1:                      /* (e)ncrypt */
3844     msg->security |= (is_smime ? SMIMEENCRYPT : PGPENCRYPT);
3845     msg->security &= ~(is_smime ? SMIMESIGN : PGPSIGN);
3846     break;
3847
3848   case 2:                      /* (s)ign */
3849     msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
3850     msg->security &= ~(is_smime ? SMIMEENCRYPT : PGPENCRYPT);
3851     break;
3852
3853   case 3:                      /* sign (a)s */
3854 /*      unset_option(OPTCRYPTCHECKTRUST); */
3855     if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
3856                                 is_smime ? APPLICATION_SMIME :
3857                                 APPLICATION_PGP, NULL))) {
3858       snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p));
3859       str_replace (is_smime ? &SmimeDefaultKey : &PgpSignAs,
3860                         input_signas);
3861       crypt_free_key (&p);
3862
3863       msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
3864     }
3865 #if 0
3866     else {
3867       msg->security &= (is_smime ? ~SMIMESIGN : ~PGPSIGN);
3868     }
3869 #endif
3870     *redraw = REDRAW_FULL;
3871     break;
3872
3873   case 4:                      /* (b)oth */
3874     msg->security =
3875       (is_smime ? (SMIMEENCRYPT | SMIMESIGN) : (PGPENCRYPT | PGPSIGN));
3876     break;
3877
3878   case 5:                      /* (p)gp or s/(m)ime */
3879     is_smime = !is_smime;
3880     break;
3881
3882   case 6:                      /* (c)lear */
3883     msg->security = 0;
3884     break;
3885   }
3886
3887   if (choice == 6 || choice == 7);
3888   else if (is_smime) {
3889     msg->security &= ~APPLICATION_PGP;
3890     msg->security |= APPLICATION_SMIME;
3891   }
3892   else {
3893     msg->security &= ~APPLICATION_SMIME;
3894     msg->security |= APPLICATION_PGP;
3895   }
3896
3897   return (msg->security);
3898 }
3899
3900 int pgp_gpgme_send_menu (HEADER * msg, int *redraw)
3901 {
3902   return gpgme_send_menu (msg, redraw, 0);
3903 }
3904
3905 int smime_gpgme_send_menu (HEADER * msg, int *redraw)
3906 {
3907   return gpgme_send_menu (msg, redraw, 1);
3908 }
3909
3910 static int verify_sender (HEADER * h, gpgme_protocol_t protocol)
3911 {
3912   ADDRESS *sender = NULL;
3913   unsigned int ret = 1;
3914
3915   if (h->env->from) {
3916     h->env->from = mutt_expand_aliases (h->env->from);
3917     sender = h->env->from;
3918   }
3919   else if (h->env->sender) {
3920     h->env->sender = mutt_expand_aliases (h->env->sender);
3921     sender = h->env->sender;
3922   }
3923
3924   if (sender) {
3925     if (signature_key) {
3926       gpgme_key_t key = signature_key;
3927       gpgme_user_id_t uid = NULL;
3928       int sender_length = 0;
3929       int uid_length = 0;
3930
3931       sender_length = str_len (sender->mailbox);
3932       for (uid = key->uids; uid && ret; uid = uid->next) {
3933         uid_length = str_len (uid->email);
3934         if (1 && (uid->email[0] == '<')
3935             && (uid->email[uid_length - 1] == '>')
3936             && (uid_length == sender_length + 2)
3937             && (!strncmp (uid->email + 1, sender->mailbox, sender_length)))
3938           ret = 0;
3939       }
3940     }
3941     else
3942       mutt_any_key_to_continue ("Failed to verify sender");
3943   }
3944   else
3945     mutt_any_key_to_continue ("Failed to figure out sender");
3946
3947   if (signature_key) {
3948     gpgme_key_release (signature_key);
3949     signature_key = NULL;
3950   }
3951
3952   return ret;
3953 }
3954
3955 int smime_gpgme_verify_sender (HEADER * h)
3956 {
3957   return verify_sender (h, GPGME_PROTOCOL_CMS);
3958 }
3959
3960 #endif