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