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