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