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