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