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