]> git.llucax.com Git - software/mutt-debian.git/blob - pgp.c
Imported Upstream version 1.5.19
[software/mutt-debian.git] / pgp.c
1 /*
2  * Copyright (C) 1996-7,2000 Michael R. Elkins <me@mutt.org>
3  * Copyright (C) 1998-2005 Thomas Roessler <roessler@does-not-exist.org>
4  * Copyright (C) 2004 g10 Code GmbH
5  *
6  *     This program is free software; you can redistribute it and/or modify
7  *     it under the terms of the GNU General Public License as published by
8  *     the Free Software Foundation; either version 2 of the License, or
9  *     (at your option) any later version.
10  * 
11  *     This program is distributed in the hope that it will be useful,
12  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *     GNU General Public License for more details.
15  * 
16  *     You should have received a copy of the GNU General Public License
17  *     along with this program; if not, write to the Free Software
18  *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */ 
20
21 /*
22  * This file contains all of the PGP routines necessary to sign, encrypt,
23  * verify and decrypt PGP messages in either the new PGP/MIME format, or
24  * in the older Application/Pgp format.  It also contains some code to
25  * cache the user's passphrase for repeat use when decrypting or signing
26  * a message.
27  */
28
29 #if HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include "mutt.h"
34 #include "mutt_curses.h"
35 #include "pgp.h"
36 #include "mime.h"
37 #include "copy.h"
38
39 #include <sys/wait.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include <sys/stat.h>
44 #include <errno.h>
45 #include <ctype.h>
46
47 #ifdef HAVE_LOCALE_H
48 #include <locale.h>
49 #endif
50
51 #ifdef HAVE_SYS_TIME_H
52 # include <sys/time.h>
53 #endif
54
55 #ifdef HAVE_SYS_RESOURCE_H
56 # include <sys/resource.h>
57 #endif
58
59 #ifdef CRYPT_BACKEND_CLASSIC_PGP
60
61 #include "mutt_crypt.h"
62 #include "mutt_menu.h"
63
64
65 char PgpPass[LONG_STRING];
66 time_t PgpExptime = 0; /* when does the cached passphrase expire? */
67
68 void pgp_void_passphrase (void)
69 {
70   memset (PgpPass, 0, sizeof (PgpPass));
71   PgpExptime = 0;
72 }
73
74 int pgp_valid_passphrase (void)
75 {
76   time_t now = time (NULL);
77
78   if (pgp_use_gpg_agent())
79     {
80       *PgpPass = 0;
81       return 1; /* handled by gpg-agent */
82     }
83
84   if (now < PgpExptime)
85     /* Use cached copy.  */
86     return 1;
87   
88   pgp_void_passphrase ();
89
90   if (mutt_get_password (_("Enter PGP passphrase:"), PgpPass, sizeof (PgpPass)) == 0)
91     {
92       PgpExptime = time (NULL) + PgpTimeout;
93       return (1);
94     }
95   else
96     PgpExptime = 0;
97
98   return 0;
99 }
100
101 void pgp_forget_passphrase (void)
102 {
103   pgp_void_passphrase ();
104   mutt_message _("PGP passphrase forgotten.");
105 }
106
107 int pgp_use_gpg_agent (void)
108 {
109   char *tty;
110
111   if (!option (OPTUSEGPGAGENT) || !getenv ("GPG_AGENT_INFO"))
112     return 0;
113
114   if ((tty = ttyname(0)))
115     setenv("GPG_TTY", tty, 0);
116
117   return 1;
118 }
119
120 char *pgp_keyid(pgp_key_t k)
121 {
122   if((k->flags & KEYFLAG_SUBKEY) && k->parent && option(OPTPGPIGNORESUB))
123     k = k->parent;
124
125   return _pgp_keyid(k);
126 }
127
128 char *_pgp_keyid(pgp_key_t k)
129 {
130   if(option(OPTPGPLONGIDS))
131     return k->keyid;
132   else
133     return (k->keyid + 8);
134 }
135
136 /* ----------------------------------------------------------------------------
137  * Routines for handing PGP input.
138  */
139
140
141
142 /* Copy PGP output messages and look for signs of a good signature */
143
144 static int pgp_copy_checksig (FILE *fpin, FILE *fpout)
145 {
146   int rv = -1;
147
148   if (PgpGoodSign.pattern)
149   {
150     char *line = NULL;
151     int lineno = 0;
152     size_t linelen;
153     
154     while ((line = mutt_read_line (line, &linelen, fpin, &lineno)) != NULL)
155     {
156       if (regexec (PgpGoodSign.rx, line, 0, NULL, 0) == 0)
157       {
158         dprint (2, (debugfile, "pgp_copy_checksig: \"%s\" matches regexp.\n",
159                     line));
160         rv = 0;
161       }
162       else
163         dprint (2, (debugfile, "pgp_copy_checksig: \"%s\" doesn't match regexp.\n",
164                     line));
165       
166       if (strncmp (line, "[GNUPG:] ", 9) == 0)
167         continue;
168       fputs (line, fpout);
169       fputc ('\n', fpout);
170     }
171     FREE (&line);
172   }
173   else
174   {
175     dprint (2, (debugfile, "pgp_copy_checksig: No pattern.\n"));
176     mutt_copy_stream (fpin, fpout);
177     rv = 1;
178   }
179
180   return rv;
181 }
182
183 /* 
184  * Copy a clearsigned message, and strip the signature and PGP's
185  * dash-escaping.
186  * 
187  * XXX - charset handling: We assume that it is safe to do
188  * character set decoding first, dash decoding second here, while
189  * we do it the other way around in the main handler.
190  * 
191  * (Note that we aren't worse than Outlook &c in this, and also
192  * note that we can successfully handle anything produced by any
193  * existing versions of mutt.) 
194  */
195
196 static void pgp_copy_clearsigned (FILE *fpin, STATE *s, char *charset)
197 {
198   char buf[HUGE_STRING];
199   short complete, armor_header;
200   
201   FGETCONV *fc;
202   
203   rewind (fpin);
204
205   /* fromcode comes from the MIME Content-Type charset label. It might
206    * be a wrong label, so we want the ability to do corrections via
207    * charset-hooks. Therefore we set flags to M_ICONV_HOOK_FROM.
208    */
209   fc = fgetconv_open (fpin, charset, Charset, M_ICONV_HOOK_FROM);
210   
211   for (complete = 1, armor_header = 1;
212        fgetconvs (buf, sizeof (buf), fc) != NULL;
213        complete = strchr (buf, '\n') != NULL)
214   {
215     if (!complete)
216     {
217       if (!armor_header)
218         state_puts (buf, s);
219       continue;
220     }
221
222     if (mutt_strcmp (buf, "-----BEGIN PGP SIGNATURE-----\n") == 0)
223       break;
224     
225     if (armor_header)
226     {
227       char *p = mutt_skip_whitespace (buf);
228       if (*p == '\0') 
229         armor_header = 0;
230       continue;
231     }
232     
233     if (s->prefix) 
234       state_puts (s->prefix, s);
235     
236     if (buf[0] == '-' && buf[1] == ' ')
237       state_puts (buf + 2, s);
238     else
239       state_puts (buf, s);
240   }
241   
242   fgetconv_close (&fc);
243 }
244
245
246 /* Support for the Application/PGP Content Type. */
247
248 int pgp_application_pgp_handler (BODY *m, STATE *s)
249 {
250   int could_not_decrypt = 0;
251   int needpass = -1, pgp_keyblock = 0;
252   int clearsign = 0, rv, rc;
253   int c = 1; /* silence GCC warning */
254   long start_pos = 0;
255   long bytes;
256   LOFF_T last_pos, offset;
257   char buf[HUGE_STRING];
258   char outfile[_POSIX_PATH_MAX];
259   char tmpfname[_POSIX_PATH_MAX];
260   FILE *pgpout = NULL, *pgpin = NULL, *pgperr = NULL;
261   FILE *tmpfp = NULL;
262   pid_t thepid;
263
264   short maybe_goodsig = 1;
265   short have_any_sigs = 0;
266
267   char body_charset[STRING];
268   mutt_get_body_charset (body_charset, sizeof (body_charset), m);
269
270   rc = 0;       /* silence false compiler warning if (s->flags & M_DISPLAY) */
271
272   fseeko (s->fpin, m->offset, 0);
273   last_pos = m->offset;
274   
275   for (bytes = m->length; bytes > 0;)
276   {
277     if (fgets (buf, sizeof (buf), s->fpin) == NULL)
278       break;
279     
280     offset = ftello (s->fpin);
281     bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */
282     last_pos = offset;
283     
284     if (mutt_strncmp ("-----BEGIN PGP ", buf, 15) == 0)
285     {
286       clearsign = 0;
287       start_pos = last_pos;
288
289       if (mutt_strcmp ("MESSAGE-----\n", buf + 15) == 0)
290         needpass = 1;
291       else if (mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15) == 0)
292       {
293         clearsign = 1;
294         needpass = 0;
295       }
296       else if (!mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15))
297       {
298         needpass = 0;
299         pgp_keyblock = 1;
300       } 
301       else
302       {
303         /* XXX - we may wish to recode here */
304         if (s->prefix)
305           state_puts (s->prefix, s);
306         state_puts (buf, s);
307         continue;
308       }
309
310       have_any_sigs = have_any_sigs || (clearsign && (s->flags & M_VERIFY));
311
312       /* Copy PGP material to temporary file */
313       mutt_mktemp (tmpfname);
314       if ((tmpfp = safe_fopen (tmpfname, "w+")) == NULL)
315       {
316         mutt_perror (tmpfname);
317         return -1;
318       }
319       
320       fputs (buf, tmpfp);
321       while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL)
322       {
323         offset = ftello (s->fpin);
324         bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */
325         last_pos = offset;
326         
327         fputs (buf, tmpfp);
328
329         if ((needpass && mutt_strcmp ("-----END PGP MESSAGE-----\n", buf) == 0) ||
330             (!needpass 
331              && (mutt_strcmp ("-----END PGP SIGNATURE-----\n", buf) == 0
332                  || mutt_strcmp ("-----END PGP PUBLIC KEY BLOCK-----\n",buf) == 0)))
333           break;
334       }
335
336       /* leave tmpfp open in case we still need it - but flush it! */
337       fflush (tmpfp);
338
339       /* Invoke PGP if needed */
340       if (!clearsign || (s->flags & M_VERIFY))
341       {
342         mutt_mktemp (outfile);
343         if ((pgpout = safe_fopen (outfile, "w+")) == NULL)
344         {
345           mutt_perror (tmpfname);
346           return -1;
347         }
348         
349         if ((thepid = pgp_invoke_decode (&pgpin, NULL, &pgperr, -1,
350                                          fileno (pgpout), -1, tmpfname,
351                                          needpass)) == -1)
352         {
353           safe_fclose (&pgpout);
354           maybe_goodsig = 0;
355           pgpin = NULL;
356           pgperr = NULL;
357           state_attach_puts (_("[-- Error: unable to create PGP subprocess! --]\n"), s);
358         }
359         else /* PGP started successfully */
360         {
361           if (needpass)
362           {
363             if (!pgp_valid_passphrase ()) pgp_void_passphrase();
364             if (pgp_use_gpg_agent())
365               *PgpPass = 0;
366             fprintf (pgpin, "%s\n", PgpPass);
367           }
368           
369           safe_fclose (&pgpin);
370
371           if (s->flags & M_DISPLAY)
372           {
373             crypt_current_time (s, "PGP");
374             rc = pgp_copy_checksig (pgperr, s->fpout);
375           }
376           
377           safe_fclose (&pgperr);
378           rv = mutt_wait_filter (thepid);
379           
380           if (s->flags & M_DISPLAY)
381           {
382             if (rc == 0) have_any_sigs = 1;
383             /*
384              * Sig is bad if
385              * gpg_good_sign-pattern did not match || pgp_decode_command returned not 0
386              * Sig _is_ correct if
387              *  gpg_good_sign="" && pgp_decode_command returned 0
388              */
389             if (rc == -1 || rv) maybe_goodsig = 0;
390             
391             state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
392           }
393         }
394         
395         /* treat empty result as sign of failure */
396         /* TODO: maybe on failure mutt should include the original undecoded text. */
397         if (pgpout)
398         {
399           rewind (pgpout);
400           c = fgetc (pgpout);
401           ungetc (c, pgpout);
402         }
403         if (!clearsign && (!pgpout || c == EOF))
404         {
405           could_not_decrypt = 1;
406           pgp_void_passphrase ();
407         }
408         
409         if (could_not_decrypt && !(s->flags & M_DISPLAY))
410         {
411           mutt_error _("Could not decrypt PGP message");
412           mutt_sleep (1);
413           rc = -1;
414           goto out;
415         }
416       }
417       
418       /*
419        * Now, copy cleartext to the screen.  NOTE - we expect that PGP
420        * outputs utf-8 cleartext.  This may not always be true, but it 
421        * seems to be a reasonable guess.
422        */
423
424       if(s->flags & M_DISPLAY)
425       {
426         if (needpass)
427           state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s);
428         else if (pgp_keyblock)
429           state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"), s);
430         else
431           state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"), s);
432       }
433
434       if (clearsign)
435       {
436         rewind (tmpfp);
437         if (tmpfp) 
438           pgp_copy_clearsigned (tmpfp, s, body_charset);
439       }
440       else if (pgpout)
441       {
442         FGETCONV *fc;
443         int c;
444         rewind (pgpout);
445         state_set_prefix (s);
446         fc = fgetconv_open (pgpout, "utf-8", Charset, 0);
447         while ((c = fgetconv (fc)) != EOF)
448           state_prefix_putc (c, s);
449         fgetconv_close (&fc);
450       }
451
452       if (s->flags & M_DISPLAY)
453       {
454         state_putc ('\n', s);
455         if (needpass)
456         {
457           state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
458           if (could_not_decrypt)
459             mutt_error _("Could not decrypt PGP message");
460           else
461             mutt_message _("PGP message successfully decrypted.");
462         }
463         else if (pgp_keyblock)
464           state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);
465         else
466           state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);
467       }
468     }
469 #if 0
470     else
471     {
472       /* why would we want to display this at all? */
473       /* XXX - we may wish to recode here */
474       if (s->prefix)
475         state_puts (s->prefix, s);
476       state_puts (buf, s);
477     }
478 #endif
479   }
480
481   rc = 0;
482
483 out:
484   m->goodsig = (maybe_goodsig && have_any_sigs);
485
486   if (tmpfp)
487   {
488     safe_fclose (&tmpfp);
489     mutt_unlink (tmpfname);
490   }
491   if (pgpout)
492   {
493     safe_fclose (&pgpout);
494     mutt_unlink (outfile);
495   }
496   
497   if (needpass == -1)
498   {
499     state_attach_puts (_("[-- Error: could not find beginning of PGP message! --]\n\n"), s);
500     return -1;
501   }
502   
503   return rc;
504 }
505
506 static int pgp_check_traditional_one_body (FILE *fp, BODY *b, int tagged_only)
507 {
508   char tempfile[_POSIX_PATH_MAX];
509   char buf[HUGE_STRING];
510   FILE *tfp;
511   
512   short sgn = 0;
513   short enc = 0;
514   short key = 0;
515   
516   if (b->type != TYPETEXT)
517     return 0;
518
519   if (tagged_only && !b->tagged)
520     return 0;
521
522   mutt_mktemp (tempfile);
523   if (mutt_decode_save_attachment (fp, b, tempfile, 0, 0) != 0)
524   {
525     unlink (tempfile);
526     return 0;
527   }
528   
529   if ((tfp = fopen (tempfile, "r")) == NULL)
530   {
531     unlink (tempfile);
532     return 0;
533   }
534   
535   while (fgets (buf, sizeof (buf), tfp))
536   {
537     if (mutt_strncmp ("-----BEGIN PGP ", buf, 15) == 0)
538     {
539       if (mutt_strcmp ("MESSAGE-----\n", buf + 15) == 0)
540         enc = 1;
541       else if (mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15) == 0)
542         sgn = 1;
543       else if (mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15) == 0)
544         key = 1;
545     }
546   }
547   safe_fclose (&tfp);
548   unlink (tempfile);
549
550   if (!enc && !sgn && !key)
551     return 0;
552
553   /* fix the content type */
554   
555   mutt_set_parameter ("format", "fixed", &b->parameter);
556   if (enc)
557     mutt_set_parameter ("x-action", "pgp-encrypted", &b->parameter);
558   else if (sgn)
559     mutt_set_parameter ("x-action", "pgp-signed", &b->parameter);
560   else if (key)
561     mutt_set_parameter ("x-action", "pgp-keys", &b->parameter);
562   
563   return 1;
564 }
565
566 int pgp_check_traditional (FILE *fp, BODY *b, int tagged_only)
567 {
568   int rv = 0;
569   int r;
570   for (; b; b = b->next)
571   {
572     if (is_multipart (b))
573       rv = pgp_check_traditional (fp, b->parts, tagged_only) || rv;
574     else if (b->type == TYPETEXT)
575     {
576       if ((r = mutt_is_application_pgp (b)))
577         rv = rv || r;
578       else
579         rv = pgp_check_traditional_one_body (fp, b, tagged_only) || rv;
580     }
581   }
582
583   return rv;
584 }
585
586      
587
588
589
590 int pgp_verify_one (BODY *sigbdy, STATE *s, const char *tempfile)
591 {
592   char sigfile[_POSIX_PATH_MAX], pgperrfile[_POSIX_PATH_MAX];
593   FILE *fp, *pgpout, *pgperr;
594   pid_t thepid;
595   int badsig = -1;
596   int rv;
597   
598   snprintf (sigfile, sizeof (sigfile), "%s.asc", tempfile);
599   
600   if(!(fp = safe_fopen (sigfile, "w")))
601   {
602     mutt_perror(sigfile);
603     return -1;
604   }
605         
606   fseeko (s->fpin, sigbdy->offset, 0);
607   mutt_copy_bytes (s->fpin, fp, sigbdy->length);
608   fclose (fp);
609   
610   mutt_mktemp(pgperrfile);
611   if(!(pgperr = safe_fopen(pgperrfile, "w+")))
612   {
613     mutt_perror(pgperrfile);
614     unlink(sigfile);
615     return -1;
616   }
617   
618   crypt_current_time (s, "PGP");
619   
620   if((thepid = pgp_invoke_verify (NULL, &pgpout, NULL, 
621                                    -1, -1, fileno(pgperr),
622                                    tempfile, sigfile)) != -1)
623   {
624     if (pgp_copy_checksig (pgpout, s->fpout) >= 0)
625       badsig = 0;
626     
627     
628     safe_fclose (&pgpout);
629     fflush (pgperr);
630     rewind (pgperr);
631     
632     if (pgp_copy_checksig  (pgperr, s->fpout) >= 0)
633       badsig = 0;
634
635     if ((rv = mutt_wait_filter (thepid)))
636       badsig = -1;
637     
638      dprint (1, (debugfile, "pgp_verify_one: mutt_wait_filter returned %d.\n", rv));
639   }
640
641   safe_fclose (&pgperr);
642
643   state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
644
645   mutt_unlink (sigfile);
646   mutt_unlink (pgperrfile);
647
648   dprint (1, (debugfile, "pgp_verify_one: returning %d.\n", badsig));
649   
650   return badsig;
651 }
652
653
654 /* Extract pgp public keys from messages or attachments */
655
656 void pgp_extract_keys_from_messages (HEADER *h)
657 {
658   int i;
659   char tempfname[_POSIX_PATH_MAX];
660   FILE *fpout;
661
662   if (h)
663   {
664     mutt_parse_mime_message (Context, h);
665     if(h->security & PGPENCRYPT && !pgp_valid_passphrase ())
666       return;
667   }
668
669   mutt_mktemp (tempfname);
670   if (!(fpout = safe_fopen (tempfname, "w")))
671   {
672     mutt_perror (tempfname);
673     return;
674   }
675
676   set_option (OPTDONTHANDLEPGPKEYS);
677   
678   if (!h)
679   {
680     for (i = 0; i < Context->vcount; i++)
681     {
682       if (Context->hdrs[Context->v2r[i]]->tagged)
683       {
684         mutt_parse_mime_message (Context, Context->hdrs[Context->v2r[i]]);
685         if (Context->hdrs[Context->v2r[i]]->security & PGPENCRYPT
686            && !pgp_valid_passphrase())
687         {
688           fclose (fpout);
689           goto bailout;
690         }
691         mutt_copy_message (fpout, Context, Context->hdrs[Context->v2r[i]], 
692                            M_CM_DECODE|M_CM_CHARCONV, 0);
693       }
694     }
695   } 
696   else
697   {
698     mutt_parse_mime_message (Context, h);
699     if (h->security & PGPENCRYPT && !pgp_valid_passphrase())
700     {
701       fclose (fpout);
702       goto bailout;
703     }
704     mutt_copy_message (fpout, Context, h, M_CM_DECODE|M_CM_CHARCONV, 0);
705   }
706       
707   fclose (fpout);
708   mutt_endwin (NULL);
709   pgp_invoke_import (tempfname);
710   mutt_any_key_to_continue (NULL);
711
712   bailout:
713   
714   mutt_unlink (tempfname);
715   unset_option (OPTDONTHANDLEPGPKEYS);
716   
717 }
718
719 static void pgp_extract_keys_from_attachment (FILE *fp, BODY *top)
720 {
721   STATE s;
722   FILE *tempfp;
723   char tempfname[_POSIX_PATH_MAX];
724
725   mutt_mktemp (tempfname);
726   if (!(tempfp = safe_fopen (tempfname, "w")))
727   {
728     mutt_perror (tempfname);
729     return;
730   }
731
732   memset (&s, 0, sizeof (STATE));
733   
734   s.fpin = fp;
735   s.fpout = tempfp;
736   
737   mutt_body_handler (top, &s);
738
739   fclose (tempfp);
740
741   pgp_invoke_import (tempfname);
742   mutt_any_key_to_continue (NULL);
743
744   mutt_unlink (tempfname);
745 }
746
747 void pgp_extract_keys_from_attachment_list (FILE *fp, int tag, BODY *top)
748 {
749   if(!fp)
750   {
751     mutt_error _("Internal error. Inform <roessler@does-not-exist.org>.");
752     return;
753   }
754
755   mutt_endwin (NULL);
756   set_option(OPTDONTHANDLEPGPKEYS);
757   
758   for(; top; top = top->next)
759   {
760     if(!tag || top->tagged)
761       pgp_extract_keys_from_attachment (fp, top);
762     
763     if(!tag)
764       break;
765   }
766   
767   unset_option(OPTDONTHANDLEPGPKEYS);
768 }
769
770 BODY *pgp_decrypt_part (BODY *a, STATE *s, FILE *fpout, BODY *p)
771 {
772   char buf[LONG_STRING];
773   FILE *pgpin, *pgpout, *pgperr, *pgptmp;
774   struct stat info;
775   BODY *tattach;
776   int len;
777   char pgperrfile[_POSIX_PATH_MAX];
778   char pgptmpfile[_POSIX_PATH_MAX];
779   pid_t thepid;
780   int rv;
781   
782   mutt_mktemp (pgperrfile);
783   if ((pgperr = safe_fopen (pgperrfile, "w+")) == NULL)
784   {
785     mutt_perror (pgperrfile);
786     return NULL;
787   }
788   unlink (pgperrfile);
789
790   mutt_mktemp (pgptmpfile);
791   if((pgptmp = safe_fopen (pgptmpfile, "w")) == NULL)
792   {
793     mutt_perror (pgptmpfile);
794     fclose(pgperr);
795     return NULL;
796   }
797
798   /* Position the stream at the beginning of the body, and send the data to
799    * the temporary file.
800    */
801
802   fseeko (s->fpin, a->offset, 0);
803   mutt_copy_bytes (s->fpin, pgptmp, a->length);
804   fclose (pgptmp);
805
806   if ((thepid = pgp_invoke_decrypt (&pgpin, &pgpout, NULL, -1, -1,
807                                     fileno (pgperr), pgptmpfile)) == -1)
808   {
809     fclose (pgperr);
810     unlink (pgptmpfile);
811     if (s->flags & M_DISPLAY)
812       state_attach_puts (_("[-- Error: could not create a PGP subprocess! --]\n\n"), s);
813     return (NULL);
814   }
815
816   /* send the PGP passphrase to the subprocess.  Never do this if the
817      agent is active, because this might lead to a passphrase send as
818      the message. */
819   if (!pgp_use_gpg_agent())
820     fputs (PgpPass, pgpin);
821   fputc ('\n', pgpin);
822   fclose(pgpin);
823   
824   /* Read the output from PGP, and make sure to change CRLF to LF, otherwise
825    * read_mime_header has a hard time parsing the message.
826    */
827   while (fgets (buf, sizeof (buf) - 1, pgpout) != NULL)
828   {
829     len = mutt_strlen (buf);
830     if (len > 1 && buf[len - 2] == '\r')
831       strcpy (buf + len - 2, "\n");     /* __STRCPY_CHECKED__ */
832     fputs (buf, fpout);
833   }
834
835   fclose (pgpout);
836   rv = mutt_wait_filter (thepid);
837   mutt_unlink(pgptmpfile);
838   
839   if (s->flags & M_DISPLAY)
840   {
841     fflush (pgperr);
842     rewind (pgperr);
843     if (pgp_copy_checksig (pgperr, s->fpout) == 0 && !rv && p)
844       p->goodsig = 1;
845     else
846       p->goodsig = 0;
847     state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
848   }
849   fclose (pgperr);
850
851   fflush (fpout);
852   rewind (fpout);
853
854   if (pgp_use_gpg_agent())
855     mutt_need_hard_redraw ();
856
857   if (fgetc (fpout) == EOF)
858   {
859     mutt_error _("Decryption failed");
860     pgp_void_passphrase ();
861     return NULL;
862   }
863
864   rewind (fpout);
865   
866   if ((tattach = mutt_read_mime_header (fpout, 0)) != NULL)
867   {
868     /*
869      * Need to set the length of this body part.
870      */
871     fstat (fileno (fpout), &info);
872     tattach->length = info.st_size - tattach->offset;
873
874     /* See if we need to recurse on this MIME part.  */
875
876     mutt_parse_part (fpout, tattach);
877   }
878
879   return (tattach);
880 }
881
882 int pgp_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur)
883 {
884   char tempfile[_POSIX_PATH_MAX];
885   STATE s;
886   BODY *p = b;
887   
888   if(!mutt_is_multipart_encrypted(b))
889     return -1;
890
891   if(!b->parts || !b->parts->next)
892     return -1;
893   
894   b = b->parts->next;
895   
896   memset (&s, 0, sizeof (s));
897   s.fpin = fpin;
898   mutt_mktemp (tempfile);
899   if ((*fpout = safe_fopen (tempfile, "w+")) == NULL)
900   {
901     mutt_perror (tempfile);
902     return (-1);
903   }
904   unlink (tempfile);
905
906   *cur = pgp_decrypt_part (b, &s, *fpout, p);
907
908   rewind (*fpout);
909   
910   if (!*cur)
911     return -1;
912   
913   return (0);
914 }
915
916 int pgp_encrypted_handler (BODY *a, STATE *s)
917 {
918   char tempfile[_POSIX_PATH_MAX];
919   FILE *fpout, *fpin;
920   BODY *tattach;
921   BODY *p = a;
922   int rc = 0;
923   
924   a = a->parts;
925   if (!a || a->type != TYPEAPPLICATION || !a->subtype || 
926       ascii_strcasecmp ("pgp-encrypted", a->subtype) != 0 ||
927       !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype ||
928       ascii_strcasecmp ("octet-stream", a->next->subtype) != 0)
929   {
930     if (s->flags & M_DISPLAY)
931       state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"), s);
932     return -1;
933   }
934
935   /*
936    * Move forward to the application/pgp-encrypted body.
937    */
938   a = a->next;
939
940   mutt_mktemp (tempfile);
941   if ((fpout = safe_fopen (tempfile, "w+")) == NULL)
942   {
943     if (s->flags & M_DISPLAY)
944       state_attach_puts (_("[-- Error: could not create temporary file! --]\n"), s);
945     return -1;
946   }
947
948   if (s->flags & M_DISPLAY) crypt_current_time (s, "PGP");
949
950   if ((tattach = pgp_decrypt_part (a, s, fpout, p)) != NULL)
951   {
952     if (s->flags & M_DISPLAY)
953       state_attach_puts (_("[-- The following data is PGP/MIME encrypted --]\n\n"), s);
954
955     fpin = s->fpin;
956     s->fpin = fpout;
957     rc = mutt_body_handler (tattach, s);
958     s->fpin = fpin;
959
960     /* 
961      * if a multipart/signed is the _only_ sub-part of a
962      * multipart/encrypted, cache signature verification
963      * status.
964      *
965      */
966     
967     if (mutt_is_multipart_signed (tattach) && !tattach->next)
968       p->goodsig |= tattach->goodsig;
969     
970     if (s->flags & M_DISPLAY)
971     {
972       state_puts ("\n", s);
973       state_attach_puts (_("[-- End of PGP/MIME encrypted data --]\n"), s);
974     }
975
976     mutt_free_body (&tattach);
977     /* clear 'Invoking...' message, since there's no error */
978     mutt_message _("PGP message successfully decrypted.");
979   }
980   else
981   {
982     mutt_error _("Could not decrypt PGP message");
983     /* void the passphrase, even if it's not necessarily the problem */
984     pgp_void_passphrase ();
985     rc = -1;
986   }
987
988   fclose (fpout);
989   mutt_unlink(tempfile);
990
991   return rc;
992 }
993
994 /* ----------------------------------------------------------------------------
995  * Routines for sending PGP/MIME messages.
996  */
997
998
999 BODY *pgp_sign_message (BODY *a)
1000 {
1001   BODY *t;
1002   char buffer[LONG_STRING];
1003   char sigfile[_POSIX_PATH_MAX], signedfile[_POSIX_PATH_MAX];
1004   FILE *pgpin, *pgpout, *pgperr, *fp, *sfp;
1005   int err = 0;
1006   int empty = 1;
1007   pid_t thepid;
1008   
1009   convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */
1010
1011   mutt_mktemp (sigfile);
1012   if ((fp = safe_fopen (sigfile, "w")) == NULL)
1013   {
1014     return (NULL);
1015   }
1016
1017   mutt_mktemp (signedfile);
1018   if ((sfp = safe_fopen(signedfile, "w")) == NULL)
1019   {
1020     mutt_perror(signedfile);
1021     fclose(fp);
1022     unlink(sigfile);
1023     return NULL;
1024   }
1025   
1026   mutt_write_mime_header (a, sfp);
1027   fputc ('\n', sfp);
1028   mutt_write_mime_body (a, sfp);
1029   fclose(sfp);
1030   
1031   if ((thepid = pgp_invoke_sign (&pgpin, &pgpout, &pgperr,
1032                                  -1, -1, -1, signedfile)) == -1)
1033   {
1034     mutt_perror _("Can't open PGP subprocess!");
1035     fclose(fp);
1036     unlink(sigfile);
1037     unlink(signedfile);
1038     return NULL;
1039   }
1040   
1041   if (!pgp_use_gpg_agent())
1042      fputs(PgpPass, pgpin);
1043   fputc('\n', pgpin);
1044   fclose(pgpin);
1045   
1046   /*
1047    * Read back the PGP signature.  Also, change MESSAGE=>SIGNATURE as
1048    * recommended for future releases of PGP.
1049    */
1050   while (fgets (buffer, sizeof (buffer) - 1, pgpout) != NULL)
1051   {
1052     if (mutt_strcmp ("-----BEGIN PGP MESSAGE-----\n", buffer) == 0)
1053       fputs ("-----BEGIN PGP SIGNATURE-----\n", fp);
1054     else if (mutt_strcmp("-----END PGP MESSAGE-----\n", buffer) == 0)
1055       fputs ("-----END PGP SIGNATURE-----\n", fp);
1056     else
1057       fputs (buffer, fp);
1058     empty = 0; /* got some output, so we're ok */
1059   }
1060
1061   /* check for errors from PGP */
1062   err = 0;
1063   while (fgets (buffer, sizeof (buffer) - 1, pgperr) != NULL)
1064   {
1065     err = 1;
1066     fputs (buffer, stdout);
1067   }
1068
1069   if(mutt_wait_filter (thepid) && option(OPTPGPCHECKEXIT))
1070     empty=1;
1071
1072   fclose (pgperr);
1073   fclose (pgpout);
1074   unlink (signedfile);
1075   
1076   if (fclose (fp) != 0)
1077   {
1078     mutt_perror ("fclose");
1079     unlink (sigfile);
1080     return (NULL);
1081   }
1082
1083   if (err)
1084     mutt_any_key_to_continue (NULL);
1085   if (empty)
1086   {
1087     unlink (sigfile);
1088     /* most likely error is a bad passphrase, so automatically forget it */
1089     pgp_void_passphrase ();
1090     return (NULL); /* fatal error while signing */
1091   }
1092
1093   t = mutt_new_body ();
1094   t->type = TYPEMULTIPART;
1095   t->subtype = safe_strdup ("signed");
1096   t->encoding = ENC7BIT;
1097   t->use_disp = 0;
1098   t->disposition = DISPINLINE;
1099
1100   mutt_generate_boundary (&t->parameter);
1101   mutt_set_parameter ("protocol", "application/pgp-signature", &t->parameter);
1102   mutt_set_parameter ("micalg", pgp_micalg (sigfile), &t->parameter);
1103
1104   t->parts = a;
1105   a = t;
1106
1107   t->parts->next = mutt_new_body ();
1108   t = t->parts->next;
1109   t->type = TYPEAPPLICATION;
1110   t->subtype = safe_strdup ("pgp-signature");
1111   t->filename = safe_strdup (sigfile);
1112   t->use_disp = 0;
1113   t->disposition = DISPINLINE;
1114   t->encoding = ENC7BIT;
1115   t->unlink = 1; /* ok to remove this file after sending. */
1116
1117   return (a);
1118 }
1119
1120 static short is_numerical_keyid (const char *s)
1121 {
1122   /* or should we require the "0x"? */
1123   if (strncmp (s, "0x", 2) == 0)
1124     s += 2;
1125   if (strlen (s) % 8)
1126     return 0;
1127   while (*s)
1128     if (strchr ("0123456789ABCDEFabcdef", *s++) == NULL)
1129       return 0;
1130   
1131   return 1;
1132 }
1133
1134 /* This routine attempts to find the keyids of the recipients of a message.
1135  * It returns NULL if any of the keys can not be found.
1136  */
1137 char *pgp_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc)
1138 {
1139   char *keyID, *keylist = NULL, *t;
1140   size_t keylist_size = 0;
1141   size_t keylist_used = 0;
1142   ADDRESS *tmp = NULL, *addr = NULL;
1143   ADDRESS **last = &tmp;
1144   ADDRESS *p, *q;
1145   int i;
1146   pgp_key_t k_info = NULL, key = NULL;
1147
1148   const char *fqdn = mutt_fqdn (1);
1149
1150   for (i = 0; i < 3; i++) 
1151   {
1152     switch (i)
1153     {
1154       case 0: p = to; break;
1155       case 1: p = cc; break;
1156       case 2: p = bcc; break;
1157       default: abort ();
1158     }
1159     
1160     *last = rfc822_cpy_adr (p);
1161     while (*last)
1162       last = &((*last)->next);
1163   }
1164
1165   if (fqdn)
1166     rfc822_qualify (tmp, fqdn);
1167
1168   tmp = mutt_remove_duplicates (tmp);
1169   
1170   for (p = tmp; p ; p = p->next)
1171   {
1172     char buf[LONG_STRING];
1173
1174     q = p;
1175     k_info = NULL;
1176
1177     if ((keyID = mutt_crypt_hook (p)) != NULL)
1178     {
1179       int r;
1180       snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox);
1181       if ((r = mutt_yesorno (buf, M_YES)) == M_YES)
1182       {
1183         if (is_numerical_keyid (keyID))
1184         {
1185           if (strncmp (keyID, "0x", 2) == 0)
1186             keyID += 2;
1187           goto bypass_selection;                /* you don't see this. */
1188         }
1189         
1190         /* check for e-mail address */
1191         if ((t = strchr (keyID, '@')) && 
1192             (addr = rfc822_parse_adrlist (NULL, keyID)))
1193         {
1194           if (fqdn) rfc822_qualify (addr, fqdn);
1195           q = addr;
1196         }
1197         else
1198           k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING);
1199       }
1200       else if (r == -1)
1201       {
1202         FREE (&keylist);
1203         rfc822_free_address (&tmp);
1204         rfc822_free_address (&addr);
1205         return NULL;
1206       }
1207     }
1208
1209     if (k_info == NULL)
1210       pgp_invoke_getkeys (q);
1211
1212     if (k_info == NULL && (k_info = pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL)
1213     {
1214       snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
1215
1216       if ((key = pgp_ask_for_key (buf, q->mailbox,
1217                                   KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL)
1218       {
1219         FREE (&keylist);
1220         rfc822_free_address (&tmp);
1221         rfc822_free_address (&addr);
1222         return NULL;
1223       }
1224     }
1225     else
1226       key = k_info;
1227
1228     keyID = pgp_keyid (key);
1229     
1230   bypass_selection:
1231     keylist_size += mutt_strlen (keyID) + 4;
1232     safe_realloc (&keylist, keylist_size);
1233     sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "", /* __SPRINTF_CHECKED__ */
1234              keyID);
1235     keylist_used = mutt_strlen (keylist);
1236
1237     pgp_free_key (&key);
1238     rfc822_free_address (&addr);
1239
1240   }
1241   rfc822_free_address (&tmp);
1242   return (keylist);
1243 }
1244
1245 /* Warning: "a" is no longer freed in this routine, you need
1246  * to free it later.  This is necessary for $fcc_attach. */
1247
1248 BODY *pgp_encrypt_message (BODY *a, char *keylist, int sign)
1249 {
1250   char buf[LONG_STRING];
1251   char tempfile[_POSIX_PATH_MAX], pgperrfile[_POSIX_PATH_MAX];
1252   char pgpinfile[_POSIX_PATH_MAX];
1253   FILE *pgpin, *pgperr, *fpout, *fptmp;
1254   BODY *t;
1255   int err = 0;
1256   int empty = 0;
1257   pid_t thepid;
1258   
1259   mutt_mktemp (tempfile);
1260   if ((fpout = safe_fopen (tempfile, "w+")) == NULL)
1261   {
1262     mutt_perror (tempfile);
1263     return (NULL);
1264   }
1265
1266   mutt_mktemp (pgperrfile);
1267   if ((pgperr = safe_fopen (pgperrfile, "w+")) == NULL)
1268   {
1269     mutt_perror (pgperrfile);
1270     unlink(tempfile);
1271     fclose(fpout);
1272     return NULL;
1273   }
1274   unlink (pgperrfile);
1275
1276   mutt_mktemp(pgpinfile);
1277   if((fptmp = safe_fopen(pgpinfile, "w")) == NULL)
1278   {
1279     mutt_perror(pgpinfile);
1280     unlink(tempfile);
1281     fclose(fpout);
1282     fclose(pgperr);
1283     return NULL;
1284   }
1285   
1286   if (sign)
1287     convert_to_7bit (a);
1288   
1289   mutt_write_mime_header (a, fptmp);
1290   fputc ('\n', fptmp);
1291   mutt_write_mime_body (a, fptmp);
1292   fclose(fptmp);
1293   
1294   if ((thepid = pgp_invoke_encrypt (&pgpin, NULL, NULL, -1, 
1295                                     fileno (fpout), fileno (pgperr),
1296                                     pgpinfile, keylist, sign)) == -1)
1297   {
1298     fclose (pgperr);
1299     unlink(pgpinfile);
1300     return (NULL);
1301   }
1302
1303   if (sign)
1304   {
1305     if (!pgp_use_gpg_agent())
1306        fputs (PgpPass, pgpin);
1307     fputc ('\n', pgpin);
1308   }
1309   fclose(pgpin);
1310   
1311   if(mutt_wait_filter (thepid) && option(OPTPGPCHECKEXIT))
1312     empty=1;
1313
1314   unlink(pgpinfile);
1315   
1316   fflush (fpout);
1317   rewind (fpout);
1318   if(!empty)
1319     empty = (fgetc (fpout) == EOF);
1320   fclose (fpout);
1321
1322   fflush (pgperr);
1323   rewind (pgperr);
1324   while (fgets (buf, sizeof (buf) - 1, pgperr) != NULL)
1325   {
1326     err = 1;
1327     fputs (buf, stdout);
1328   }
1329   fclose (pgperr);
1330
1331   /* pause if there is any error output from PGP */
1332   if (err)
1333     mutt_any_key_to_continue (NULL);
1334
1335   if (empty)
1336   {
1337     /* fatal error while trying to encrypt message */
1338     if (sign)
1339       pgp_void_passphrase (); /* just in case */
1340     unlink (tempfile);
1341     return (NULL);
1342   }
1343
1344   t = mutt_new_body ();
1345   t->type = TYPEMULTIPART;
1346   t->subtype = safe_strdup ("encrypted");
1347   t->encoding = ENC7BIT;
1348   t->use_disp = 0;
1349   t->disposition = DISPINLINE;
1350
1351   mutt_generate_boundary(&t->parameter);
1352   mutt_set_parameter("protocol", "application/pgp-encrypted", &t->parameter);
1353   
1354   t->parts = mutt_new_body ();
1355   t->parts->type = TYPEAPPLICATION;
1356   t->parts->subtype = safe_strdup ("pgp-encrypted");
1357   t->parts->encoding = ENC7BIT;
1358
1359   t->parts->next = mutt_new_body ();
1360   t->parts->next->type = TYPEAPPLICATION;
1361   t->parts->next->subtype = safe_strdup ("octet-stream");
1362   t->parts->next->encoding = ENC7BIT;
1363   t->parts->next->filename = safe_strdup (tempfile);
1364   t->parts->next->use_disp = 1;
1365   t->parts->next->disposition = DISPINLINE;
1366   t->parts->next->unlink = 1; /* delete after sending the message */
1367   t->parts->next->d_filename = safe_strdup ("msg.asc"); /* non pgp/mime can save */
1368
1369   return (t);
1370 }
1371
1372 BODY *pgp_traditional_encryptsign (BODY *a, int flags, char *keylist)
1373 {
1374   BODY *b;
1375
1376   char pgpoutfile[_POSIX_PATH_MAX];
1377   char pgperrfile[_POSIX_PATH_MAX];
1378   char pgpinfile[_POSIX_PATH_MAX];
1379   
1380   char body_charset[STRING];
1381   char *from_charset;
1382   const char *send_charset;
1383   
1384   FILE *pgpout = NULL, *pgperr = NULL, *pgpin = NULL;
1385   FILE *fp;
1386
1387   int empty = 0;
1388   int err;
1389
1390   char buff[STRING];
1391
1392   pid_t thepid;
1393
1394   if (a->type != TYPETEXT)
1395     return NULL;
1396   if (ascii_strcasecmp (a->subtype, "plain"))
1397     return NULL;
1398   
1399   if ((fp = fopen (a->filename, "r")) == NULL)
1400   {
1401     mutt_perror (a->filename);
1402     return NULL;
1403   }
1404   
1405   mutt_mktemp (pgpinfile);
1406   if ((pgpin = safe_fopen (pgpinfile, "w")) == NULL)
1407   {
1408     mutt_perror (pgpinfile);
1409     fclose (fp);
1410     return NULL;
1411   }
1412
1413   /* The following code is really correct:  If noconv is set,
1414    * a's charset parameter contains the on-disk character set, and
1415    * we have to convert from that to utf-8.  If noconv is not set,
1416    * we have to convert from $charset to utf-8.
1417    */
1418   
1419   mutt_get_body_charset (body_charset, sizeof (body_charset), a);
1420   if (a->noconv)
1421     from_charset = body_charset;
1422   else 
1423     from_charset = Charset;
1424     
1425   if (!mutt_is_us_ascii (body_charset))
1426   {
1427     int c;
1428     FGETCONV *fc;
1429     
1430     if (flags & ENCRYPT)
1431       send_charset = "us-ascii";
1432     else
1433       send_charset = "utf-8";
1434
1435     /* fromcode is assumed to be correct: we set flags to 0 */
1436     fc = fgetconv_open (fp, from_charset, "utf-8", 0);
1437     while ((c = fgetconv (fc)) != EOF)
1438       fputc (c, pgpin);
1439     
1440     fgetconv_close (&fc);
1441   }
1442   else
1443   {
1444     send_charset = "us-ascii";
1445     mutt_copy_stream (fp, pgpin);
1446   }
1447   safe_fclose (&fp);
1448   fclose (pgpin);
1449
1450   mutt_mktemp (pgpoutfile);
1451   mutt_mktemp (pgperrfile);
1452   if ((pgpout = safe_fopen (pgpoutfile, "w+")) == NULL ||
1453       (pgperr = safe_fopen (pgperrfile, "w+")) == NULL)
1454   {
1455     mutt_perror (pgpout ? pgperrfile : pgpoutfile);
1456     unlink (pgpinfile);
1457     if (pgpout) 
1458     {
1459       fclose (pgpout);
1460       unlink (pgpoutfile);
1461     }
1462     return NULL;
1463   }
1464   
1465   unlink (pgperrfile);
1466
1467   if ((thepid = pgp_invoke_traditional (&pgpin, NULL, NULL, 
1468                                         -1, fileno (pgpout), fileno (pgperr),
1469                                         pgpinfile, keylist, flags)) == -1)
1470   {
1471     mutt_perror _("Can't invoke PGP");
1472     fclose (pgpout);
1473     fclose (pgperr);
1474     mutt_unlink (pgpinfile);
1475     unlink (pgpoutfile);
1476     return NULL;
1477   }
1478
1479   if (pgp_use_gpg_agent())
1480     *PgpPass = 0;
1481   if (flags & SIGN)
1482     fprintf (pgpin, "%s\n", PgpPass);
1483   fclose (pgpin);
1484
1485   if(mutt_wait_filter (thepid) && option(OPTPGPCHECKEXIT))
1486     empty=1;
1487
1488   mutt_unlink (pgpinfile);
1489
1490   fflush (pgpout);
1491   fflush (pgperr);
1492
1493   rewind (pgpout);
1494   rewind (pgperr);
1495   
1496   if(!empty)
1497     empty = (fgetc (pgpout) == EOF);
1498   fclose (pgpout);
1499   
1500   err = 0;
1501   
1502   while (fgets (buff, sizeof (buff), pgperr))
1503   {
1504     err = 1;
1505     fputs (buff, stdout);
1506   }
1507   
1508   fclose (pgperr);
1509   
1510   if (err)
1511     mutt_any_key_to_continue (NULL);
1512   
1513   if (empty)
1514   {
1515     if (flags & SIGN)
1516       pgp_void_passphrase (); /* just in case */
1517     unlink (pgpoutfile);
1518     return NULL;
1519   }
1520     
1521   b = mutt_new_body ();
1522   
1523   b->encoding = ENC7BIT;
1524
1525   b->type = TYPETEXT;
1526   b->subtype = safe_strdup ("plain");
1527   
1528   mutt_set_parameter ("x-action", flags & ENCRYPT ? "pgp-encrypted" : "pgp-signed",
1529                       &b->parameter);
1530   mutt_set_parameter ("charset", send_charset, &b->parameter);
1531   
1532   b->filename = safe_strdup (pgpoutfile);
1533   
1534 #if 0
1535   /* The following is intended to give a clue to some completely brain-dead 
1536    * "mail environments" which are typically used by large corporations.
1537    */
1538
1539   b->d_filename = safe_strdup ("msg.pgp");
1540   b->use_disp = 1;
1541
1542 #endif
1543
1544   b->disposition = DISPINLINE;
1545   b->unlink   = 1;
1546
1547   b->noconv = 1;
1548   b->use_disp = 0;
1549   
1550   if (!(flags & ENCRYPT))
1551     b->encoding = a->encoding;
1552   
1553   return b;
1554 }
1555
1556 int pgp_send_menu (HEADER *msg, int *redraw)
1557 {
1558   pgp_key_t p;
1559   char input_signas[SHORT_STRING];
1560
1561   char prompt[LONG_STRING];
1562   
1563   if (!(WithCrypto & APPLICATION_PGP))
1564     return msg->security;
1565
1566   /* If autoinline and no crypto options set, then set inline. */
1567   if (option (OPTPGPAUTOINLINE) && 
1568       !((msg->security & APPLICATION_PGP) && (msg->security & (SIGN|ENCRYPT))))
1569     msg->security |= INLINE;
1570   
1571   snprintf (prompt, sizeof (prompt), 
1572             _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, %s, or (c)lear? "),
1573             (msg->security & INLINE) ? _("PGP/M(i)ME") : _("(i)nline"));
1574   
1575   switch (mutt_multi_choice (prompt, _("esabifc")))
1576   {
1577   case 1: /* (e)ncrypt */
1578     msg->security |= ENCRYPT;
1579     msg->security &= ~SIGN;
1580     break;
1581
1582   case 2: /* (s)ign */
1583     msg->security |= SIGN;
1584     msg->security &= ~ENCRYPT;
1585     break;
1586
1587   case 3: /* sign (a)s */
1588     unset_option(OPTPGPCHECKTRUST);
1589
1590     if ((p = pgp_ask_for_key (_("Sign as: "), NULL, 0, PGP_SECRING)))
1591     {
1592       snprintf (input_signas, sizeof (input_signas), "0x%s",
1593                 pgp_keyid (p));
1594       mutt_str_replace (&PgpSignAs, input_signas);
1595       pgp_free_key (&p);
1596       
1597       msg->security |= SIGN;
1598         
1599       crypt_pgp_void_passphrase ();  /* probably need a different passphrase */
1600     }
1601 #if 0
1602     else
1603     {
1604       msg->security &= ~SIGN;
1605     }
1606 #endif
1607
1608     *redraw = REDRAW_FULL;
1609     break;
1610
1611   case 4: /* (b)oth */
1612     msg->security |= (ENCRYPT | SIGN);
1613     break;
1614
1615   case 5: /* (i)nline */
1616     if ((msg->security & (ENCRYPT | SIGN)))
1617       msg->security ^= INLINE;
1618     else
1619       msg->security &= ~INLINE;
1620     break;
1621
1622   case 6: /* (f)orget it */
1623   case 7: /* (c)lear     */
1624     msg->security = 0;
1625     break;
1626   }
1627
1628   if (msg->security)
1629   {
1630     if (! (msg->security & (ENCRYPT | SIGN)))
1631       msg->security = 0;
1632     else
1633       msg->security |= APPLICATION_PGP;
1634   }
1635
1636   return (msg->security);
1637 }
1638
1639
1640 #endif /* CRYPT_BACKEND_CLASSIC_PGP */