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