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