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