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