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