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