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