2 * Copyright (C) 1996,1997 Michael R. Elkins <me@mutt.org>
3 * Copyright (c) 1998,1999 Thomas Roessler <roessler@does-not-exist.org>
4 * Copyright (C) 2004 g10 Code GmbH
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
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
30 #include "mutt_curses.h"
47 #ifdef HAVE_SYS_TIME_H
48 # include <sys/time.h>
51 #ifdef HAVE_SYS_RESOURCE_H
52 # include <sys/resource.h>
55 #ifdef CRYPT_BACKEND_CLASSIC_PGP
57 #include "mutt_crypt.h"
58 #include "mutt_menu.h"
62 time_t PgpExptime = 0; /* when does the cached passphrase expire? */
64 void pgp_void_passphrase (void)
66 memset (PgpPass, 0, sizeof (PgpPass));
70 int pgp_valid_passphrase (void)
72 time_t now = time (NULL);
74 if (pgp_use_gpg_agent())
77 return 1; /* handled by gpg-agent */
81 /* Use cached copy. */
84 pgp_void_passphrase ();
86 if (mutt_get_password (_("Enter PGP passphrase:"), PgpPass, sizeof (PgpPass)) == 0)
88 PgpExptime = time (NULL) + PgpTimeout;
97 void pgp_forget_passphrase (void)
99 pgp_void_passphrase ();
100 mutt_message _("PGP passphrase forgotten.");
103 int pgp_use_gpg_agent (void)
105 return option (OPTUSEGPGAGENT) && getenv ("GPG_TTY") && getenv ("GPG_AGENT_INFO");
108 char *pgp_keyid(pgp_key_t k)
110 if((k->flags & KEYFLAG_SUBKEY) && k->parent && option(OPTPGPIGNORESUB))
113 return _pgp_keyid(k);
116 char *_pgp_keyid(pgp_key_t k)
118 if(option(OPTPGPLONGIDS))
121 return (k->keyid + 8);
124 /* ----------------------------------------------------------------------------
125 * Routines for handing PGP input.
130 /* Copy PGP output messages and look for signs of a good signature */
132 static int pgp_copy_checksig (FILE *fpin, FILE *fpout)
136 if (PgpGoodSign.pattern)
142 while ((line = mutt_read_line (line, &linelen, fpin, &lineno)) != NULL)
144 if (regexec (PgpGoodSign.rx, line, 0, NULL, 0) == 0)
146 dprint (2, (debugfile, "pgp_copy_checksig: \"%s\" matches regexp.\n",
151 dprint (2, (debugfile, "pgp_copy_checksig: \"%s\" doesn't match regexp.\n",
154 if (strncmp (line, "[GNUPG:] ", 9) == 0)
163 dprint (2, (debugfile, "pgp_copy_checksig: No pattern.\n"));
164 mutt_copy_stream (fpin, fpout);
172 * Copy a clearsigned message, and strip the signature and PGP's
175 * XXX - charset handling: We assume that it is safe to do
176 * character set decoding first, dash decoding second here, while
177 * we do it the other way around in the main handler.
179 * (Note that we aren't worse than Outlook &c in this, and also
180 * note that we can successfully handle anything produced by any
181 * existing versions of mutt.)
184 static void pgp_copy_clearsigned (FILE *fpin, STATE *s, char *charset)
186 char buf[HUGE_STRING];
187 short complete, armor_header;
193 fc = fgetconv_open (fpin, charset, Charset, M_ICONV_HOOK_FROM);
195 for (complete = 1, armor_header = 1;
196 fgetconvs (buf, sizeof (buf), fc) != NULL;
197 complete = strchr (buf, '\n') != NULL)
206 if (mutt_strcmp (buf, "-----BEGIN PGP SIGNATURE-----\n") == 0)
211 char *p = mutt_skip_whitespace (buf);
218 state_puts (s->prefix, s);
220 if (buf[0] == '-' && buf[1] == ' ')
221 state_puts (buf + 2, s);
226 fgetconv_close (&fc);
230 /* Support for the Application/PGP Content Type. */
232 void pgp_application_pgp_handler (BODY *m, STATE *s)
234 int needpass = -1, pgp_keyblock = 0;
235 int clearsign = 0, rv, rc;
237 long bytes, last_pos, offset;
238 char buf[HUGE_STRING];
239 char outfile[_POSIX_PATH_MAX];
240 char tmpfname[_POSIX_PATH_MAX];
241 FILE *pgpout = NULL, *pgpin = NULL, *pgperr = NULL;
245 short maybe_goodsig = 1;
246 short have_any_sigs = 0;
248 char body_charset[STRING];
249 mutt_get_body_charset (body_charset, sizeof (body_charset), m);
251 rc = 0; /* silence false compiler warning if (s->flags & M_DISPLAY) */
253 fseek (s->fpin, m->offset, 0);
254 last_pos = m->offset;
256 for (bytes = m->length; bytes > 0;)
258 if (fgets (buf, sizeof (buf), s->fpin) == NULL)
261 offset = ftell (s->fpin);
262 bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */
265 if (mutt_strncmp ("-----BEGIN PGP ", buf, 15) == 0)
268 start_pos = last_pos;
270 if (mutt_strcmp ("MESSAGE-----\n", buf + 15) == 0)
272 else if (mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15) == 0)
277 else if (!option (OPTDONTHANDLEPGPKEYS) &&
278 mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15) == 0)
285 /* XXX - we may wish to recode here */
287 state_puts (s->prefix, s);
292 have_any_sigs = have_any_sigs || (clearsign && (s->flags & M_VERIFY));
294 /* Copy PGP material to temporary file */
295 mutt_mktemp (tmpfname);
296 if ((tmpfp = safe_fopen (tmpfname, "w+")) == NULL)
298 mutt_perror (tmpfname);
303 while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL)
305 offset = ftell (s->fpin);
306 bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */
311 if ((needpass && mutt_strcmp ("-----END PGP MESSAGE-----\n", buf) == 0) ||
313 && (mutt_strcmp ("-----END PGP SIGNATURE-----\n", buf) == 0
314 || mutt_strcmp ("-----END PGP PUBLIC KEY BLOCK-----\n",buf) == 0)))
318 /* leave tmpfp open in case we still need it - but flush it! */
322 /* Invoke PGP if needed */
323 if (!clearsign || (s->flags & M_VERIFY))
325 mutt_mktemp (outfile);
326 if ((pgpout = safe_fopen (outfile, "w+")) == NULL)
328 mutt_perror (tmpfname);
332 if ((thepid = pgp_invoke_decode (&pgpin, NULL, &pgperr, -1,
333 fileno (pgpout), -1, tmpfname,
336 safe_fclose (&pgpout);
340 state_attach_puts (_("[-- Error: unable to create PGP subprocess! --]\n"), s);
342 else /* PGP started successfully */
346 if (!pgp_valid_passphrase ()) pgp_void_passphrase();
347 if (pgp_use_gpg_agent())
349 fprintf (pgpin, "%s\n", PgpPass);
352 safe_fclose (&pgpin);
354 if (s->flags & M_DISPLAY)
356 crypt_current_time (s, "PGP");
357 rc = pgp_copy_checksig (pgperr, s->fpout);
360 safe_fclose (&pgperr);
361 rv = mutt_wait_filter (thepid);
363 if (s->flags & M_DISPLAY)
365 if (rc == 0) have_any_sigs = 1;
368 * gpg_good_sign-pattern did not match || pgp_decode_command returned not 0
369 * Sig _is_ correct if
370 * gpg_good_sign="" && pgp_decode_command returned 0
372 if (rc == -1 || rv) maybe_goodsig = 0;
374 state_putc ('\n', s);
375 state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
382 * Now, copy cleartext to the screen. NOTE - we expect that PGP
383 * outputs utf-8 cleartext. This may not always be true, but it
384 * seems to be a reasonable guess.
387 if(s->flags & M_DISPLAY)
390 state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s);
391 else if (pgp_keyblock)
392 state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"), s);
394 state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"), s);
401 pgp_copy_clearsigned (tmpfp, s, body_charset);
408 state_set_prefix (s);
409 fc = fgetconv_open (pgpout, "utf-8", Charset, 0);
410 while ((c = fgetconv (fc)) != EOF)
411 state_prefix_putc (c, s);
412 fgetconv_close (&fc);
415 if (s->flags & M_DISPLAY)
417 state_putc ('\n', s);
419 state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
420 else if (pgp_keyblock)
421 state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);
423 state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);
428 safe_fclose (&tmpfp);
429 mutt_unlink (tmpfname);
433 safe_fclose (&pgpout);
434 mutt_unlink (outfile);
439 /* XXX - we may wish to recode here */
441 state_puts (s->prefix, s);
446 m->goodsig = (maybe_goodsig && have_any_sigs);
450 state_attach_puts (_("[-- Error: could not find beginning of PGP message! --]\n\n"), s);
455 static int pgp_check_traditional_one_body (FILE *fp, BODY *b, int tagged_only)
457 char tempfile[_POSIX_PATH_MAX];
458 char buf[HUGE_STRING];
465 if (b->type != TYPETEXT)
468 if (tagged_only && !b->tagged)
471 mutt_mktemp (tempfile);
472 if (mutt_decode_save_attachment (fp, b, tempfile, 0, 0) != 0)
478 if ((tfp = fopen (tempfile, "r")) == NULL)
484 while (fgets (buf, sizeof (buf), tfp))
486 if (mutt_strncmp ("-----BEGIN PGP ", buf, 15) == 0)
488 if (mutt_strcmp ("MESSAGE-----\n", buf + 15) == 0)
490 else if (mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15) == 0)
492 else if (mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15) == 0)
499 if (!enc && !sgn && !key)
502 /* fix the content type */
504 mutt_set_parameter ("format", "fixed", &b->parameter);
506 mutt_set_parameter ("x-action", "pgp-encrypted", &b->parameter);
508 mutt_set_parameter ("x-action", "pgp-signed", &b->parameter);
510 mutt_set_parameter ("x-action", "pgp-keys", &b->parameter);
515 int pgp_check_traditional (FILE *fp, BODY *b, int tagged_only)
519 for (; b; b = b->next)
521 if (is_multipart (b))
522 rv = pgp_check_traditional (fp, b->parts, tagged_only) || rv;
523 else if (b->type == TYPETEXT)
525 if ((r = mutt_is_application_pgp (b)))
528 rv = pgp_check_traditional_one_body (fp, b, tagged_only) || rv;
539 int pgp_verify_one (BODY *sigbdy, STATE *s, const char *tempfile)
541 char sigfile[_POSIX_PATH_MAX], pgperrfile[_POSIX_PATH_MAX];
542 FILE *fp, *pgpout, *pgperr;
547 snprintf (sigfile, sizeof (sigfile), "%s.asc", tempfile);
549 if(!(fp = safe_fopen (sigfile, "w")))
551 mutt_perror(sigfile);
555 fseek (s->fpin, sigbdy->offset, 0);
556 mutt_copy_bytes (s->fpin, fp, sigbdy->length);
559 mutt_mktemp(pgperrfile);
560 if(!(pgperr = safe_fopen(pgperrfile, "w+")))
562 mutt_perror(pgperrfile);
567 crypt_current_time (s, "PGP");
569 if((thepid = pgp_invoke_verify (NULL, &pgpout, NULL,
570 -1, -1, fileno(pgperr),
571 tempfile, sigfile)) != -1)
573 if (pgp_copy_checksig (pgpout, s->fpout) >= 0)
577 safe_fclose (&pgpout);
581 if (pgp_copy_checksig (pgperr, s->fpout) >= 0)
584 if ((rv = mutt_wait_filter (thepid)))
587 dprint (1, (debugfile, "pgp_verify_one: mutt_wait_filter returned %d.\n", rv));
590 safe_fclose (&pgperr);
592 state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
594 mutt_unlink (sigfile);
595 mutt_unlink (pgperrfile);
597 dprint (1, (debugfile, "pgp_verify_one: returning %d.\n", badsig));
603 /* Extract pgp public keys from messages or attachments */
605 void pgp_extract_keys_from_messages (HEADER *h)
608 char tempfname[_POSIX_PATH_MAX];
613 mutt_parse_mime_message (Context, h);
614 if(h->security & PGPENCRYPT && !pgp_valid_passphrase ())
618 mutt_mktemp (tempfname);
619 if (!(fpout = safe_fopen (tempfname, "w")))
621 mutt_perror (tempfname);
625 set_option (OPTDONTHANDLEPGPKEYS);
629 for (i = 0; i < Context->vcount; i++)
631 if (Context->hdrs[Context->v2r[i]]->tagged)
633 mutt_parse_mime_message (Context, Context->hdrs[Context->v2r[i]]);
634 if (Context->hdrs[Context->v2r[i]]->security & PGPENCRYPT
635 && !pgp_valid_passphrase())
640 mutt_copy_message (fpout, Context, Context->hdrs[Context->v2r[i]],
641 M_CM_DECODE|M_CM_CHARCONV, 0);
647 mutt_parse_mime_message (Context, h);
648 if (h->security & PGPENCRYPT && !pgp_valid_passphrase())
653 mutt_copy_message (fpout, Context, h, M_CM_DECODE|M_CM_CHARCONV, 0);
658 pgp_invoke_import (tempfname);
659 mutt_any_key_to_continue (NULL);
663 mutt_unlink (tempfname);
664 unset_option (OPTDONTHANDLEPGPKEYS);
668 static void pgp_extract_keys_from_attachment (FILE *fp, BODY *top)
672 char tempfname[_POSIX_PATH_MAX];
674 mutt_mktemp (tempfname);
675 if (!(tempfp = safe_fopen (tempfname, "w")))
677 mutt_perror (tempfname);
681 memset (&s, 0, sizeof (STATE));
686 mutt_body_handler (top, &s);
690 pgp_invoke_import (tempfname);
691 mutt_any_key_to_continue (NULL);
693 mutt_unlink (tempfname);
696 void pgp_extract_keys_from_attachment_list (FILE *fp, int tag, BODY *top)
700 mutt_error _("Internal error. Inform <roessler@does-not-exist.org>.");
705 set_option(OPTDONTHANDLEPGPKEYS);
707 for(; top; top = top->next)
709 if(!tag || top->tagged)
710 pgp_extract_keys_from_attachment (fp, top);
716 unset_option(OPTDONTHANDLEPGPKEYS);
719 BODY *pgp_decrypt_part (BODY *a, STATE *s, FILE *fpout, BODY *p)
721 char buf[LONG_STRING];
722 FILE *pgpin, *pgpout, *pgperr, *pgptmp;
726 char pgperrfile[_POSIX_PATH_MAX];
727 char pgptmpfile[_POSIX_PATH_MAX];
730 mutt_mktemp (pgperrfile);
731 if ((pgperr = safe_fopen (pgperrfile, "w+")) == NULL)
733 mutt_perror (pgperrfile);
738 mutt_mktemp (pgptmpfile);
739 if((pgptmp = safe_fopen (pgptmpfile, "w")) == NULL)
741 mutt_perror (pgptmpfile);
746 /* Position the stream at the beginning of the body, and send the data to
747 * the temporary file.
750 fseek (s->fpin, a->offset, 0);
751 mutt_copy_bytes (s->fpin, pgptmp, a->length);
754 if ((thepid = pgp_invoke_decrypt (&pgpin, &pgpout, NULL, -1, -1,
755 fileno (pgperr), pgptmpfile)) == -1)
759 if (s->flags & M_DISPLAY)
760 state_attach_puts (_("[-- Error: could not create a PGP subprocess! --]\n\n"), s);
764 /* send the PGP passphrase to the subprocess. Never do this if the
765 agent is active, because this might lead to a passphrase send as
767 if (!pgp_use_gpg_agent())
768 fputs (PgpPass, pgpin);
772 /* Read the output from PGP, and make sure to change CRLF to LF, otherwise
773 * read_mime_header has a hard time parsing the message.
775 while (fgets (buf, sizeof (buf) - 1, pgpout) != NULL)
777 len = mutt_strlen (buf);
778 if (len > 1 && buf[len - 2] == '\r')
779 strcpy (buf + len - 2, "\n"); /* __STRCPY_CHECKED__ */
784 mutt_wait_filter (thepid);
785 mutt_unlink(pgptmpfile);
787 if (s->flags & M_DISPLAY)
791 if (pgp_copy_checksig (pgperr, s->fpout) == 0 && p)
793 state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
803 if ((tattach = mutt_read_mime_header (fpout, 0)) != NULL)
806 * Need to set the length of this body part.
808 fstat (fileno (fpout), &info);
809 tattach->length = info.st_size - tattach->offset;
811 /* See if we need to recurse on this MIME part. */
813 mutt_parse_part (fpout, tattach);
819 int pgp_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur)
821 char tempfile[_POSIX_PATH_MAX];
825 if(!mutt_is_multipart_encrypted(b))
828 if(!b->parts || !b->parts->next)
833 memset (&s, 0, sizeof (s));
835 mutt_mktemp (tempfile);
836 if ((*fpout = safe_fopen (tempfile, "w+")) == NULL)
838 mutt_perror (tempfile);
843 *cur = pgp_decrypt_part (b, &s, *fpout, p);
853 void pgp_encrypted_handler (BODY *a, STATE *s)
855 char tempfile[_POSIX_PATH_MAX];
861 if (!a || a->type != TYPEAPPLICATION || !a->subtype ||
862 ascii_strcasecmp ("pgp-encrypted", a->subtype) != 0 ||
863 !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype ||
864 ascii_strcasecmp ("octet-stream", a->next->subtype) != 0)
866 if (s->flags & M_DISPLAY)
867 state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"), s);
872 * Move forward to the application/pgp-encrypted body.
876 mutt_mktemp (tempfile);
877 if ((fpout = safe_fopen (tempfile, "w+")) == NULL)
879 if (s->flags & M_DISPLAY)
880 state_attach_puts (_("[-- Error: could not create temporary file! --]\n"), s);
884 if (s->flags & M_DISPLAY) crypt_current_time (s, "PGP");
886 if ((tattach = pgp_decrypt_part (a, s, fpout, p)) != NULL)
888 if (s->flags & M_DISPLAY)
889 state_attach_puts (_("[-- The following data is PGP/MIME encrypted --]\n\n"), s);
893 mutt_body_handler (tattach, s);
897 * if a multipart/signed is the _only_ sub-part of a
898 * multipart/encrypted, cache signature verification
903 if (mutt_is_multipart_signed (tattach) && !tattach->next)
904 p->goodsig |= tattach->goodsig;
906 if (s->flags & M_DISPLAY)
908 state_puts ("\n", s);
909 state_attach_puts (_("[-- End of PGP/MIME encrypted data --]\n"), s);
912 mutt_free_body (&tattach);
916 mutt_unlink(tempfile);
919 /* ----------------------------------------------------------------------------
920 * Routines for sending PGP/MIME messages.
924 BODY *pgp_sign_message (BODY *a)
927 char buffer[LONG_STRING];
928 char sigfile[_POSIX_PATH_MAX], signedfile[_POSIX_PATH_MAX];
929 FILE *pgpin, *pgpout, *pgperr, *fp, *sfp;
934 convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */
936 mutt_mktemp (sigfile);
937 if ((fp = safe_fopen (sigfile, "w")) == NULL)
942 mutt_mktemp (signedfile);
943 if ((sfp = safe_fopen(signedfile, "w")) == NULL)
945 mutt_perror(signedfile);
951 mutt_write_mime_header (a, sfp);
953 mutt_write_mime_body (a, sfp);
956 if ((thepid = pgp_invoke_sign (&pgpin, &pgpout, &pgperr,
957 -1, -1, -1, signedfile)) == -1)
959 mutt_perror _("Can't open PGP subprocess!");
966 if (!pgp_use_gpg_agent())
967 fputs(PgpPass, pgpin);
972 * Read back the PGP signature. Also, change MESSAGE=>SIGNATURE as
973 * recommended for future releases of PGP.
975 while (fgets (buffer, sizeof (buffer) - 1, pgpout) != NULL)
977 if (mutt_strcmp ("-----BEGIN PGP MESSAGE-----\n", buffer) == 0)
978 fputs ("-----BEGIN PGP SIGNATURE-----\n", fp);
979 else if (mutt_strcmp("-----END PGP MESSAGE-----\n", buffer) == 0)
980 fputs ("-----END PGP SIGNATURE-----\n", fp);
983 empty = 0; /* got some output, so we're ok */
986 /* check for errors from PGP */
988 while (fgets (buffer, sizeof (buffer) - 1, pgperr) != NULL)
991 fputs (buffer, stdout);
994 if(mutt_wait_filter (thepid) && option(OPTPGPCHECKEXIT))
1001 if (fclose (fp) != 0)
1003 mutt_perror ("fclose");
1010 pgp_void_passphrase();
1011 mutt_any_key_to_continue (NULL);
1017 return (NULL); /* fatal error while signing */
1020 t = mutt_new_body ();
1021 t->type = TYPEMULTIPART;
1022 t->subtype = safe_strdup ("signed");
1023 t->encoding = ENC7BIT;
1025 t->disposition = DISPINLINE;
1027 mutt_generate_boundary (&t->parameter);
1028 mutt_set_parameter ("protocol", "application/pgp-signature", &t->parameter);
1029 mutt_set_parameter ("micalg", pgp_micalg (sigfile), &t->parameter);
1034 t->parts->next = mutt_new_body ();
1036 t->type = TYPEAPPLICATION;
1037 t->subtype = safe_strdup ("pgp-signature");
1038 t->filename = safe_strdup (sigfile);
1040 t->disposition = DISPINLINE;
1041 t->encoding = ENC7BIT;
1042 t->unlink = 1; /* ok to remove this file after sending. */
1047 static short is_numerical_keyid (const char *s)
1049 /* or should we require the "0x"? */
1050 if (strncmp (s, "0x", 2) == 0)
1055 if (strchr ("0123456789ABCDEFabcdef", *s++) == NULL)
1061 /* This routine attempts to find the keyids of the recipients of a message.
1062 * It returns NULL if any of the keys can not be found.
1064 char *pgp_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc)
1066 char *keyID, *keylist = NULL, *t;
1067 size_t keylist_size = 0;
1068 size_t keylist_used = 0;
1069 ADDRESS *tmp = NULL, *addr = NULL;
1070 ADDRESS **last = &tmp;
1073 pgp_key_t k_info = NULL, key = NULL;
1075 const char *fqdn = mutt_fqdn (1);
1077 for (i = 0; i < 3; i++)
1081 case 0: p = to; break;
1082 case 1: p = cc; break;
1083 case 2: p = bcc; break;
1087 *last = rfc822_cpy_adr (p);
1089 last = &((*last)->next);
1093 rfc822_qualify (tmp, fqdn);
1095 tmp = mutt_remove_duplicates (tmp);
1097 for (p = tmp; p ; p = p->next)
1099 char buf[LONG_STRING];
1104 if ((keyID = mutt_crypt_hook (p)) != NULL)
1107 snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox);
1108 if ((r = mutt_yesorno (buf, M_YES)) == M_YES)
1110 if (is_numerical_keyid (keyID))
1112 if (strncmp (keyID, "0x", 2) == 0)
1114 goto bypass_selection; /* you don't see this. */
1117 /* check for e-mail address */
1118 if ((t = strchr (keyID, '@')) &&
1119 (addr = rfc822_parse_adrlist (NULL, keyID)))
1121 if (fqdn) rfc822_qualify (addr, fqdn);
1125 k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING);
1130 rfc822_free_address (&tmp);
1131 rfc822_free_address (&addr);
1137 pgp_invoke_getkeys (q);
1139 if (k_info == NULL && (k_info = pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL)
1141 snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
1143 if ((key = pgp_ask_for_key (buf, q->mailbox,
1144 KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL)
1147 rfc822_free_address (&tmp);
1148 rfc822_free_address (&addr);
1155 keyID = pgp_keyid (key);
1158 keylist_size += mutt_strlen (keyID) + 4;
1159 safe_realloc (&keylist, keylist_size);
1160 sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "", /* __SPRINTF_CHECKED__ */
1162 keylist_used = mutt_strlen (keylist);
1164 pgp_free_key (&key);
1165 rfc822_free_address (&addr);
1168 rfc822_free_address (&tmp);
1172 /* Warning: "a" is no longer freed in this routine, you need
1173 * to free it later. This is necessary for $fcc_attach. */
1175 BODY *pgp_encrypt_message (BODY *a, char *keylist, int sign)
1177 char buf[LONG_STRING];
1178 char tempfile[_POSIX_PATH_MAX], pgperrfile[_POSIX_PATH_MAX];
1179 char pgpinfile[_POSIX_PATH_MAX];
1180 FILE *pgpin, *pgperr, *fpout, *fptmp;
1186 mutt_mktemp (tempfile);
1187 if ((fpout = safe_fopen (tempfile, "w+")) == NULL)
1189 mutt_perror (tempfile);
1193 mutt_mktemp (pgperrfile);
1194 if ((pgperr = safe_fopen (pgperrfile, "w+")) == NULL)
1196 mutt_perror (pgperrfile);
1201 unlink (pgperrfile);
1203 mutt_mktemp(pgpinfile);
1204 if((fptmp = safe_fopen(pgpinfile, "w")) == NULL)
1206 mutt_perror(pgpinfile);
1214 convert_to_7bit (a);
1216 mutt_write_mime_header (a, fptmp);
1217 fputc ('\n', fptmp);
1218 mutt_write_mime_body (a, fptmp);
1221 if ((thepid = pgp_invoke_encrypt (&pgpin, NULL, NULL, -1,
1222 fileno (fpout), fileno (pgperr),
1223 pgpinfile, keylist, sign)) == -1)
1232 if (!pgp_use_gpg_agent())
1233 fputs (PgpPass, pgpin);
1234 fputc ('\n', pgpin);
1238 if(mutt_wait_filter (thepid) && option(OPTPGPCHECKEXIT))
1246 empty = (fgetc (fpout) == EOF);
1251 while (fgets (buf, sizeof (buf) - 1, pgperr) != NULL)
1254 fputs (buf, stdout);
1258 /* pause if there is any error output from PGP */
1260 mutt_any_key_to_continue (NULL);
1264 /* fatal error while trying to encrypt message */
1269 t = mutt_new_body ();
1270 t->type = TYPEMULTIPART;
1271 t->subtype = safe_strdup ("encrypted");
1272 t->encoding = ENC7BIT;
1274 t->disposition = DISPINLINE;
1276 mutt_generate_boundary(&t->parameter);
1277 mutt_set_parameter("protocol", "application/pgp-encrypted", &t->parameter);
1279 t->parts = mutt_new_body ();
1280 t->parts->type = TYPEAPPLICATION;
1281 t->parts->subtype = safe_strdup ("pgp-encrypted");
1282 t->parts->encoding = ENC7BIT;
1284 t->parts->next = mutt_new_body ();
1285 t->parts->next->type = TYPEAPPLICATION;
1286 t->parts->next->subtype = safe_strdup ("octet-stream");
1287 t->parts->next->encoding = ENC7BIT;
1288 t->parts->next->filename = safe_strdup (tempfile);
1289 t->parts->next->use_disp = 1;
1290 t->parts->next->disposition = DISPINLINE;
1291 t->parts->next->unlink = 1; /* delete after sending the message */
1292 t->parts->next->d_filename = safe_strdup ("msg.asc"); /* non pgp/mime can save */
1297 BODY *pgp_traditional_encryptsign (BODY *a, int flags, char *keylist)
1301 char pgpoutfile[_POSIX_PATH_MAX];
1302 char pgperrfile[_POSIX_PATH_MAX];
1303 char pgpinfile[_POSIX_PATH_MAX];
1305 char body_charset[STRING];
1307 const char *send_charset;
1309 FILE *pgpout = NULL, *pgperr = NULL, *pgpin = NULL;
1319 if (a->type != TYPETEXT)
1321 if (ascii_strcasecmp (a->subtype, "plain"))
1324 if ((fp = fopen (a->filename, "r")) == NULL)
1326 mutt_perror (a->filename);
1330 mutt_mktemp (pgpinfile);
1331 if ((pgpin = safe_fopen (pgpinfile, "w")) == NULL)
1333 mutt_perror (pgpinfile);
1338 /* The following code is really correct: If noconv is set,
1339 * a's charset parameter contains the on-disk character set, and
1340 * we have to convert from that to utf-8. If noconv is not set,
1341 * we have to convert from $charset to utf-8.
1344 mutt_get_body_charset (body_charset, sizeof (body_charset), a);
1346 from_charset = body_charset;
1348 from_charset = Charset;
1350 if (!mutt_is_us_ascii (body_charset))
1355 if (flags & ENCRYPT)
1356 send_charset = "us-ascii";
1358 send_charset = "utf-8";
1360 fc = fgetconv_open (fp, from_charset, "utf-8", M_ICONV_HOOK_FROM);
1361 while ((c = fgetconv (fc)) != EOF)
1364 fgetconv_close (&fc);
1368 send_charset = "us-ascii";
1369 mutt_copy_stream (fp, pgpin);
1374 mutt_mktemp (pgpoutfile);
1375 mutt_mktemp (pgperrfile);
1376 if ((pgpout = safe_fopen (pgpoutfile, "w+")) == NULL ||
1377 (pgperr = safe_fopen (pgperrfile, "w+")) == NULL)
1379 mutt_perror (pgpout ? pgperrfile : pgpoutfile);
1384 unlink (pgpoutfile);
1389 unlink (pgperrfile);
1391 if ((thepid = pgp_invoke_traditional (&pgpin, NULL, NULL,
1392 -1, fileno (pgpout), fileno (pgperr),
1393 pgpinfile, keylist, flags)) == -1)
1395 mutt_perror _("Can't invoke PGP");
1398 mutt_unlink (pgpinfile);
1399 unlink (pgpoutfile);
1403 if (pgp_use_gpg_agent())
1406 fprintf (pgpin, "%s\n", PgpPass);
1409 if(mutt_wait_filter (thepid) && option(OPTPGPCHECKEXIT))
1412 mutt_unlink (pgpinfile);
1421 empty = (fgetc (pgpout) == EOF);
1426 while (fgets (buff, sizeof (buff), pgperr))
1429 fputs (buff, stdout);
1435 mutt_any_key_to_continue (NULL);
1439 unlink (pgpoutfile);
1443 b = mutt_new_body ();
1445 b->encoding = ENC7BIT;
1448 b->subtype = safe_strdup ("plain");
1450 mutt_set_parameter ("x-action", flags & ENCRYPT ? "pgp-encrypted" : "pgp-signed",
1452 mutt_set_parameter ("charset", send_charset, &b->parameter);
1454 b->filename = safe_strdup (pgpoutfile);
1457 /* The following is intended to give a clue to some completely brain-dead
1458 * "mail environments" which are typically used by large corporations.
1461 b->d_filename = safe_strdup ("msg.pgp");
1466 b->disposition = DISPINLINE;
1472 if (!(flags & ENCRYPT))
1473 b->encoding = a->encoding;
1478 int pgp_send_menu (HEADER *msg, int *redraw)
1481 char input_signas[SHORT_STRING];
1483 char prompt[LONG_STRING];
1485 if (!(WithCrypto & APPLICATION_PGP))
1486 return msg->security;
1488 snprintf (prompt, sizeof (prompt),
1489 _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, %s, or (c)lear? "),
1490 (msg->security & INLINE) ? _("PGP/M(i)ME") : _("(i)nline"));
1492 switch (mutt_multi_choice (prompt, _("esabifc")))
1494 case 1: /* (e)ncrypt */
1495 msg->security |= ENCRYPT;
1496 msg->security &= ~SIGN;
1499 case 2: /* (s)ign */
1500 msg->security |= SIGN;
1501 msg->security &= ~ENCRYPT;
1504 case 3: /* sign (a)s */
1505 unset_option(OPTPGPCHECKTRUST);
1507 if ((p = pgp_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN, PGP_PUBRING)))
1509 snprintf (input_signas, sizeof (input_signas), "0x%s",
1511 mutt_str_replace (&PgpSignAs, input_signas);
1514 msg->security |= SIGN;
1516 crypt_pgp_void_passphrase (); /* probably need a different passphrase */
1521 msg->security &= ~SIGN;
1525 *redraw = REDRAW_FULL;
1528 case 4: /* (b)oth */
1529 msg->security |= (ENCRYPT | SIGN);
1532 case 5: /* (i)nline */
1533 if ((msg->security & (ENCRYPT | SIGN)))
1534 msg->security ^= INLINE;
1536 msg->security &= ~INLINE;
1539 case 6: /* (f)orget it */
1540 case 7: /* (c)lear */
1547 if (! (msg->security & (ENCRYPT | SIGN)))
1550 msg->security |= APPLICATION_PGP;
1553 return (msg->security);
1557 #endif /* CRYPT_BACKEND_CLASSIC_PGP */