continue the include dance
[apps/madmutt.git] / lib-crypt / crypt-gpgme.c
1 /*
2  * Copyright notice from original mutt:
3  * crypt-gpgme.c - GPGME based crypto operations
4  * Copyright (C) 1996,1997 Michael R. Elkins <me@cs.hmc.edu>
5  * Copyright (C) 1998,1999,2000 Thomas Roessler <roessler@guug.de>
6  * Copyright (C) 2001  Thomas Roessler <roessler@guug.de>
7  *                     Oliver Ehli <elmy@acm.org>
8  * Copyright (C) 2002, 2003, 2004 g10 Code GmbH
9  *
10  * This file is part of mutt-ng, see http://www.muttng.org/.
11  * It's licensed under the GNU General Public License,
12  * please see the file GPL in the top level source directory.
13  */
14
15 #if HAVE_CONFIG_H
16 # include "config.h"
17 #endif
18
19 #ifdef CRYPT_BACKEND_GPGME
20
21 #include <sys/wait.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/stat.h>
26 #include <errno.h>
27 #include <ctype.h>
28
29 #ifdef HAVE_LOCALE_H
30 #  include <locale.h>
31 #endif
32 #ifdef HAVE_LANGINFO_D_T_FMT
33 #  include <langinfo.h>
34 #endif
35 #ifdef HAVE_SYS_TIME_H
36 #  include <sys/time.h>
37 #endif
38 #ifdef HAVE_SYS_RESOURCE_H
39 #  include <sys/resource.h>
40 #endif
41
42 #include <gpgme.h>
43
44 #include <lib-lib/mem.h>
45 #include <lib-lib/str.h>
46 #include <lib-lib/ascii.h>
47 #include <lib-lib/macros.h>
48 #include <lib-lib/file.h>
49 #include <lib-lib/debug.h>
50
51 #include <lib-mime/mime.h>
52
53 #include <lib-ui/curses.h>
54 #include <lib-ui/enter.h>
55 #include <lib-ui/menu.h>
56
57 #include "mutt.h"
58 #include "lib.h"
59 #include "alias.h"
60 #include <lib-crypt/crypt.h>
61 #include "handler.h"
62 #include "copy.h"
63 #include "pager.h"
64 #include "recvattach.h"
65 #include "sort.h"
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   ssize_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, ssize_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   int is_strong = 0;
256   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   ssize_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 < ssizeof(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, ssize_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     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     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 sig;
1287
1288     result = gpgme_op_verify_result (ctx);
1289     if (result) {
1290       for (sig = result->signatures; sig; sig = sig->next) {
1291         if (sig->notations) {
1292           state_attach_puts ("*** Begin Notation (signature by: ", s);
1293           state_attach_puts (sig->fpr, s);
1294           state_attach_puts (") ***\n", s);
1295           for (notation = sig->notations; notation; notation = notation->next)
1296           {
1297             if (notation->name) {
1298               state_attach_puts (notation->name, s);
1299               state_attach_puts ("=", s);
1300             }
1301             if (notation->value) {
1302               state_attach_puts (notation->value, s);
1303               if (!(*notation->value
1304                     && (notation->value[m_strlen(notation->value) - 1] ==
1305                         '\n')))
1306                 state_attach_puts ("\n", s);
1307             }
1308           }
1309           state_attach_puts ("*** End Notation ***\n", s);
1310         }
1311       }
1312     }
1313   }
1314
1315   gpgme_release (ctx);
1316
1317   state_attach_puts (_("[-- End signature information --]\n\n"), s);
1318   debug_print (1, ("returning %d.\n", badsig));
1319
1320   return badsig ? 1 : anywarn ? 2 : 0;
1321 }
1322
1323 int pgp_gpgme_verify_one (BODY * sigbdy, STATE * s, const char *tempfile)
1324 {
1325   return verify_one (sigbdy, s, tempfile, 0);
1326 }
1327
1328 int smime_gpgme_verify_one (BODY * sigbdy, STATE * s, const char *tempfile)
1329 {
1330   return verify_one (sigbdy, s, tempfile, 1);
1331 }
1332
1333 /*
1334  * Implementation of `decrypt_part'.
1335  */
1336
1337 /* Decrypt a PGP or SMIME message (depending on the boolean flag
1338    IS_SMIME) with body A described further by state S.  Write
1339    plaintext out to file FPOUT and return a new body.  For PGP returns
1340    a flag in R_IS_SIGNED to indicate whether this is a combined
1341    encrypted and signed message, for S/MIME it returns true when it is
1342    not a encrypted but a signed message.  */
1343 static BODY *decrypt_part (BODY * a, STATE * s, FILE * fpout, int is_smime,
1344                            int *r_is_signed)
1345 {
1346   struct stat info;
1347   BODY *tattach;
1348   int err = 0;
1349   gpgme_ctx_t ctx;
1350   gpgme_data_t ciphertext, plaintext;
1351   int maybe_signed = 0;
1352   int anywarn = 0;
1353   int sig_stat = 0;
1354
1355   if (r_is_signed)
1356     *r_is_signed = 0;
1357
1358   ctx = create_gpgme_context (is_smime);
1359
1360 restart:
1361   /* Make a data object from the body, create context etc. */
1362   ciphertext = file_to_data_object (s->fpin, a->offset, a->length);
1363   if (!ciphertext)
1364     return NULL;
1365   plaintext = create_gpgme_data ();
1366
1367   /* Do the decryption or the verification in case of the S/MIME hack. */
1368   if ((!is_smime) || maybe_signed) {
1369     if (!is_smime)
1370       err = gpgme_op_decrypt_verify (ctx, ciphertext, plaintext);
1371     else if (maybe_signed)
1372       err = gpgme_op_verify (ctx, ciphertext, NULL, plaintext);
1373
1374     {
1375       /* Check wether signatures have been verified.  */
1376       gpgme_verify_result_t verify_result = gpgme_op_verify_result (ctx);
1377
1378       if (verify_result->signatures)
1379         sig_stat = 1;
1380     }
1381   }
1382   else
1383     err = gpgme_op_decrypt (ctx, ciphertext, plaintext);
1384   gpgme_data_release (ciphertext);
1385   if (err) {
1386     if (is_smime && !maybe_signed && gpg_err_code (err) == GPG_ERR_NO_DATA) {
1387       /* Check whether this might be a signed message despite what
1388          the mime header told us.  Retry then.  gpgsm returns the
1389          error information "unsupported Algorithm '?'" but gpgme
1390          will not store this unknown algorithm, thus we test that
1391          it has not been set. */
1392       gpgme_decrypt_result_t result;
1393
1394       result = gpgme_op_decrypt_result (ctx);
1395       if (!result->unsupported_algorithm) {
1396         maybe_signed = 1;
1397         gpgme_data_release (plaintext);
1398         goto restart;
1399       }
1400     }
1401     mutt_need_hard_redraw ();
1402     if ((s->flags & M_DISPLAY)) {
1403       char buf[200];
1404
1405       snprintf (buf, sizeof (buf) - 1,
1406                 _("[-- Error: decryption failed: %s --]\n\n"),
1407                 gpgme_strerror (err));
1408       state_attach_puts (buf, s);
1409     }
1410     gpgme_data_release (plaintext);
1411     gpgme_release (ctx);
1412     return NULL;
1413   }
1414   mutt_need_hard_redraw ();
1415
1416   /* Read the output from GPGME, and make sure to change CRLF to LF,
1417      otherwise read_mime_header has a hard time parsing the message.  */
1418   if (data_object_to_stream (plaintext, fpout)) {
1419     gpgme_data_release (plaintext);
1420     gpgme_release (ctx);
1421     return NULL;
1422   }
1423   gpgme_data_release (plaintext);
1424
1425   a->is_signed_data = 0;
1426   if (sig_stat) {
1427     int res, idx;
1428     int anybad = 0;
1429
1430     if (maybe_signed)
1431       a->is_signed_data = 1;
1432     if (r_is_signed)
1433       *r_is_signed = -1;        /* A signature exists. */
1434
1435     if ((s->flags & M_DISPLAY))
1436       state_attach_puts (_("[-- Begin signature " "information --]\n"), s);
1437     for (idx = 0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) {
1438       if (res == 1)
1439         anybad = 1;
1440       else if (res == 2)
1441         anywarn = 1;
1442     }
1443     if (!anybad && idx && r_is_signed && *r_is_signed)
1444       *r_is_signed = anywarn ? 2 : 1;   /* Good signature. */
1445
1446     if ((s->flags & M_DISPLAY))
1447       state_attach_puts (_("[-- End signature " "information --]\n\n"), s);
1448   }
1449   gpgme_release (ctx);
1450   ctx = NULL;
1451
1452   fflush (fpout);
1453   rewind (fpout);
1454   tattach = mutt_read_mime_header (fpout, 0);
1455   if (tattach) {
1456     /*
1457      * Need to set the length of this body part.
1458      */
1459     fstat (fileno (fpout), &info);
1460     tattach->length = info.st_size - tattach->offset;
1461
1462     tattach->warnsig = anywarn;
1463
1464     /* See if we need to recurse on this MIME part.  */
1465     mutt_parse_part (fpout, tattach);
1466   }
1467
1468   return tattach;
1469 }
1470
1471 /* Decrypt a PGP/MIME message in FPIN and B and return a new body and
1472    the stream in CUR and FPOUT.  Returns 0 on success. */
1473 int pgp_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur)
1474 {
1475   char tempfile[_POSIX_PATH_MAX];
1476   STATE s;
1477   BODY *first_part = b;
1478   int is_signed;
1479
1480   first_part->goodsig = 0;
1481   first_part->warnsig = 0;
1482
1483   if (!mutt_is_multipart_encrypted (b))
1484     return -1;
1485
1486   if (!b->parts || !b->parts->next)
1487     return -1;
1488
1489   b = b->parts->next;
1490
1491   p_clear(&s, 1);
1492   s.fpin = fpin;
1493   mutt_mktemp (tempfile);
1494   if (!(*fpout = safe_fopen (tempfile, "w+"))) {
1495     mutt_perror (tempfile);
1496     return -1;
1497   }
1498   unlink (tempfile);
1499
1500   *cur = decrypt_part (b, &s, *fpout, 0, &is_signed);
1501   rewind (*fpout);
1502   if (is_signed > 0)
1503     first_part->goodsig = 1;
1504
1505   return *cur ? 0 : -1;
1506 }
1507
1508
1509 /* Decrypt a S/MIME message in FPIN and B and return a new body and
1510    the stream in CUR and FPOUT.  Returns 0 on success. */
1511 int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b,
1512                               BODY ** cur)
1513 {
1514   char tempfile[_POSIX_PATH_MAX];
1515   STATE s;
1516   FILE *tmpfp = NULL;
1517   int is_signed;
1518   long saved_b_offset;
1519   ssize_t saved_b_length;
1520   int saved_b_type;
1521
1522   if (!mutt_is_application_smime (b))
1523     return -1;
1524
1525   if (b->parts)
1526     return -1;
1527
1528   /* Decode the body - we need to pass binary CMS to the
1529      backend.  The backend allows for Base64 encoded data but it does
1530      not allow for QP which I have seen in some messages.  So better
1531      do it here. */
1532   saved_b_type = b->type;
1533   saved_b_offset = b->offset;
1534   saved_b_length = b->length;
1535   p_clear(&s, 1);
1536   s.fpin = fpin;
1537   fseeko (s.fpin, b->offset, 0);
1538   mutt_mktemp (tempfile);
1539   if (!(tmpfp = safe_fopen (tempfile, "w+"))) {
1540     mutt_perror (tempfile);
1541     return -1;
1542   }
1543   mutt_unlink (tempfile);
1544
1545   s.fpout = tmpfp;
1546   mutt_decode_attachment (b, &s);
1547   fflush (tmpfp);
1548   b->length = ftello (s.fpout);
1549   b->offset = 0;
1550   rewind (tmpfp);
1551
1552   p_clear(&s, 1);
1553   s.fpin = tmpfp;
1554   s.fpout = 0;
1555   mutt_mktemp (tempfile);
1556   if (!(*fpout = safe_fopen (tempfile, "w+"))) {
1557     mutt_perror (tempfile);
1558     return -1;
1559   }
1560   mutt_unlink (tempfile);
1561
1562   *cur = decrypt_part (b, &s, *fpout, 1, &is_signed);
1563   if (*cur)
1564     (*cur)->goodsig = is_signed > 0;
1565   b->type = saved_b_type;
1566   b->length = saved_b_length;
1567   b->offset = saved_b_offset;
1568   fclose (tmpfp);
1569   rewind (*fpout);
1570   if (*cur && !is_signed && !(*cur)->parts
1571       && mutt_is_application_smime (*cur)) {
1572     /* Assume that this is a opaque signed s/mime message.  This is
1573        an ugly way of doing it but we have anyway a problem with
1574        arbitrary encoded S/MIME messages: Only the outer part may be
1575        encrypted.  The entire mime parsing should be revamped,
1576        probably by keeping the temportary files so that we don't
1577        need to decrypt them all the time.  Inner parts of an
1578        encrypted part can then pint into this file and tehre won't
1579        never be a need to decrypt again.  This needs a partial
1580        rewrite of the MIME engine. */
1581     BODY *bb = *cur;
1582     BODY *tmp_b;
1583
1584     saved_b_type = bb->type;
1585     saved_b_offset = bb->offset;
1586     saved_b_length = bb->length;
1587     p_clear(&s, 1);
1588     s.fpin = *fpout;
1589     fseeko (s.fpin, bb->offset, 0);
1590     mutt_mktemp (tempfile);
1591     if (!(tmpfp = safe_fopen (tempfile, "w+"))) {
1592       mutt_perror (tempfile);
1593       return -1;
1594     }
1595     mutt_unlink (tempfile);
1596
1597     s.fpout = tmpfp;
1598     mutt_decode_attachment (bb, &s);
1599     fflush (tmpfp);
1600     bb->length = ftello (s.fpout);
1601     bb->offset = 0;
1602     rewind (tmpfp);
1603     fclose (*fpout);
1604
1605     p_clear(&s, 1);
1606     s.fpin = tmpfp;
1607     s.fpout = 0;
1608     mutt_mktemp (tempfile);
1609     if (!(*fpout = safe_fopen (tempfile, "w+"))) {
1610       mutt_perror (tempfile);
1611       return -1;
1612     }
1613     mutt_unlink (tempfile);
1614
1615     tmp_b = decrypt_part (bb, &s, *fpout, 1, &is_signed);
1616     if (tmp_b)
1617       tmp_b->goodsig = is_signed > 0;
1618     bb->type = saved_b_type;
1619     bb->length = saved_b_length;
1620     bb->offset = saved_b_offset;
1621     fclose (tmpfp);
1622     rewind (*fpout);
1623     mutt_free_body (cur);
1624     *cur = tmp_b;
1625   }
1626   return *cur ? 0 : -1;
1627 }
1628
1629
1630 /* 
1631  * Implementation of `pgp_check_traditional'.
1632  */
1633
1634 static int pgp_check_traditional_one_body (FILE * fp, BODY * b,
1635                                            int tagged_only)
1636 {
1637   char tempfile[_POSIX_PATH_MAX];
1638   char buf[HUGE_STRING];
1639   FILE *tfp;
1640
1641   short sgn = 0;
1642   short enc = 0;
1643
1644   if (b->type != TYPETEXT)
1645     return 0;
1646
1647   if (tagged_only && !b->tagged)
1648     return 0;
1649
1650   mutt_mktemp (tempfile);
1651   if (mutt_decode_save_attachment (fp, b, tempfile, 0, 0) != 0) {
1652     unlink (tempfile);
1653     return 0;
1654   }
1655
1656   if ((tfp = fopen (tempfile, "r")) == NULL) {
1657     unlink (tempfile);
1658     return 0;
1659   }
1660
1661   while (fgets (buf, sizeof (buf), tfp)) {
1662     if (!m_strncmp("-----BEGIN PGP ", buf, 15)) {
1663       if (!m_strcmp("MESSAGE-----\n", buf + 15))
1664         enc = 1;
1665       else if (!m_strcmp("SIGNED MESSAGE-----\n", buf + 15))
1666         sgn = 1;
1667     }
1668   }
1669   safe_fclose (&tfp);
1670   unlink (tempfile);
1671
1672   if (!enc && !sgn)
1673     return 0;
1674
1675   /* fix the content type */
1676
1677   mutt_set_parameter ("format", "fixed", &b->parameter);
1678   mutt_set_parameter ("x-action", enc ? "pgp-encrypted" : "pgp-signed",
1679                       &b->parameter);
1680
1681   return 1;
1682 }
1683
1684 int pgp_gpgme_check_traditional (FILE * fp, BODY * b, int tagged_only)
1685 {
1686   int rv = 0;
1687   int r;
1688
1689   for (; b; b = b->next) {
1690     if (is_multipart (b))
1691       rv = (pgp_gpgme_check_traditional (fp, b->parts, tagged_only) || rv);
1692     else if (b->type == TYPETEXT) {
1693       if ((r = mutt_is_application_pgp (b)))
1694         rv = (rv || r);
1695       else
1696         rv = (pgp_check_traditional_one_body (fp, b, tagged_only) || rv);
1697     }
1698   }
1699   return rv;
1700 }
1701
1702
1703 /* 
1704  * Implementation of `application_handler'.
1705  */
1706
1707 /* 
1708   Copy a clearsigned message, and strip the signature and PGP's
1709   dash-escaping.
1710   
1711   XXX - charset handling: We assume that it is safe to do
1712   character set decoding first, dash decoding second here, while
1713   we do it the other way around in the main handler.
1714   
1715   (Note that we aren't worse than Outlook & Cie in this, and also
1716   note that we can successfully handle anything produced by any
1717   existing versions of mutt.)  */
1718
1719 static void copy_clearsigned (gpgme_data_t data, STATE * s, char *charset)
1720 {
1721   char buf[HUGE_STRING];
1722   short complete, armor_header;
1723   FGETCONV *fc;
1724   char *fname;
1725   FILE *fp;
1726
1727   fname = data_object_to_tempfile (data, &fp);
1728   if (!fname)
1729     return;
1730   unlink (fname);
1731   p_delete(&fname);
1732
1733   fc = fgetconv_open (fp, charset, Charset, M_ICONV_HOOK_FROM);
1734
1735   for (complete = 1, armor_header = 1;
1736        fgetconvs (buf, sizeof (buf), fc) != NULL;
1737        complete = strchr (buf, '\n') != NULL) {
1738     if (!complete) {
1739       if (!armor_header)
1740         state_puts (buf, s);
1741       continue;
1742     }
1743
1744     if (!m_strcmp(buf, "-----BEGIN PGP SIGNATURE-----\n"))
1745       break;
1746
1747     if (armor_header) {
1748       if (buf[0] == '\n')
1749         armor_header = 0;
1750       continue;
1751     }
1752
1753     if (s->prefix)
1754       state_puts (s->prefix, s);
1755
1756     if (buf[0] == '-' && buf[1] == ' ')
1757       state_puts (buf + 2, s);
1758     else
1759       state_puts (buf, s);
1760   }
1761
1762   fgetconv_close (&fc);
1763   fclose (fp);
1764 }
1765
1766
1767 /* Support for classic_application/pgp */
1768 int pgp_gpgme_application_handler (BODY * m, STATE * s)
1769 {
1770   int needpass = -1, pgp_keyblock = 0;
1771   int clearsign = 0;
1772   long start_pos = 0;
1773   long bytes;
1774   off_t last_pos, offset;
1775   char buf[HUGE_STRING];
1776   FILE *pgpout = NULL;
1777
1778   gpgme_error_t err = 0;
1779   gpgme_data_t armored_data = NULL;
1780
1781   short maybe_goodsig = 1;
1782   short have_any_sigs = 0;
1783
1784   char body_charset[STRING];    /* Only used for clearsigned messages. */
1785
1786   debug_print (2, ("Entering pgp_application_pgp handler\n"));
1787
1788   /* For clearsigned messages we won't be able to get a character set
1789      but we know that this may only be text thus we assume Latin-1
1790      here. */
1791   if (!mutt_get_body_charset (body_charset, sizeof (body_charset), m))
1792     m_strcpy(body_charset, sizeof(body_charset), "iso-8859-1");
1793
1794   fseeko (s->fpin, m->offset, 0);
1795   last_pos = m->offset;
1796
1797   for (bytes = m->length; bytes > 0;) {
1798     if (fgets (buf, sizeof (buf), s->fpin) == NULL)
1799       break;
1800
1801     offset = ftello (s->fpin);
1802     bytes -= (offset - last_pos);       /* don't rely on m_strlen(buf) */
1803     last_pos = offset;
1804
1805     if (!m_strncmp("-----BEGIN PGP ", buf, 15)) {
1806       clearsign = 0;
1807       start_pos = last_pos;
1808
1809       if (!m_strcmp("MESSAGE-----\n", buf + 15))
1810         needpass = 1;
1811       else if (!m_strcmp("SIGNED MESSAGE-----\n", buf + 15)) {
1812         clearsign = 1;
1813         needpass = 0;
1814       }
1815       else if (!option (OPTDONTHANDLEPGPKEYS) &&
1816                !m_strcmp("PUBLIC KEY BLOCK-----\n", buf + 15)) {
1817         needpass = 0;
1818         pgp_keyblock = 1;
1819       }
1820       else {
1821         /* XXX - we may wish to recode here */
1822         if (s->prefix)
1823           state_puts (s->prefix, s);
1824         state_puts (buf, s);
1825         continue;
1826       }
1827
1828       have_any_sigs = (have_any_sigs || (clearsign && (s->flags & M_VERIFY)));
1829
1830       /* Copy PGP material to an data container */
1831       armored_data = create_gpgme_data ();
1832       gpgme_data_write (armored_data, buf, m_strlen(buf));
1833       while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL) {
1834         offset = ftello (s->fpin);
1835         bytes -= (offset - last_pos);   /* don't rely on m_strlen(buf) */
1836         last_pos = offset;
1837
1838         gpgme_data_write (armored_data, buf, m_strlen(buf));
1839
1840         if ((needpass && !m_strcmp("-----END PGP MESSAGE-----\n", buf))
1841             || (!needpass
1842                 && (!m_strcmp("-----END PGP SIGNATURE-----\n", buf)
1843                     || !m_strcmp("-----END PGP PUBLIC KEY BLOCK-----\n",
1844                                      buf))))
1845           break;
1846       }
1847
1848       /* Invoke PGP if needed */
1849       if (!clearsign || (s->flags & M_VERIFY)) {
1850         unsigned int sig_stat = 0;
1851         gpgme_data_t plaintext;
1852         gpgme_ctx_t ctx;
1853
1854         plaintext = create_gpgme_data ();
1855         ctx = create_gpgme_context (0);
1856
1857         if (clearsign)
1858           err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);
1859         else {
1860           err = gpgme_op_decrypt_verify (ctx, armored_data, plaintext);
1861           if (gpg_err_code (err) == GPG_ERR_NO_DATA) {
1862             /* Decrypt verify can't handle signed only messages. */
1863             err = (gpgme_data_seek (armored_data, 0, SEEK_SET) == -1)
1864               ? gpgme_error_from_errno (errno) : 0;
1865             /* Must release plaintext so that we supply an
1866                uninitialized object. */
1867             gpgme_data_release (plaintext);
1868             plaintext = create_gpgme_data ();
1869             err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);
1870           }
1871         }
1872
1873         if (err) {
1874           char errbuf[200];
1875
1876           snprintf (errbuf, sizeof (errbuf) - 1,
1877                     _("Error: decryption/verification failed: %s\n"),
1878                     gpgme_strerror (err));
1879           state_attach_puts (errbuf, s);
1880         }
1881         else {                  /* Decryption/Verification succeeded */
1882           char *tmpfname;
1883
1884           {
1885             /* Check wether signatures have been verified.  */
1886             gpgme_verify_result_t verify_result;
1887
1888             verify_result = gpgme_op_verify_result (ctx);
1889             if (verify_result->signatures)
1890               sig_stat = 1;
1891           }
1892
1893           have_any_sigs = 0;
1894           maybe_goodsig = 0;
1895           if ((s->flags & M_DISPLAY) && sig_stat) {
1896             int res, idx;
1897             int anybad = 0;
1898             int anywarn = 0;
1899
1900             state_attach_puts (_("[-- Begin signature "
1901                                  "information --]\n"), s);
1902             have_any_sigs = 1;
1903             for (idx = 0;
1904                  (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) {
1905               if (res == 1)
1906                 anybad = 1;
1907               else if (res == 2)
1908                 anywarn = 1;
1909             }
1910             if (!anybad && idx)
1911               maybe_goodsig = 1;
1912
1913             state_attach_puts (_("[-- End signature "
1914                                  "information --]\n\n"), s);
1915           }
1916
1917           tmpfname = data_object_to_tempfile (plaintext, &pgpout);
1918           if (!tmpfname) {
1919             pgpout = NULL;
1920             state_attach_puts (_("Error: copy data failed\n"), s);
1921           }
1922           else {
1923             unlink (tmpfname);
1924             p_delete(&tmpfname);
1925           }
1926         }
1927         gpgme_release (ctx);
1928       }
1929
1930       /*
1931        * Now, copy cleartext to the screen.  NOTE - we expect that PGP
1932        * outputs utf-8 cleartext.  This may not always be true, but it 
1933        * seems to be a reasonable guess.
1934        */
1935
1936       if (s->flags & M_DISPLAY) {
1937         if (needpass)
1938           state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s);
1939         else if (pgp_keyblock)
1940           state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"), s);
1941         else
1942           state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"), s);
1943       }
1944
1945       if (clearsign) {
1946         copy_clearsigned (armored_data, s, body_charset);
1947       }
1948       else if (pgpout) {
1949         FGETCONV *fc;
1950         int c;
1951
1952         rewind (pgpout);
1953         fc = fgetconv_open (pgpout, "utf-8", Charset, 0);
1954         while ((c = fgetconv (fc)) != EOF) {
1955           state_putc (c, s);
1956           if (c == '\n' && s->prefix)
1957             state_puts (s->prefix, s);
1958         }
1959         fgetconv_close (&fc);
1960       }
1961
1962       if (s->flags & M_DISPLAY) {
1963         state_putc ('\n', s);
1964         if (needpass)
1965           state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
1966         else if (pgp_keyblock)
1967           state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);
1968         else
1969           state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);
1970       }
1971
1972       if (pgpout) {
1973         safe_fclose (&pgpout);
1974       }
1975     }
1976     else {
1977       /* XXX - we may wish to recode here */
1978       if (s->prefix)
1979         state_puts (s->prefix, s);
1980       state_puts (buf, s);
1981     }
1982   }
1983
1984   m->goodsig = (maybe_goodsig && have_any_sigs);
1985
1986   if (needpass == -1) {
1987     state_attach_puts (_("[-- Error: could not find beginning"
1988                          " of PGP message! --]\n\n"), s);
1989     return (-1);
1990   }
1991   debug_print (2, ("Leaving pgp_application_pgp handler\n"));
1992   return (err);
1993 }
1994
1995 /* 
1996  * Implementation of `encrypted_handler'.
1997  */
1998
1999 /* MIME handler for pgp/mime encrypted messages. */
2000 int pgp_gpgme_encrypted_handler (BODY * a, STATE * s)
2001 {
2002   char tempfile[_POSIX_PATH_MAX];
2003   FILE *fpout;
2004   BODY *tattach;
2005   BODY *orig_body = a;
2006   int is_signed;
2007   int rc = 0;
2008
2009   debug_print (2, ("Entering pgp_encrypted handler\n"));
2010   a = a->parts;
2011   if (!a || a->type != TYPEAPPLICATION || !a->subtype
2012       || ascii_strcasecmp ("pgp-encrypted", a->subtype)
2013       || !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype
2014       || ascii_strcasecmp ("octet-stream", a->next->subtype)) {
2015     if (s->flags & M_DISPLAY)
2016       state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"),
2017                          s);
2018     return (-1);
2019   }
2020
2021   /* Move forward to the application/pgp-encrypted body. */
2022   a = a->next;
2023
2024   mutt_mktemp (tempfile);
2025   if (!(fpout = safe_fopen (tempfile, "w+"))) {
2026     if (s->flags & M_DISPLAY)
2027       state_attach_puts (_("[-- Error: could not create temporary file! "
2028                            "--]\n"), s);
2029     return (-1);
2030   }
2031
2032   tattach = decrypt_part (a, s, fpout, 0, &is_signed);
2033   if (tattach) {
2034     tattach->goodsig = is_signed > 0;
2035
2036     if (s->flags & M_DISPLAY)
2037       state_attach_puts (is_signed ?
2038                          _
2039                          ("[-- The following data is PGP/MIME signed and encrypted --]\n\n") :
2040                          _("[-- The following data is PGP/MIME encrypted --]\n\n"), s);
2041
2042     {
2043       FILE *savefp = s->fpin;
2044
2045       s->fpin = fpout;
2046       rc = mutt_body_handler (tattach, s);
2047       s->fpin = savefp;
2048     }
2049
2050     /* 
2051      * if a multipart/signed is the _only_ sub-part of a
2052      * multipart/encrypted, cache signature verification
2053      * status.
2054      */
2055     if (mutt_is_multipart_signed (tattach) && !tattach->next)
2056       orig_body->goodsig |= tattach->goodsig;
2057
2058     if (s->flags & M_DISPLAY) {
2059       state_puts ("\n", s);
2060       state_attach_puts (is_signed ?
2061                          _
2062                          ("[-- End of PGP/MIME signed and encrypted data --]\n")
2063                          : _("[-- End of PGP/MIME encrypted data --]\n"), s);
2064     }
2065
2066     mutt_free_body (&tattach);
2067   }
2068
2069   fclose (fpout);
2070   mutt_unlink (tempfile);
2071   debug_print (2, ("Leaving pgp_encrypted handler\n"));
2072   return (rc);
2073 }
2074
2075 /* Support for application/smime */
2076 int smime_gpgme_application_handler (BODY * a, STATE * s)
2077 {
2078   char tempfile[_POSIX_PATH_MAX];
2079   FILE *fpout;
2080   BODY *tattach;
2081   int is_signed;
2082   int rc = 0;
2083
2084   debug_print (2, ("Entering smime_encrypted handler\n"));
2085
2086   a->warnsig = 0;
2087   mutt_mktemp (tempfile);
2088   if (!(fpout = safe_fopen (tempfile, "w+"))) {
2089     if (s->flags & M_DISPLAY)
2090       state_attach_puts (_("[-- Error: could not create temporary file! "
2091                            "--]\n"), s);
2092     return (-1);
2093   }
2094
2095   tattach = decrypt_part (a, s, fpout, 1, &is_signed);
2096   if (tattach) {
2097     tattach->goodsig = is_signed > 0;
2098
2099     if (s->flags & M_DISPLAY)
2100       state_attach_puts (is_signed ?
2101                          _("[-- The following data is S/MIME signed --]\n\n") :
2102                          _("[-- The following data is S/MIME encrypted --]\n\n"), s);
2103
2104     {
2105       FILE *savefp = s->fpin;
2106
2107       s->fpin = fpout;
2108       rc = mutt_body_handler (tattach, s);
2109       s->fpin = savefp;
2110     }
2111
2112     /* 
2113      * if a multipart/signed is the _only_ sub-part of a
2114      * multipart/encrypted, cache signature verification
2115      * status.
2116      */
2117     if (mutt_is_multipart_signed (tattach) && !tattach->next) {
2118       if (!(a->goodsig = tattach->goodsig))
2119         a->warnsig = tattach->warnsig;
2120     }
2121     else if (tattach->goodsig) {
2122       a->goodsig = 1;
2123       a->warnsig = tattach->warnsig;
2124     }
2125
2126     if (s->flags & M_DISPLAY) {
2127       state_puts ("\n", s);
2128       state_attach_puts (is_signed ?
2129                          _("[-- End of S/MIME signed data --]\n") :
2130                          _("[-- End of S/MIME encrypted data --]\n"), s);
2131     }
2132
2133     mutt_free_body (&tattach);
2134   }
2135
2136   fclose (fpout);
2137   mutt_unlink (tempfile);
2138   debug_print (2, ("Leaving smime_encrypted handler\n"));
2139   return (rc);
2140 }
2141
2142
2143 /*
2144  * Format an entry on the CRYPT key selection menu.
2145  * 
2146  * %n   number
2147  * %k   key id          %K      key id of the principal key
2148  * %u   user id
2149  * %a   algorithm       %A      algorithm of the princ. key
2150  * %l   length          %L      length of the princ. key
2151  * %f   flags           %F      flags of the princ. key
2152  * %c   capabilities    %C      capabilities of the princ. key
2153  * %t   trust/validity of the key-uid association
2154  * %p           protocol
2155  * %[...] date of key using strftime(3)
2156  */
2157
2158 static const char *
2159 crypt_entry_fmt (char *dest, ssize_t destlen, char op,
2160                  const char *src, const char *prefix,
2161                  const char *ifstring, const char *elsestring,
2162                  unsigned long data, format_flag flags)
2163 {
2164   char fmt[16];
2165   crypt_entry_t *entry;
2166   crypt_key_t *key;
2167   int kflags = 0;
2168   int optional = (flags & M_FORMAT_OPTIONAL);
2169   const char *s = NULL;
2170   unsigned long val;
2171
2172   entry = (crypt_entry_t *) data;
2173   key = entry->key;
2174
2175 /*    if (isupper ((unsigned char) op)) */
2176 /*      key = pkey; */
2177
2178   kflags = (key->flags          /*| (pkey->flags & KEYFLAG_RESTRICTIONS)
2179                                    | uid->flags */ );
2180
2181   switch (ascii_tolower (op)) {
2182   case '[':
2183     {
2184       const char *cp;
2185       char buf2[SHORT_STRING], *p;
2186       int do_locales;
2187       struct tm *tm;
2188       ssize_t len;
2189
2190       p = dest;
2191
2192       cp = src;
2193       if (*cp == '!') {
2194         do_locales = 0;
2195         cp++;
2196       }
2197       else
2198         do_locales = 1;
2199
2200       len = destlen - 1;
2201       while (len > 0 && *cp != ']') {
2202         if (*cp == '%') {
2203           cp++;
2204           if (len >= 2) {
2205             *p++ = '%';
2206             *p++ = *cp;
2207             len -= 2;
2208           }
2209           else
2210             break;              /* not enough space */
2211           cp++;
2212         }
2213         else {
2214           *p++ = *cp++;
2215           len--;
2216         }
2217       }
2218       *p = 0;
2219
2220       if (do_locales && Locale)
2221         setlocale (LC_TIME, Locale);
2222
2223       {
2224         time_t tt = 0;
2225
2226         if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
2227           tt = key->kobj->subkeys->timestamp;
2228
2229         tm = localtime (&tt);
2230       }
2231       strftime (buf2, sizeof (buf2), dest, tm);
2232
2233       if (do_locales)
2234         setlocale (LC_TIME, "C");
2235
2236       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2237       snprintf (dest, destlen, fmt, buf2);
2238       if (len > 0)
2239         src = cp + 1;
2240     }
2241     break;
2242   case 'n':
2243     if (!optional) {
2244       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
2245       snprintf (dest, destlen, fmt, entry->num);
2246     }
2247     break;
2248   case 'k':
2249     if (!optional) {
2250       /* fixme: we need a way to distinguish between main and subkeys.
2251          Store the idx in entry? */
2252       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2253       snprintf (dest, destlen, fmt, crypt_keyid (key));
2254     }
2255     break;
2256   case 'u':
2257     if (!optional) {
2258       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2259       snprintf (dest, destlen, fmt, key->uid);
2260     }
2261     break;
2262   case 'a':
2263     if (!optional) {
2264       snprintf (fmt, sizeof (fmt), "%%%s.3s", prefix);
2265       if (key->kobj->subkeys)
2266         s = gpgme_pubkey_algo_name (key->kobj->subkeys->pubkey_algo);
2267       else
2268         s = "?";
2269       snprintf (dest, destlen, fmt, s);
2270     }
2271     break;
2272   case 'l':
2273     if (!optional) {
2274       snprintf (fmt, sizeof (fmt), "%%%slu", prefix);
2275       if (key->kobj->subkeys)
2276         val = key->kobj->subkeys->length;
2277       else
2278         val = 0;
2279       snprintf (dest, destlen, fmt, val);
2280     }
2281     break;
2282   case 'f':
2283     if (!optional) {
2284       snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2285       snprintf (dest, destlen, fmt, crypt_flags (kflags));
2286     }
2287     else if (!(kflags & (KEYFLAG_RESTRICTIONS)))
2288       optional = 0;
2289     break;
2290   case 'c':
2291     if (!optional) {
2292       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2293       snprintf (dest, destlen, fmt, crypt_key_abilities (kflags));
2294     }
2295     else if (!(kflags & (KEYFLAG_ABILITIES)))
2296       optional = 0;
2297     break;
2298   case 't':
2299     if ((kflags & KEYFLAG_ISX509))
2300       s = "x";
2301     else {
2302       gpgme_user_id_t uid = NULL;
2303       int i = 0;
2304
2305       for (i = 0, uid = key->kobj->uids; uid && (i < key->idx);
2306            i++, uid = uid->next);
2307       if (uid)
2308         switch (uid->validity) {
2309         case GPGME_VALIDITY_UNDEFINED:
2310           s = "q";
2311           break;
2312         case GPGME_VALIDITY_NEVER:
2313           s = "n";
2314           break;
2315         case GPGME_VALIDITY_MARGINAL:
2316           s = "m";
2317           break;
2318         case GPGME_VALIDITY_FULL:
2319           s = "f";
2320           break;
2321         case GPGME_VALIDITY_ULTIMATE:
2322           s = "u";
2323           break;
2324         case GPGME_VALIDITY_UNKNOWN:
2325         default:
2326           s = "?";
2327           break;
2328         }
2329     }
2330     snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2331     snprintf (dest, destlen, fmt, s ? *s : 'B');
2332     break;
2333   case 'p':
2334     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2335     snprintf (dest, destlen, fmt,
2336               gpgme_get_protocol_name (key->kobj->protocol));
2337     break;
2338
2339   default:
2340     *dest = '\0';
2341   }
2342
2343   if (optional)
2344     mutt_FormatString (dest, destlen, ifstring, mutt_attach_fmt, data, 0);
2345   else if (flags & M_FORMAT_OPTIONAL)
2346     mutt_FormatString (dest, destlen, elsestring, mutt_attach_fmt, data, 0);
2347   return (src);
2348 }
2349
2350 /* Used by the display fucntion to format a line. */
2351 static void crypt_entry (char *s, ssize_t l, MUTTMENU * menu, int num)
2352 {
2353   crypt_key_t **key_table = (crypt_key_t **) menu->data;
2354   crypt_entry_t entry;
2355
2356   entry.key = key_table[num];
2357   entry.num = num + 1;
2358
2359   mutt_FormatString (s, l, NONULL (PgpEntryFormat), crypt_entry_fmt,
2360                      (unsigned long) &entry, M_FORMAT_ARROWCURSOR);
2361 }
2362
2363 /* Compare two addresses and the keyid to be used for sorting. */
2364 static int _crypt_compare_address (const void *a, const void *b)
2365 {
2366   crypt_key_t **s = (crypt_key_t **) a;
2367   crypt_key_t **t = (crypt_key_t **) b;
2368   int r;
2369
2370   if ((r = m_strcasecmp((*s)->uid, (*t)->uid)))
2371     return r > 0;
2372   else
2373     return m_strcasecmp(crypt_keyid (*s), crypt_keyid (*t)) > 0;
2374 }
2375
2376 static int crypt_compare_address (const void *a, const void *b)
2377 {
2378   return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_address (a, b)
2379           : _crypt_compare_address (a, b));
2380 }
2381
2382
2383 /* Compare two key IDs and the addresses to be used for sorting. */
2384 static int _crypt_compare_keyid (const void *a, const void *b)
2385 {
2386   crypt_key_t **s = (crypt_key_t **) a;
2387   crypt_key_t **t = (crypt_key_t **) b;
2388   int r;
2389
2390   if ((r = m_strcasecmp(crypt_keyid (*s), crypt_keyid (*t))))
2391     return r > 0;
2392   else
2393     return m_strcasecmp((*s)->uid, (*t)->uid) > 0;
2394 }
2395
2396 static int crypt_compare_keyid (const void *a, const void *b)
2397 {
2398   return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_keyid (a, b)
2399           : _crypt_compare_keyid (a, b));
2400 }
2401
2402 /* Compare 2 creation dates and the addresses.  For sorting. */
2403 static int _crypt_compare_date (const void *a, const void *b)
2404 {
2405   crypt_key_t **s = (crypt_key_t **) a;
2406   crypt_key_t **t = (crypt_key_t **) b;
2407   unsigned long ts = 0, tt = 0;
2408
2409   if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2410     ts = (*s)->kobj->subkeys->timestamp;
2411   if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2412     tt = (*t)->kobj->subkeys->timestamp;
2413
2414   if (ts > tt)
2415     return 1;
2416   if (ts < tt)
2417     return 0;
2418
2419   return m_strcasecmp((*s)->uid, (*t)->uid) > 0;
2420 }
2421
2422 static int crypt_compare_date (const void *a, const void *b)
2423 {
2424   return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_date (a, b)
2425           : _crypt_compare_date (a, b));
2426 }
2427
2428 /* Compare two trust values, the key length, the creation dates. the
2429    addresses and the key IDs.  For sorting. */
2430 static int _crypt_compare_trust (const void *a, const void *b)
2431 {
2432   crypt_key_t **s = (crypt_key_t **) a;
2433   crypt_key_t **t = (crypt_key_t **) b;
2434   unsigned long ts = 0, tt = 0;
2435   int r;
2436
2437   if ((r = (((*s)->flags & (KEYFLAG_RESTRICTIONS))
2438             - ((*t)->flags & (KEYFLAG_RESTRICTIONS)))))
2439     return r > 0;
2440
2441   if ((*s)->kobj->uids)
2442     ts = (*s)->kobj->uids->validity;
2443   if ((*t)->kobj->uids)
2444     tt = (*t)->kobj->uids->validity;
2445   if ((r = (tt - ts)))
2446     return r < 0;
2447
2448   if ((*s)->kobj->subkeys)
2449     ts = (*s)->kobj->subkeys->length;
2450   if ((*t)->kobj->subkeys)
2451     tt = (*t)->kobj->subkeys->length;
2452   if (ts != tt)
2453     return ts > tt;
2454
2455   if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2456     ts = (*s)->kobj->subkeys->timestamp;
2457   if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2458     tt = (*t)->kobj->subkeys->timestamp;
2459   if (ts > tt)
2460     return 1;
2461   if (ts < tt)
2462     return 0;
2463
2464   if ((r = m_strcasecmp((*s)->uid, (*t)->uid)))
2465     return r > 0;
2466   return (m_strcasecmp(crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0;
2467 }
2468
2469 static int crypt_compare_trust (const void *a, const void *b)
2470 {
2471   return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_trust (a, b)
2472           : _crypt_compare_trust (a, b));
2473 }
2474
2475 /* Print the X.500 Distinguished Name part KEY from the array of parts
2476    DN to FP. */
2477 static int print_dn_part (FILE * fp, struct dn_array_s *dn, const char *key)
2478 {
2479   int any = 0;
2480
2481   for (; dn->key; dn++) {
2482     if (!m_strcmp(dn->key, key)) {
2483       if (any)
2484         fputs (" + ", fp);
2485       print_utf8 (fp, dn->value, m_strlen(dn->value));
2486       any = 1;
2487     }
2488   }
2489   return any;
2490 }
2491
2492 /* Print all parts of a DN in a standard sequence. */
2493 static void print_dn_parts (FILE * fp, struct dn_array_s *dn)
2494 {
2495   const char *stdpart[] = {
2496     "CN", "OU", "O", "STREET", "L", "ST", "C", NULL
2497   };
2498   int any = 0, any2 = 0, i;
2499
2500   for (i = 0; stdpart[i]; i++) {
2501     if (any)
2502       fputs (", ", fp);
2503     any = print_dn_part (fp, dn, stdpart[i]);
2504   }
2505   /* now print the rest without any specific ordering */
2506   for (; dn->key; dn++) {
2507     for (i = 0; stdpart[i]; i++) {
2508       if (!m_strcmp(dn->key, stdpart[i]))
2509         break;
2510     }
2511     if (!stdpart[i]) {
2512       if (any)
2513         fputs (", ", fp);
2514       if (!any2)
2515         fputs ("(", fp);
2516       any = print_dn_part (fp, dn, dn->key);
2517       any2 = 1;
2518     }
2519   }
2520   if (any2)
2521     fputs (")", fp);
2522 }
2523
2524
2525 /* Parse an RDN; this is a helper to parse_dn(). */
2526 static const unsigned char *parse_dn_part (struct dn_array_s *array,
2527                                            const unsigned char *string)
2528 {
2529   const unsigned char *s, *s1;
2530   ssize_t n;
2531   unsigned char *p;
2532
2533   /* parse attributeType */
2534   for (s = string + 1; *s && *s != '='; s++);
2535   if (!*s)
2536     return NULL;                /* error */
2537   n = s - string;
2538   if (!n)
2539     return NULL;                /* empty key */
2540   array->key = p_dupstr(string, n );
2541   p = (unsigned char *) array->key;
2542   string = s + 1;
2543
2544   if (*string == '#') {         /* hexstring */
2545     string++;
2546     for (s = string; hexdigitp (s); s++)
2547       s++;
2548     n = s - string;
2549     if (!n || (n & 1))
2550       return NULL;              /* empty or odd number of digits */
2551     n /= 2;
2552     p = xmalloc(n + 1);
2553     array->value = (char *) p;
2554     for (s1 = string; n; s1 += 2, n--)
2555       *p++ = xtoi_2 (s1);
2556     *p = 0;
2557   }
2558   else {                        /* regular v3 quoted string */
2559     for (n = 0, s = string; *s; s++) {
2560       if (*s == '\\') {         /* pair */
2561         s++;
2562         if (*s == ',' || *s == '=' || *s == '+'
2563             || *s == '<' || *s == '>' || *s == '#' || *s == ';'
2564             || *s == '\\' || *s == '\"' || *s == ' ')
2565           n++;
2566         else if (hexdigitp (s) && hexdigitp (s + 1)) {
2567           s++;
2568           n++;
2569         }
2570         else
2571           return NULL;          /* invalid escape sequence */
2572       }
2573       else if (*s == '\"')
2574         return NULL;            /* invalid encoding */
2575       else if (*s == ',' || *s == '=' || *s == '+'
2576                || *s == '<' || *s == '>' || *s == '#' || *s == ';')
2577         break;
2578       else
2579         n++;
2580     }
2581
2582     p = xmalloc(n + 1);
2583     array->value = (char *) p;
2584     for (s = string; n; s++, n--) {
2585       if (*s == '\\') {
2586         s++;
2587         if (hexdigitp (s)) {
2588           *p++ = xtoi_2 (s);
2589           s++;
2590         }
2591         else
2592           *p++ = *s;
2593       }
2594       else
2595         *p++ = *s;
2596     }
2597     *p = 0;
2598   }
2599   return s;
2600 }
2601
2602
2603 /* Parse a DN and return an array-ized one.  This is not a validating
2604    parser and it does not support any old-stylish syntax; gpgme is
2605    expected to return only rfc2253 compatible strings. */
2606 static struct dn_array_s *parse_dn (const unsigned char *string)
2607 {
2608   struct dn_array_s *array;
2609   ssize_t arrayidx, arraysize;
2610   int i;
2611
2612   arraysize = 7;                /* C,ST,L,O,OU,CN,email */
2613   array = p_new(struct dn_array_s, arraysize + 1);
2614   arrayidx = 0;
2615   while (*string) {
2616     while (*string == ' ')
2617       string++;
2618     if (!*string)
2619       break;                    /* ready */
2620     if (arrayidx >= arraysize) {        /* mutt lacks a real safe_realoc - so we need to copy */
2621       struct dn_array_s *a2;
2622
2623       arraysize += 5;
2624       a2 = p_new(struct dn_array_s, arraysize + 1);
2625       for (i = 0; i < arrayidx; i++) {
2626         a2[i].key = array[i].key;
2627         a2[i].value = array[i].value;
2628       }
2629       p_delete(&array);
2630       array = a2;
2631     }
2632     array[arrayidx].key = NULL;
2633     array[arrayidx].value = NULL;
2634     string = parse_dn_part (array + arrayidx, string);
2635     arrayidx++;
2636     if (!string)
2637       goto failure;
2638     while (*string == ' ')
2639       string++;
2640     if (*string && *string != ',' && *string != ';' && *string != '+')
2641       goto failure;             /* invalid delimiter */
2642     if (*string)
2643       string++;
2644   }
2645   array[arrayidx].key = NULL;
2646   array[arrayidx].value = NULL;
2647   return array;
2648
2649 failure:
2650   for (i = 0; i < arrayidx; i++) {
2651     p_delete(&array[i].key);
2652     p_delete(&array[i].value);
2653   }
2654   p_delete(&array);
2655   return NULL;
2656 }
2657
2658
2659 /* Print a nice representation of the USERID and make sure it is
2660    displayed in a proper way, which does mean to reorder some parts
2661    for S/MIME's DNs.  USERID is a string as returned by the gpgme key
2662    functions.  It is utf-8 encoded. */
2663 static void parse_and_print_user_id (FILE * fp, const char *userid)
2664 {
2665   const char *s;
2666   int i;
2667
2668   if (*userid == '<') {
2669     s = strchr (userid + 1, '>');
2670     if (s)
2671       print_utf8 (fp, userid + 1, s - userid - 1);
2672   }
2673   else if (*userid == '(')
2674     fputs (_("[Can't display this user ID (unknown encoding)]"), fp);
2675   else if (!digit_or_letter ((const unsigned char *) userid))
2676     fputs (_("[Can't display this user ID (invalid encoding)]"), fp);
2677   else {
2678     struct dn_array_s *dn = parse_dn ((const unsigned char *) userid);
2679
2680     if (!dn)
2681       fputs (_("[Can't display this user ID (invalid DN)]"), fp);
2682     else {
2683       print_dn_parts (fp, dn);
2684       for (i = 0; dn[i].key; i++) {
2685         p_delete(&dn[i].key);
2686         p_delete(&dn[i].value);
2687       }
2688       p_delete(&dn);
2689     }
2690   }
2691 }
2692
2693 typedef enum {
2694   KEY_CAP_CAN_ENCRYPT,
2695   KEY_CAP_CAN_SIGN,
2696   KEY_CAP_CAN_CERTIFY
2697 } key_cap_t;
2698
2699 static unsigned int key_check_cap (gpgme_key_t key, key_cap_t cap)
2700 {
2701   gpgme_subkey_t subkey = NULL;
2702   unsigned int ret = 0;
2703
2704   switch (cap) {
2705   case KEY_CAP_CAN_ENCRYPT:
2706     if (!(ret = key->can_encrypt))
2707       for (subkey = key->subkeys; subkey; subkey = subkey->next)
2708         if ((ret = subkey->can_encrypt))
2709           break;
2710     break;
2711   case KEY_CAP_CAN_SIGN:
2712     if (!(ret = key->can_sign))
2713       for (subkey = key->subkeys; subkey; subkey = subkey->next)
2714         if ((ret = subkey->can_sign))
2715           break;
2716     break;
2717   case KEY_CAP_CAN_CERTIFY:
2718     if (!(ret = key->can_certify))
2719       for (subkey = key->subkeys; subkey; subkey = subkey->next)
2720         if ((ret = subkey->can_certify))
2721           break;
2722     break;
2723   }
2724
2725   return ret;
2726 }
2727
2728
2729 /* Print verbose information about a key or certificate to FP. */
2730 static void print_key_info (gpgme_key_t key, FILE * fp)
2731 {
2732   int idx;
2733   const char *s = NULL, *s2 = NULL;
2734   time_t tt = 0;
2735   struct tm *tm;
2736   char shortbuf[SHORT_STRING];
2737   unsigned long aval = 0;
2738   const char *delim;
2739   int is_pgp = 0;
2740   int i;
2741   gpgme_user_id_t uid = NULL;
2742
2743   if (Locale)
2744     setlocale (LC_TIME, Locale);
2745
2746   is_pgp = key->protocol == GPGME_PROTOCOL_OpenPGP;
2747
2748   for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
2749     if (uid->revoked)
2750       continue;
2751
2752     s = uid->uid;
2753     fputs (idx ? _(" aka ......: ") :_("Name ......: "), fp);
2754
2755     if (uid->invalid) {
2756       fputs (_("[Invalid]"), fp);
2757       putc (' ', fp);
2758     }
2759     if (is_pgp)
2760       print_utf8 (fp, s, m_strlen(s));
2761     else
2762       parse_and_print_user_id (fp, s);
2763     putc ('\n', fp);
2764   }
2765
2766   if (key->subkeys && (key->subkeys->timestamp > 0)) {
2767     tt = key->subkeys->timestamp;
2768
2769     tm = localtime (&tt);
2770 #ifdef HAVE_LANGINFO_D_T_FMT
2771     strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2772 #else
2773     strftime (shortbuf, sizeof shortbuf, "%c", tm);
2774 #endif
2775     fprintf (fp, _("Valid From : %s\n"), shortbuf);
2776   }
2777
2778   if (key->subkeys && (key->subkeys->expires > 0)) {
2779     tt = key->subkeys->expires;
2780
2781     tm = localtime (&tt);
2782 #ifdef HAVE_LANGINFO_D_T_FMT
2783     strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2784 #else
2785     strftime (shortbuf, sizeof shortbuf, "%c", tm);
2786 #endif
2787     fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
2788   }
2789
2790   if (key->subkeys)
2791     s = gpgme_pubkey_algo_name (key->subkeys->pubkey_algo);
2792   else
2793     s = "?";
2794
2795   s2 = is_pgp ? "PGP" : "X.509";
2796
2797   if (key->subkeys)
2798     aval = key->subkeys->length;
2799
2800   fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), s2, aval, s);
2801
2802   fprintf (fp, _("Key Usage .: "));
2803   delim = "";
2804
2805   if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) {
2806     fprintf (fp, "%s%s", delim, _("encryption"));
2807     delim = _(", ");
2808   }
2809   if (key_check_cap (key, KEY_CAP_CAN_SIGN)) {
2810     fprintf (fp, "%s%s", delim, _("signing"));
2811     delim = _(", ");
2812   }
2813   if (key_check_cap (key, KEY_CAP_CAN_CERTIFY)) {
2814     fprintf (fp, "%s%s", delim, _("certification"));
2815     delim = _(", ");
2816   }
2817   putc ('\n', fp);
2818
2819   if (key->subkeys) {
2820     s = key->subkeys->fpr;
2821     fputs (_("Fingerprint: "), fp);
2822     if (is_pgp && m_strlen(s) == 40) {
2823       for (i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) {
2824         putc (*s, fp);
2825         putc (s[1], fp);
2826         putc (s[2], fp);
2827         putc (s[3], fp);
2828         putc (is_pgp ? ' ' : ':', fp);
2829         if (is_pgp && i == 4)
2830           putc (' ', fp);
2831       }
2832     }
2833     else {
2834       for (i = 0; *s && s[1] && s[2]; s += 2, i++) {
2835         putc (*s, fp);
2836         putc (s[1], fp);
2837         putc (is_pgp ? ' ' : ':', fp);
2838         if (is_pgp && i == 7)
2839           putc (' ', fp);
2840       }
2841     }
2842     fprintf (fp, "%s\n", s);
2843   }
2844
2845   if (key->issuer_serial) {
2846     s = key->issuer_serial;
2847     if (s)
2848       fprintf (fp, _("Serial-No .: 0x%s\n"), s);
2849   }
2850
2851   if (key->issuer_name) {
2852     s = key->issuer_name;
2853     if (s) {
2854       fprintf (fp, _("Issued By .: "));
2855       parse_and_print_user_id (fp, s);
2856       putc ('\n', fp);
2857     }
2858   }
2859
2860   /* For PGP we list all subkeys. */
2861   if (is_pgp) {
2862     gpgme_subkey_t subkey = NULL;
2863
2864     for (idx = 1, subkey = key->subkeys; subkey; idx++, subkey = subkey->next) {
2865       s = subkey->keyid;
2866
2867       putc ('\n', fp);
2868       if (m_strlen(s) == 16)
2869         s += 8;                 /* display only the short keyID */
2870       fprintf (fp, _("Subkey ....: 0x%s"), s);
2871       if (subkey->revoked) {
2872         putc (' ', fp);
2873         fputs (_("[Revoked]"), fp);
2874       }
2875       if (subkey->invalid) {
2876         putc (' ', fp);
2877         fputs (_("[Invalid]"), fp);
2878       }
2879       if (subkey->expired) {
2880         putc (' ', fp);
2881         fputs (_("[Expired]"), fp);
2882       }
2883       if (subkey->disabled) {
2884         putc (' ', fp);
2885         fputs (_("[Disabled]"), fp);
2886       }
2887       putc ('\n', fp);
2888
2889       if (subkey->timestamp > 0) {
2890         tt = subkey->timestamp;
2891
2892         tm = localtime (&tt);
2893 #ifdef HAVE_LANGINFO_D_T_FMT
2894         strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2895 #else
2896         strftime (shortbuf, sizeof shortbuf, "%c", tm);
2897 #endif
2898         fprintf (fp, _("Valid From : %s\n"), shortbuf);
2899       }
2900
2901       if (subkey->expires > 0) {
2902         tt = subkey->expires;
2903
2904         tm = localtime (&tt);
2905 #ifdef HAVE_LANGINFO_D_T_FMT
2906         strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2907 #else
2908         strftime (shortbuf, sizeof shortbuf, "%c", tm);
2909 #endif
2910         fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
2911       }
2912
2913       if (subkey)
2914         s = gpgme_pubkey_algo_name (subkey->pubkey_algo);
2915       else
2916         s = "?";
2917
2918       if (subkey)
2919         aval = subkey->length;
2920       else
2921         aval = 0;
2922
2923       fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), "PGP", aval, s);
2924
2925       fprintf (fp, _("Key Usage .: "));
2926       delim = "";
2927
2928       if (subkey->can_encrypt) {
2929         fprintf (fp, "%s%s", delim, _("encryption"));
2930         delim = _(", ");
2931       }
2932       if (subkey->can_sign) {
2933         fprintf (fp, "%s%s", delim, _("signing"));
2934         delim = _(", ");
2935       }
2936       if (subkey->can_certify) {
2937         fprintf (fp, "%s%s", delim, _("certification"));
2938         delim = _(", ");
2939       }
2940       putc ('\n', fp);
2941     }
2942   }
2943
2944   if (Locale)
2945     setlocale (LC_TIME, "C");
2946 }
2947
2948
2949 /* Show detailed information about the selected key */
2950 static void verify_key (crypt_key_t * key)
2951 {
2952   FILE *fp;
2953   char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX];
2954   const char *s;
2955   gpgme_ctx_t listctx = NULL;
2956   gpgme_error_t err;
2957   gpgme_key_t k = NULL;
2958   int maxdepth = 100;
2959
2960   mutt_mktemp (tempfile);
2961   if (!(fp = safe_fopen (tempfile, "w"))) {
2962     mutt_perror (_("Can't create temporary file"));
2963
2964     return;
2965   }
2966   mutt_message _("Collecting data...");
2967
2968   print_key_info (key->kobj, fp);
2969
2970   err = gpgme_new (&listctx);
2971   if (err) {
2972     fprintf (fp, "Internal error: can't create gpgme context: %s\n",
2973              gpgme_strerror (err));
2974     goto leave;
2975   }
2976   if ((key->flags & KEYFLAG_ISX509))
2977     gpgme_set_protocol (listctx, GPGME_PROTOCOL_CMS);
2978
2979   k = key->kobj;
2980   gpgme_key_ref (k);
2981   while ((s = k->chain_id) && k->subkeys && m_strcmp(s, k->subkeys->fpr)) {
2982     putc ('\n', fp);
2983     err = gpgme_op_keylist_start (listctx, s, 0);
2984     gpgme_key_release (k);
2985     k = NULL;
2986     if (!err)
2987       err = gpgme_op_keylist_next (listctx, &k);
2988     if (err) {
2989       fprintf (fp, _("Error finding issuer key: %s\n"), gpgme_strerror (err));
2990       goto leave;
2991     }
2992     gpgme_op_keylist_end (listctx);
2993
2994     print_key_info (k, fp);
2995     if (!--maxdepth) {
2996       putc ('\n', fp);
2997       fputs (_("Error: certification chain to long - stopping here\n"), fp);
2998       break;
2999     }
3000   }
3001
3002 leave:
3003   gpgme_key_release (k);
3004   gpgme_release (listctx);
3005   fclose (fp);
3006   mutt_clear_error ();
3007   snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"), crypt_keyid (key));
3008   mutt_do_pager (cmd, tempfile, 0, NULL);
3009 }
3010
3011 /* 
3012  * Implementation of `findkeys'.
3013  */
3014
3015
3016 /* Convert string_list_t into a pattern string suitable to be passed to GPGME.
3017    We need to convert spaces in an item into a '+' and '%' into
3018    "%25". */
3019 static char *list_to_pattern (string_list_t * list)
3020 {
3021   string_list_t *l;
3022   char *pattern, *p;
3023   const char *s;
3024   ssize_t n;
3025
3026   n = 0;
3027   for (l = list; l; l = l->next) {
3028     for (s = l->data; *s; s++) {
3029       if (*s == '%')
3030         n += 2;
3031       n++;
3032     }
3033     n++;                        /* delimiter or end of string */
3034   }
3035   n++;                          /* make sure to allocate at least one byte */
3036   pattern = p = p_new(char, n);
3037   for (l = list; l; l = l->next) {
3038     s = l->data;
3039     if (*s) {
3040       if (l != list)
3041         *p++ = ' ';
3042       for (s = l->data; *s; s++) {
3043         if (*s == '%') {
3044           *p++ = '%';
3045           *p++ = '2';
3046           *p++ = '5';
3047         }
3048         else if (*s == '+') {
3049           *p++ = '%';
3050           *p++ = '2';
3051           *p++ = 'B';
3052         }
3053         else if (*s == ' ')
3054           *p++ = '+';
3055         else
3056           *p++ = *s;
3057       }
3058     }
3059   }
3060   *p = 0;
3061   return pattern;
3062 }
3063
3064 /* Return a list of keys which are candidates for the selection.
3065    Select by looking at the HINTS list. */
3066 static crypt_key_t *get_candidates (string_list_t * hints, unsigned int app,
3067                                     int secret)
3068 {
3069   crypt_key_t *db, *k, **kend;
3070   char *pattern;
3071   gpgme_error_t err;
3072   gpgme_ctx_t ctx;
3073   gpgme_key_t key;
3074   int idx;
3075   gpgme_user_id_t uid = NULL;
3076
3077   pattern = list_to_pattern (hints);
3078   if (!pattern)
3079     return NULL;
3080
3081   err = gpgme_new (&ctx);
3082   if (err) {
3083     mutt_error (_("gpgme_new failed: %s"), gpgme_strerror (err));
3084     p_delete(&pattern);
3085     return NULL;
3086   }
3087
3088   db = NULL;
3089   kend = &db;
3090
3091   if ((app & APPLICATION_PGP)) {
3092     /* Its all a mess.  That old GPGME expects different things
3093        depending on the protocol.  For gpg we don' t need percent
3094        escaped pappert but simple strings passed in an array to the
3095        keylist_ext_start function. */
3096     string_list_t *l;
3097     ssize_t n;
3098     char **patarr;
3099
3100     for (l = hints, n = 0; l; l = l->next) {
3101       if (l->data && *l->data)
3102         n++;
3103     }
3104     if (!n)
3105       goto no_pgphints;
3106
3107     patarr = p_new(char *, n + 1);
3108     for (l = hints, n = 0; l; l = l->next) {
3109       if (l->data && *l->data)
3110         patarr[n++] = m_strdup(l->data);
3111     }
3112     patarr[n] = NULL;
3113     err = gpgme_op_keylist_ext_start (ctx, (const char **) patarr, secret, 0);
3114     for (n = 0; patarr[n]; n++)
3115       p_delete(&patarr[n]);
3116     p_delete(&patarr);
3117     if (err) {
3118       mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err));
3119       gpgme_release (ctx);
3120       p_delete(&pattern);
3121       return NULL;
3122     }
3123
3124     while (!(err = gpgme_op_keylist_next (ctx, &key))) {
3125       unsigned int flags = 0;
3126
3127       if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3128         flags |= KEYFLAG_CANENCRYPT;
3129       if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3130         flags |= KEYFLAG_CANSIGN;
3131
3132 #if 0                           /* DISABLED code */
3133       if (!flags) {
3134         /* Bug in gpg.  Capabilities are not listed for secret
3135            keys.  Try to deduce them from the algorithm. */
3136
3137         switch (key->subkeys[0].pubkey_algo) {
3138         case GPGME_PK_RSA:
3139           flags |= KEYFLAG_CANENCRYPT;
3140           flags |= KEYFLAG_CANSIGN;
3141           break;
3142         case GPGME_PK_ELG_E:
3143           flags |= KEYFLAG_CANENCRYPT;
3144           break;
3145         case GPGME_PK_DSA:
3146           flags |= KEYFLAG_CANSIGN;
3147           break;
3148         }
3149       }
3150 #endif /* DISABLED code */
3151
3152       for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
3153         k = p_new(crypt_key_t, 1);
3154         k->kobj = key;
3155         k->idx = idx;
3156         k->uid = uid->uid;
3157         k->flags = flags;
3158         *kend = k;
3159         kend = &k->next;
3160       }
3161     }
3162     if (gpg_err_code (err) != GPG_ERR_EOF)
3163       mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3164     gpgme_op_keylist_end (ctx);
3165   no_pgphints:
3166     ;
3167   }
3168
3169   if ((app & APPLICATION_SMIME)) {
3170     /* and now look for x509 certificates */
3171     gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
3172     err = gpgme_op_keylist_start (ctx, pattern, 0);
3173     if (err) {
3174       mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err));
3175       gpgme_release (ctx);
3176       p_delete(&pattern);
3177       return NULL;
3178     }
3179
3180     while (!(err = gpgme_op_keylist_next (ctx, &key))) {
3181       unsigned int flags = KEYFLAG_ISX509;
3182
3183       if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3184         flags |= KEYFLAG_CANENCRYPT;
3185       if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3186         flags |= KEYFLAG_CANSIGN;
3187
3188       for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
3189         k = p_new(crypt_key_t, 1);
3190         k->kobj = key;
3191         k->idx = idx;
3192         k->uid = uid->uid;
3193         k->flags = flags;
3194         *kend = k;
3195         kend = &k->next;
3196       }
3197     }
3198     if (gpg_err_code (err) != GPG_ERR_EOF)
3199       mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3200     gpgme_op_keylist_end (ctx);
3201   }
3202
3203   gpgme_release (ctx);
3204   p_delete(&pattern);
3205   return db;
3206 }
3207
3208 /* Add the string STR to the list HINTS.  This list is later used to
3209    match addresses. */
3210 static string_list_t *crypt_add_string_to_hints (string_list_t * hints, const char *str)
3211 {
3212   char *scratch;
3213   char *t;
3214
3215   if ((scratch = m_strdup(str)) == NULL)
3216     return hints;
3217
3218   for (t = strtok (scratch, " ,.:\"()<>\n"); t;
3219        t = strtok (NULL, " ,.:\"()<>\n")) {
3220     if (m_strlen(t) > 3)
3221       hints = mutt_add_list(hints, t);
3222   }
3223
3224   p_delete(&scratch);
3225   return hints;
3226 }
3227
3228 /* Display a menu to select a key from the array KEYS. FORCED_VALID
3229    will be set to true on return if the user did override the the
3230    key's validity. */
3231 static crypt_key_t *crypt_select_key (crypt_key_t * keys,
3232                                       address_t * p, const char *s,
3233                                       unsigned int app, int *forced_valid)
3234 {
3235   int keymax;
3236   crypt_key_t **key_table;
3237   MUTTMENU *menu;
3238   int i, done = 0;
3239   char helpstr[SHORT_STRING], buf[LONG_STRING];
3240   crypt_key_t *k;
3241   int (*f) (const void *, const void *);
3242   int menu_to_use = 0;
3243   int unusable = 0;
3244
3245   *forced_valid = 0;
3246
3247   /* build the key table */
3248   keymax = i = 0;
3249   key_table = NULL;
3250   for (k = keys; k; k = k->next) {
3251     if (!option (OPTPGPSHOWUNUSABLE) && (k->flags & KEYFLAG_CANTUSE)) {
3252       unusable = 1;
3253       continue;
3254     }
3255
3256     if (i == keymax) {
3257       keymax += 20;
3258       p_realloc(&key_table, keymax);
3259     }
3260
3261     key_table[i++] = k;
3262   }
3263
3264   if (!i && unusable) {
3265     mutt_error _("All matching keys are marked expired/revoked.");
3266
3267     mutt_sleep (1);
3268     return NULL;
3269   }
3270
3271   switch (PgpSortKeys & SORT_MASK) {
3272   case SORT_DATE:
3273     f = crypt_compare_date;
3274     break;
3275   case SORT_KEYID:
3276     f = crypt_compare_keyid;
3277     break;
3278   case SORT_ADDRESS:
3279     f = crypt_compare_address;
3280     break;
3281   case SORT_TRUST:
3282   default:
3283     f = crypt_compare_trust;
3284     break;
3285   }
3286   qsort (key_table, i, sizeof (crypt_key_t *), f);
3287
3288   if (app & APPLICATION_PGP)
3289     menu_to_use = MENU_KEY_SELECT_PGP;
3290   else if (app & APPLICATION_SMIME)
3291     menu_to_use = MENU_KEY_SELECT_SMIME;
3292
3293   helpstr[0] = 0;
3294   mutt_make_help (buf, sizeof (buf), _("Exit  "), menu_to_use, OP_EXIT);
3295   strcat (helpstr, buf);        /* __STRCAT_CHECKED__ */
3296   mutt_make_help (buf, sizeof (buf), _("Select  "), menu_to_use,
3297                   OP_GENERIC_SELECT_ENTRY);
3298   strcat (helpstr, buf);        /* __STRCAT_CHECKED__ */
3299   mutt_make_help (buf, sizeof (buf), _("Check key  "),
3300                   menu_to_use, OP_VERIFY_KEY);
3301   strcat (helpstr, buf);        /* __STRCAT_CHECKED__ */
3302   mutt_make_help (buf, sizeof (buf), _("Help"), menu_to_use, OP_HELP);
3303   strcat (helpstr, buf);        /* __STRCAT_CHECKED__ */
3304
3305   menu = mutt_new_menu ();
3306   menu->max = i;
3307   menu->make_entry = crypt_entry;
3308   menu->menu = menu_to_use;
3309   menu->help = helpstr;
3310   menu->data = key_table;
3311
3312   {
3313     const char *ts;
3314
3315     if ((app & APPLICATION_PGP) && (app & APPLICATION_SMIME))
3316       ts = _("PGP and S/MIME keys matching");
3317     else if ((app & APPLICATION_PGP))
3318       ts = _("PGP keys matching");
3319     else if ((app & APPLICATION_SMIME))
3320       ts = _("S/MIME keys matching");
3321     else
3322       ts = _("keys matching");
3323
3324     if (p)
3325       snprintf (buf, sizeof (buf), _("%s <%s>."), ts, p->mailbox);
3326     else
3327       snprintf (buf, sizeof (buf), _("%s \"%s\"."), ts, s);
3328     menu->title = buf;
3329   }
3330
3331   mutt_clear_error ();
3332   k = NULL;
3333   while (!done) {
3334     *forced_valid = 0;
3335     switch (mutt_menuLoop (menu)) {
3336     case OP_VERIFY_KEY:
3337       verify_key (key_table[menu->current]);
3338       menu->redraw = REDRAW_FULL;
3339       break;
3340
3341     case OP_VIEW_ID:
3342       mutt_message ("%s", key_table[menu->current]->uid);
3343       break;
3344
3345     case OP_GENERIC_SELECT_ENTRY:
3346       /* FIXME make error reporting more verbose - this should be
3347          easy because gpgme provides more information */
3348       if (option (OPTPGPCHECKTRUST)) {
3349         if (!crypt_key_is_valid (key_table[menu->current])) {
3350           mutt_error _("This key can't be used: "
3351                        "expired/disabled/revoked.");
3352           break;
3353         }
3354       }
3355
3356       if (option (OPTPGPCHECKTRUST) &&
3357           (!crypt_id_is_valid (key_table[menu->current])
3358            || !crypt_id_is_strong (key_table[menu->current]))) {
3359         const char *warn_s;
3360         char buff[LONG_STRING];
3361
3362         if (key_table[menu->current]->flags & KEYFLAG_CANTUSE)
3363           s = N_("ID is expired/disabled/revoked.");
3364         else {
3365           gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
3366           gpgme_user_id_t uid = NULL;
3367           int j = 0;
3368
3369           warn_s = "??";
3370
3371           uid = key_table[menu->current]->kobj->uids;
3372           for (j = 0; (j < key_table[menu->current]->idx) && uid;
3373                j++, uid = uid->next);
3374           if (uid)
3375             val = uid->validity;
3376
3377           switch (val) {
3378           case GPGME_VALIDITY_UNKNOWN:
3379           case GPGME_VALIDITY_UNDEFINED:
3380             warn_s = N_("ID has undefined validity.");
3381             break;
3382           case GPGME_VALIDITY_NEVER:
3383             warn_s = N_("ID is not valid.");
3384             break;
3385           case GPGME_VALIDITY_MARGINAL:
3386             warn_s = N_("ID is only marginally valid.");
3387             break;
3388           case GPGME_VALIDITY_FULL:
3389           case GPGME_VALIDITY_ULTIMATE:
3390             break;
3391           }
3392
3393           snprintf (buff, sizeof (buff),
3394                     _("%s Do you really want to use the key?"), _(warn_s));
3395
3396           if (mutt_yesorno (buff, 0) != 1) {
3397             mutt_clear_error ();
3398             break;
3399           }
3400           *forced_valid = 1;
3401         }
3402       }
3403
3404       k = crypt_copy_key (key_table[menu->current]);
3405       done = 1;
3406       break;
3407
3408     case OP_EXIT:
3409       k = NULL;
3410       done = 1;
3411       break;
3412     }
3413   }
3414
3415   mutt_menuDestroy (&menu);
3416   p_delete(&key_table);
3417
3418   set_option (OPTNEEDREDRAW);
3419
3420   return k;
3421 }
3422
3423 static crypt_key_t *crypt_getkeybyaddr (address_t * a, short abilities,
3424                                         unsigned int app, int *forced_valid)
3425 {
3426   address_t *r, *p;
3427   string_list_t *hints = NULL;
3428
3429   int weak = 0;
3430   int invalid = 0;
3431   int multi = 0;
3432   int this_key_has_strong;
3433   int this_key_has_weak;
3434   int this_key_has_invalid;
3435   int match;
3436
3437   crypt_key_t *keys, *k;
3438   crypt_key_t *the_valid_key = NULL;
3439   crypt_key_t *matches = NULL;
3440   crypt_key_t **matches_endp = &matches;
3441
3442   *forced_valid = 0;
3443
3444   if (a && a->mailbox)
3445     hints = crypt_add_string_to_hints (hints, a->mailbox);
3446   if (a && a->personal)
3447     hints = crypt_add_string_to_hints (hints, a->personal);
3448
3449   mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
3450   keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
3451
3452   string_list_wipe(&hints);
3453
3454   if (!keys)
3455     return NULL;
3456
3457   debug_print (5, ("looking for %s <%s>.\n", a->personal, a->mailbox));
3458
3459   for (k = keys; k; k = k->next) {
3460     debug_print (5, ("  looking at key: %s `%.15s'\n", crypt_keyid (k), k->uid));
3461
3462     if (abilities && !(k->flags & abilities)) {
3463       debug_print (5, ("  insufficient abilities: Has %x, want %x\n", k->flags, abilities));
3464       continue;
3465     }
3466
3467     this_key_has_weak = 0;      /* weak but valid match   */
3468     this_key_has_invalid = 0;   /* invalid match          */
3469     this_key_has_strong = 0;    /* strong and valid match */
3470     match = 0;                  /* any match            */
3471
3472     r = rfc822_parse_adrlist (NULL, k->uid);
3473     for (p = r; p; p = p->next) {
3474       int validity = crypt_id_matches_addr (a, p, k);
3475
3476       if (validity & CRYPT_KV_MATCH)    /* something matches */
3477         match = 1;
3478
3479       /* is this key a strong candidate? */
3480       if ((validity & CRYPT_KV_VALID)
3481           && (validity & CRYPT_KV_STRONGID)
3482           && (validity & CRYPT_KV_ADDR)) {
3483         if (the_valid_key && the_valid_key != k)
3484           multi = 1;
3485         the_valid_key = k;
3486         this_key_has_strong = 1;
3487       }
3488       else if ((validity & CRYPT_KV_MATCH)
3489                && !(validity & CRYPT_KV_VALID))
3490         this_key_has_invalid = 1;
3491       else if ((validity & CRYPT_KV_MATCH)
3492                && (!(validity & CRYPT_KV_STRONGID)
3493                    || !(validity & CRYPT_KV_ADDR)))
3494         this_key_has_weak = 1;
3495     }
3496     address_list_wipe(&r);
3497
3498     if (match) {
3499       crypt_key_t *tmp;
3500
3501       if (!this_key_has_strong && this_key_has_invalid)
3502         invalid = 1;
3503       if (!this_key_has_strong && this_key_has_weak)
3504         weak = 1;
3505
3506       *matches_endp = tmp = crypt_copy_key (k);
3507       matches_endp = &tmp->next;
3508       the_valid_key = tmp;
3509     }
3510   }
3511
3512   crypt_free_key (&keys);
3513
3514   if (matches) {
3515     if (the_valid_key && !multi && !weak
3516         && !(invalid && option (OPTPGPSHOWUNUSABLE))) {
3517       /* 
3518        * There was precisely one strong match on a valid ID, there
3519        * were no valid keys with weak matches, and we aren't
3520        * interested in seeing invalid keys.
3521        * 
3522        * Proceed without asking the user.
3523        */
3524       k = crypt_copy_key (the_valid_key);
3525     }
3526     else {
3527       /* 
3528        * Else: Ask the user.
3529        */
3530       k = crypt_select_key (matches, a, NULL, app, forced_valid);
3531     }
3532     crypt_free_key (&matches);
3533   }
3534   else
3535     k = NULL;
3536
3537   return k;
3538 }
3539
3540
3541 static crypt_key_t *crypt_getkeybystr (char *p, short abilities,
3542                                        unsigned int app, int *forced_valid)
3543 {
3544   string_list_t *hints = NULL;
3545   crypt_key_t *keys;
3546   crypt_key_t *matches = NULL;
3547   crypt_key_t **matches_endp = &matches;
3548   crypt_key_t *k;
3549   int match;
3550
3551   mutt_message (_("Looking for keys matching \"%s\"..."), p);
3552
3553   *forced_valid = 0;
3554
3555   hints = crypt_add_string_to_hints (hints, p);
3556   keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
3557   string_list_wipe(&hints);
3558
3559   if (!keys)
3560     return NULL;
3561
3562   for (k = keys; k; k = k->next) {
3563     if (abilities && !(k->flags & abilities))
3564       continue;
3565
3566     match = 0;
3567     debug_print (5, ("matching \"%s\" against " "key %s, \"%s\":\n", p, crypt_keyid (k), k->uid));
3568
3569     if (!*p || !m_strcasecmp(p, crypt_keyid (k))
3570         || (!m_strncasecmp(p, "0x", 2)
3571             && !m_strcasecmp(p + 2, crypt_keyid (k)))
3572         || (option (OPTPGPLONGIDS)
3573             && !m_strncasecmp(p, "0x", 2)
3574             && !m_strcasecmp(p + 2, crypt_keyid (k) + 8))
3575         || m_stristr(k->uid, p)) {
3576       crypt_key_t *tmp;
3577
3578       debug_print (5, ("match.\n"));
3579
3580       *matches_endp = tmp = crypt_copy_key (k);
3581       matches_endp = &tmp->next;
3582     }
3583   }
3584
3585   crypt_free_key (&keys);
3586
3587   if (matches) {
3588     k = crypt_select_key (matches, NULL, p, app, forced_valid);
3589     crypt_free_key (&matches);
3590     return k;
3591   }
3592
3593   return NULL;
3594 }
3595
3596 /* Display TAG as a prompt to ask for a key.  If WHATFOR is not null
3597    use it as default and store it under that label as the next
3598    default.  ABILITIES describe the required key abilities (sign,
3599    encrypt) and APP the type of the requested key; ether S/MIME or
3600    PGP.  Return a copy of the key or NULL if not found. */
3601 static crypt_key_t *crypt_ask_for_key (char *tag,
3602                                        char *whatfor,
3603                                        short abilities,
3604                                        unsigned int app, int *forced_valid)
3605 {
3606   crypt_key_t *key;
3607   char resp[SHORT_STRING];
3608   struct crypt_cache *l = NULL;
3609   int dummy;
3610
3611   if (!forced_valid)
3612     forced_valid = &dummy;
3613
3614   mutt_clear_error ();
3615
3616   *forced_valid = 0;
3617   resp[0] = 0;
3618   if (whatfor) {
3619
3620     for (l = id_defaults; l; l = l->next)
3621       if (!m_strcasecmp(whatfor, l->what)) {
3622         m_strcpy(resp, sizeof(resp), NONULL(l->dflt));
3623         break;
3624       }
3625   }
3626
3627
3628   for (;;) {
3629     resp[0] = 0;
3630     if (mutt_get_field (tag, resp, sizeof (resp), M_CLEAR) != 0)
3631       return NULL;
3632
3633     if (whatfor) {
3634       if (l)
3635         m_strreplace(&l->dflt, resp);
3636       else {
3637         l = p_new(struct crypt_cache, 1);
3638         l->next = id_defaults;
3639         id_defaults = l;
3640         l->what = m_strdup(whatfor);
3641         l->dflt = m_strdup(resp);
3642       }
3643     }
3644
3645     if ((key = crypt_getkeybystr (resp, abilities, app, forced_valid)))
3646       return key;
3647
3648     BEEP ();
3649   }
3650   /* not reached */
3651 }
3652
3653 /* This routine attempts to find the keyids of the recipients of a
3654    message.  It returns NULL if any of the keys can not be found.  */
3655 static char *find_keys (address_t * to, address_t * cc, address_t * bcc,
3656                         unsigned int app)
3657 {
3658   char *keyID, *keylist = NULL, *t;
3659   ssize_t keylist_size = 0;
3660   ssize_t keylist_used = 0;
3661   address_t *tmp = NULL, *addr = NULL;
3662   address_t **last = &tmp;
3663   address_t *p, *q;
3664   int i;
3665   crypt_key_t *k_info, *key;
3666   const char *fqdn = mutt_fqdn (1);
3667
3668 #if 0
3669   *r_application = APPLICATION_PGP | APPLICATION_SMIME;
3670 #endif
3671
3672   for (i = 0; i < 3; i++) {
3673     switch (i) {
3674     case 0:
3675       p = to;
3676       break;
3677     case 1:
3678       p = cc;
3679       break;
3680     case 2:
3681       p = bcc;
3682       break;
3683     default:
3684       abort ();
3685     }
3686
3687     *last = address_list_dup (p);
3688     while (*last)
3689       last = &((*last)->next);
3690   }
3691
3692   if (fqdn)
3693     rfc822_qualify (tmp, fqdn);
3694
3695   tmp = mutt_remove_duplicates (tmp);
3696
3697   for (p = tmp; p; p = p->next) {
3698     char buf[LONG_STRING];
3699     int forced_valid = 0;
3700
3701     q = p;
3702     k_info = NULL;
3703
3704     if ((keyID = mutt_crypt_hook (p)) != NULL) {
3705       int r;
3706
3707       snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"),
3708                 keyID, p->mailbox);
3709       if ((r = mutt_yesorno (buf, M_YES)) == M_YES) {
3710         /* check for e-mail address */
3711         if ((t = strchr (keyID, '@')) &&
3712             (addr = rfc822_parse_adrlist (NULL, keyID))) {
3713           if (fqdn)
3714             rfc822_qualify (addr, fqdn);
3715           q = addr;
3716         }
3717         else {
3718 #if 0
3719           k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
3720                                       *r_application, &forced_valid);
3721 #else
3722           k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
3723                                       app, &forced_valid);
3724 #endif
3725         }
3726       }
3727       else if (r == -1) {
3728         p_delete(&keylist);
3729         address_list_wipe(&tmp);
3730         address_list_wipe(&addr);
3731         return NULL;
3732       }
3733     }
3734
3735     if (k_info == NULL
3736         && (k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT,
3737                                          app, &forced_valid)) == NULL) {
3738       snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
3739
3740       if ((key = crypt_ask_for_key (buf, q->mailbox, KEYFLAG_CANENCRYPT,
3741 #if 0
3742                                     *r_application,
3743 #else
3744                                     app,
3745 #endif
3746                                     &forced_valid)) == NULL) {
3747         p_delete(&keylist);
3748         address_list_wipe(&tmp);
3749         address_list_wipe(&addr);
3750         return NULL;
3751       }
3752     }
3753     else
3754       key = k_info;
3755
3756     {
3757       const char *s = crypt_fpr (key);
3758
3759 #if 0
3760       if (key->flags & KEYFLAG_ISX509)
3761         *r_application &= ~APPLICATION_PGP;
3762       if (!(key->flags & KEYFLAG_ISX509))
3763         *r_application &= ~APPLICATION_SMIME;
3764 #endif
3765
3766       keylist_size += m_strlen(s) + 4 + 1;
3767       p_realloc(&keylist, keylist_size);
3768       sprintf (keylist + keylist_used, "%s0x%s%s",      /* __SPRINTF_CHECKED__ */
3769                keylist_used ? " " : "", s, forced_valid ? "!" : "");
3770     }
3771     keylist_used = m_strlen(keylist);
3772
3773     crypt_free_key (&key);
3774     address_list_wipe(&addr);
3775   }
3776   address_list_wipe(&tmp);
3777   return (keylist);
3778 }