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