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