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