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