# include "config.h"
#endif
+#include <lib-lib/mem.h>
+#include <lib-lib/ascii.h>
+#include <lib-lib/str.h>
+#include <lib-lib/macros.h>
+#include <lib-lib/file.h>
+
+#include <lib-mime/mime.h>
+
#include "mutt.h"
+#include "enter.h"
+#include "handler.h"
#include "mutt_curses.h"
#include "pgp.h"
-#include "mime.h"
#include "copy.h"
+#include "attach.h"
-#include "lib/mem.h"
-#include "lib/intl.h"
-#include "lib/str.h"
#include "lib/debug.h"
#include <sys/wait.h>
# include <sys/resource.h>
#endif
-#ifdef CRYPT_BACKEND_CLASSIC_PGP
-
#include "mutt_crypt.h"
#include "mutt_menu.h"
-char PgpPass[STRING];
+char PgpPass[LONG_STRING];
time_t PgpExptime = 0; /* when does the cached passphrase expire? */
void pgp_void_passphrase (void)
{
- memset (PgpPass, 0, sizeof (PgpPass));
+ p_clear(PgpPass, sizeof(PgpPass));
PgpExptime = 0;
}
pgp_void_passphrase ();
- if (mutt_get_password
- (_("Enter PGP passphrase:"), PgpPass, sizeof (PgpPass)) == 0) {
+ if (mutt_get_field_unbuffered (_("Enter PGP passphrase:"), PgpPass,
+ sizeof (PgpPass), M_PASS) == 0) {
PgpExptime = time (NULL) + PgpTimeout;
return (1);
}
mutt_message _("PGP passphrase forgotten.");
}
-int pgp_use_gpg_agent (void)
-{
- return option (OPTUSEGPGAGENT) && getenv ("GPG_TTY")
- && getenv ("GPG_AGENT_INFO");
+int pgp_use_gpg_agent (void) {
+ char *tty;
+
+ if (!option (OPTUSEGPGAGENT) || !getenv ("GPG_AGENT_INFO"))
+ return 0;
+
+ if ((tty = ttyname(0)))
+ setenv ("GPG_TTY", tty, 0);
+
+ return 1;
}
char *pgp_keyid (pgp_key_t k)
fputs (line, fpout);
fputc ('\n', fpout);
}
- FREE (&line);
+ p_delete(&line);
}
else {
debug_print (2, ("No pattern.\n"));
continue;
}
- if (mutt_strcmp (buf, "-----BEGIN PGP SIGNATURE-----\n") == 0)
+ if (m_strcmp(buf, "-----BEGIN PGP SIGNATURE-----\n") == 0)
break;
if (armor_header) {
- char *p = str_skip_initws (buf);
+ char *p = vskipspaces(buf);
if (*p == '\0')
armor_header = 0;
/* Support for the Application/PGP Content Type. */
-void pgp_application_pgp_handler (BODY * m, STATE * s)
+int pgp_application_pgp_handler (BODY * m, STATE * s)
{
+ int could_not_decrypt = 0;
int needpass = -1, pgp_keyblock = 0;
+ int c = 1;
int clearsign = 0, rv, rc;
long start_pos = 0;
- long bytes, last_pos, offset;
+ long bytes;
+ off_t last_pos, offset;
char buf[HUGE_STRING];
char outfile[_POSIX_PATH_MAX];
char tmpfname[_POSIX_PATH_MAX];
FILE *pgpout = NULL, *pgpin = NULL, *pgperr = NULL;
- FILE *tmpfp;
+ FILE *tmpfp = NULL;
pid_t thepid;
short maybe_goodsig = 1;
rc = 0; /* silence false compiler warning if (s->flags & M_DISPLAY) */
- fseek (s->fpin, m->offset, 0);
+ fseeko (s->fpin, m->offset, 0);
last_pos = m->offset;
for (bytes = m->length; bytes > 0;) {
if (fgets (buf, sizeof (buf), s->fpin) == NULL)
break;
- offset = ftell (s->fpin);
- bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */
+ offset = ftello (s->fpin);
+ bytes -= (offset - last_pos); /* don't rely on m_strlen(buf) */
last_pos = offset;
- if (safe_strncmp ("-----BEGIN PGP ", buf, 15) == 0) {
+ if (m_strncmp("-----BEGIN PGP ", buf, 15) == 0) {
clearsign = 0;
start_pos = last_pos;
- if (mutt_strcmp ("MESSAGE-----\n", buf + 15) == 0)
+ if (m_strcmp("MESSAGE-----\n", buf + 15) == 0)
needpass = 1;
- else if (mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15) == 0) {
+ else if (m_strcmp("SIGNED MESSAGE-----\n", buf + 15) == 0) {
clearsign = 1;
needpass = 0;
}
else if (!option (OPTDONTHANDLEPGPKEYS) &&
- mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15) == 0) {
+ m_strcmp("PUBLIC KEY BLOCK-----\n", buf + 15) == 0) {
needpass = 0;
pgp_keyblock = 1;
}
mutt_mktemp (tmpfname);
if ((tmpfp = safe_fopen (tmpfname, "w+")) == NULL) {
mutt_perror (tmpfname);
- return;
+ return (-1);
}
fputs (buf, tmpfp);
while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL) {
- offset = ftell (s->fpin);
- bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */
+ offset = ftello (s->fpin);
+ bytes -= (offset - last_pos); /* don't rely on m_strlen(buf) */
last_pos = offset;
fputs (buf, tmpfp);
if ((needpass
- && mutt_strcmp ("-----END PGP MESSAGE-----\n", buf) == 0)
+ && m_strcmp("-----END PGP MESSAGE-----\n", buf) == 0)
|| (!needpass
- && (mutt_strcmp ("-----END PGP SIGNATURE-----\n", buf) == 0
- || mutt_strcmp ("-----END PGP PUBLIC KEY BLOCK-----\n",
+ && (m_strcmp("-----END PGP SIGNATURE-----\n", buf) == 0
+ || m_strcmp("-----END PGP PUBLIC KEY BLOCK-----\n",
buf) == 0)))
break;
}
mutt_mktemp (outfile);
if ((pgpout = safe_fopen (outfile, "w+")) == NULL) {
mutt_perror (tmpfname);
- return;
+ return (-1);
}
if ((thepid = pgp_invoke_decode (&pgpin, NULL, &pgperr, -1,
if (s->flags & M_DISPLAY) {
if (rc == 0)
have_any_sigs = 1;
-/*
- * Sig is bad if
- * gpg_good_sign-pattern did not match || pgp_decode_command returned not 0
- * Sig _is_ correct if
- * gpg_good_sign="" && pgp_decode_command returned 0
- */
+
+ /*
+ * Sig is bad if
+ * gpg_good_sign-pattern did not match || pgp_decode_command returned not 0
+ * Sig _is_ correct if
+ * gpg_good_sign="" && pgp_decode_command returned 0
+ */
if (rc == -1 || rv)
maybe_goodsig = 0;
- state_putc ('\n', s);
state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
}
}
- }
+ /* treat empty result as sign of failure */
+ /* TODO: maybe on failure mutt should include the original undecoded text. */
+ if (pgpout) {
+ rewind (pgpout);
+ c = fgetc (pgpout);
+ ungetc (c, pgpout);
+ }
+ if (!clearsign && (!pgpout || c == EOF)) {
+ could_not_decrypt = 1;
+ pgp_void_passphrase ();
+ }
+
+ if (could_not_decrypt && !(s->flags & M_DISPLAY)) {
+ mutt_error _("Could not decrypt PGP message");
+ mutt_sleep (1);
+ rc = -1;
+ goto out;
+ }
+ }
/*
* Now, copy cleartext to the screen. NOTE - we expect that PGP
if (s->flags & M_DISPLAY) {
state_putc ('\n', s);
- if (needpass)
+ if (needpass) {
state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
+ if (could_not_decrypt)
+ mutt_error _("Could not decrypt PGP message.");
+ else
+ mutt_message _("PGP message successfully decrypted.");
+ }
else if (pgp_keyblock)
state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);
else
state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);
}
- if (tmpfp) {
- safe_fclose (&tmpfp);
- mutt_unlink (tmpfname);
- }
- if (pgpout) {
- safe_fclose (&pgpout);
- mutt_unlink (outfile);
- }
}
else {
/* XXX - we may wish to recode here */
}
}
+ rc = 0;
+
+out:
m->goodsig = (maybe_goodsig && have_any_sigs);
+ if (tmpfp) {
+ safe_fclose (&tmpfp);
+ mutt_unlink (tmpfname);
+ }
+ if (pgpout) {
+ safe_fclose (&pgpout);
+ mutt_unlink (outfile);
+ }
+
if (needpass == -1) {
state_attach_puts (_
("[-- Error: could not find beginning of PGP message! --]\n\n"),
s);
- return;
+ return (-1);
}
+
+ return (rc);
}
static int pgp_check_traditional_one_body (FILE * fp, BODY * b,
}
while (fgets (buf, sizeof (buf), tfp)) {
- if (safe_strncmp ("-----BEGIN PGP ", buf, 15) == 0) {
- if (mutt_strcmp ("MESSAGE-----\n", buf + 15) == 0)
+ if (m_strncmp("-----BEGIN PGP ", buf, 15) == 0) {
+ if (m_strcmp("MESSAGE-----\n", buf + 15) == 0)
enc = 1;
- else if (mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15) == 0)
+ else if (m_strcmp("SIGNED MESSAGE-----\n", buf + 15) == 0)
sgn = 1;
- else if (mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15) == 0)
+ else if (m_strcmp("PUBLIC KEY BLOCK-----\n", buf + 15) == 0)
key = 1;
}
}
return -1;
}
- fseek (s->fpin, sigbdy->offset, 0);
+ fseeko (s->fpin, sigbdy->offset, 0);
mutt_copy_bytes (s->fpin, fp, sigbdy->length);
fclose (fp);
return;
}
- memset (&s, 0, sizeof (STATE));
+ p_clear(&s, 1);
s.fpin = fp;
s.fpout = tempfp;
char pgperrfile[_POSIX_PATH_MAX];
char pgptmpfile[_POSIX_PATH_MAX];
pid_t thepid;
+ int rv;
mutt_mktemp (pgperrfile);
if ((pgperr = safe_fopen (pgperrfile, "w+")) == NULL) {
* the temporary file.
*/
- fseek (s->fpin, a->offset, 0);
+ fseeko (s->fpin, a->offset, 0);
mutt_copy_bytes (s->fpin, pgptmp, a->length);
fclose (pgptmp);
* read_mime_header has a hard time parsing the message.
*/
while (fgets (buf, sizeof (buf) - 1, pgpout) != NULL) {
- len = mutt_strlen (buf);
+ len = m_strlen(buf);
if (len > 1 && buf[len - 2] == '\r')
strcpy (buf + len - 2, "\n"); /* __STRCPY_CHECKED__ */
fputs (buf, fpout);
}
fclose (pgpout);
- mutt_wait_filter (thepid);
+ rv = mutt_wait_filter (thepid);
mutt_unlink (pgptmpfile);
if (s->flags & M_DISPLAY) {
fflush (pgperr);
rewind (pgperr);
- if (pgp_copy_checksig (pgperr, s->fpout) == 0 && p)
+ if (pgp_copy_checksig (pgperr, s->fpout) == 0 && !rv && p)
p->goodsig = 1;
+ else
+ p->goodsig = 0;
state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
}
fclose (pgperr);
fflush (fpout);
rewind (fpout);
- if (fgetc (fpout) == EOF)
+ if (fgetc (fpout) == EOF) {
+ mutt_error (_("Decryption failed."));
+ pgp_void_passphrase ();
return NULL;
+ }
rewind (fpout);
b = b->parts->next;
- memset (&s, 0, sizeof (s));
+ p_clear(&s, 1);
s.fpin = fpin;
mutt_mktemp (tempfile);
if ((*fpout = safe_fopen (tempfile, "w+")) == NULL) {
return (0);
}
-void pgp_encrypted_handler (BODY * a, STATE * s)
+int pgp_encrypted_handler (BODY * a, STATE * s)
{
char tempfile[_POSIX_PATH_MAX];
FILE *fpout, *fpin;
BODY *tattach;
BODY *p = a;
+ int rc = 0;
a = a->parts;
if (!a || a->type != TYPEAPPLICATION || !a->subtype ||
if (s->flags & M_DISPLAY)
state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"),
s);
- return;
+ return (-1);
}
/*
state_attach_puts (_
("[-- Error: could not create temporary file! --]\n"),
s);
- return;
+ return (-1);
}
if (s->flags & M_DISPLAY)
fpin = s->fpin;
s->fpin = fpout;
- mutt_body_handler (tattach, s);
+ rc = mutt_body_handler (tattach, s);
s->fpin = fpin;
/*
}
mutt_free_body (&tattach);
+ /* clear 'Invoking...' message, since there's no error */
+ mutt_message _("PGP message successfully decrypted.");
+ } else {
+ mutt_error _("Could not decrypt PGP message");
+ pgp_void_passphrase ();
+ rc = -1;
}
fclose (fpout);
mutt_unlink (tempfile);
+
+ return (rc);
}
/* ----------------------------------------------------------------------------
* recommended for future releases of PGP.
*/
while (fgets (buffer, sizeof (buffer) - 1, pgpout) != NULL) {
- if (mutt_strcmp ("-----BEGIN PGP MESSAGE-----\n", buffer) == 0)
+ if (m_strcmp("-----BEGIN PGP MESSAGE-----\n", buffer) == 0)
fputs ("-----BEGIN PGP SIGNATURE-----\n", fp);
- else if (mutt_strcmp ("-----END PGP MESSAGE-----\n", buffer) == 0)
+ else if (m_strcmp("-----END PGP MESSAGE-----\n", buffer) == 0)
fputs ("-----END PGP SIGNATURE-----\n", fp);
else
fputs (buffer, fp);
t = mutt_new_body ();
t->type = TYPEMULTIPART;
- t->subtype = safe_strdup ("signed");
+ t->subtype = m_strdup("signed");
t->encoding = ENC7BIT;
t->use_disp = 0;
t->disposition = DISPINLINE;
t->parts->next = mutt_new_body ();
t = t->parts->next;
t->type = TYPEAPPLICATION;
- t->subtype = safe_strdup ("pgp-signature");
- t->filename = safe_strdup (sigfile);
+ t->subtype = m_strdup("pgp-signature");
+ t->filename = m_strdup(sigfile);
t->use_disp = 0;
t->disposition = DISPINLINE;
t->encoding = ENC7BIT;
/* or should we require the "0x"? */
if (strncmp (s, "0x", 2) == 0)
s += 2;
- if (mutt_strlen (s) % 8)
+ if (m_strlen(s) % 8)
return 0;
while (*s)
if (strchr ("0123456789ABCDEFabcdef", *s++) == NULL)
/* This routine attempts to find the keyids of the recipients of a message.
* It returns NULL if any of the keys can not be found.
*/
-char *pgp_findKeys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc)
+char *pgp_findKeys (address_t * to, address_t * cc, address_t * bcc)
{
char *keyID, *keylist = NULL, *t;
size_t keylist_size = 0;
size_t keylist_used = 0;
- ADDRESS *tmp = NULL, *addr = NULL;
- ADDRESS **last = &tmp;
- ADDRESS *p, *q;
+ address_t *tmp = NULL, *addr = NULL;
+ address_t **last = &tmp;
+ address_t *p, *q;
int i;
pgp_key_t k_info = NULL, key = NULL;
abort ();
}
- *last = rfc822_cpy_adr (p);
+ *last = address_list_dup (p);
while (*last)
last = &((*last)->next);
}
k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING);
}
else if (r == -1) {
- FREE (&keylist);
- rfc822_free_address (&tmp);
- rfc822_free_address (&addr);
+ p_delete(&keylist);
+ address_delete (&tmp);
+ address_delete (&addr);
return NULL;
}
}
if ((key = pgp_ask_for_key (buf, q->mailbox,
KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) {
- FREE (&keylist);
- rfc822_free_address (&tmp);
- rfc822_free_address (&addr);
+ p_delete(&keylist);
+ address_delete (&tmp);
+ address_delete (&addr);
return NULL;
}
}
keyID = pgp_keyid (key);
bypass_selection:
- keylist_size += mutt_strlen (keyID) + 4;
- safe_realloc (&keylist, keylist_size);
+ keylist_size += m_strlen(keyID) + 4;
+ p_realloc(&keylist, keylist_size);
sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "", /* __SPRINTF_CHECKED__ */
keyID);
- keylist_used = mutt_strlen (keylist);
+ keylist_used = m_strlen(keylist);
pgp_free_key (&key);
- rfc822_free_address (&addr);
+ address_delete (&addr);
}
- rfc822_free_address (&tmp);
+ address_delete (&tmp);
return (keylist);
}
if (empty) {
/* fatal error while trying to encrypt message */
+ if (sign)
+ pgp_void_passphrase (); /* just in case */
unlink (tempfile);
return (NULL);
}
t = mutt_new_body ();
t->type = TYPEMULTIPART;
- t->subtype = safe_strdup ("encrypted");
+ t->subtype = m_strdup("encrypted");
t->encoding = ENC7BIT;
t->use_disp = 0;
t->disposition = DISPINLINE;
t->parts = mutt_new_body ();
t->parts->type = TYPEAPPLICATION;
- t->parts->subtype = safe_strdup ("pgp-encrypted");
+ t->parts->subtype = m_strdup("pgp-encrypted");
t->parts->encoding = ENC7BIT;
t->parts->next = mutt_new_body ();
t->parts->next->type = TYPEAPPLICATION;
- t->parts->next->subtype = safe_strdup ("octet-stream");
+ t->parts->next->subtype = m_strdup("octet-stream");
t->parts->next->encoding = ENC7BIT;
- t->parts->next->filename = safe_strdup (tempfile);
+ t->parts->next->filename = m_strdup(tempfile);
t->parts->next->use_disp = 1;
t->parts->next->disposition = DISPINLINE;
t->parts->next->unlink = 1; /* delete after sending the message */
- t->parts->next->d_filename = safe_strdup ("msg.asc"); /* non pgp/mime can save */
+ t->parts->next->d_filename = m_strdup("msg.asc"); /* non pgp/mime can save */
return (t);
}
mutt_any_key_to_continue (NULL);
if (empty) {
+ if (flags & SIGN)
+ pgp_void_passphrase (); /* just in case */
unlink (pgpoutfile);
return NULL;
}
b->encoding = ENC7BIT;
b->type = TYPETEXT;
- b->subtype = safe_strdup ("plain");
+ b->subtype = m_strdup("plain");
mutt_set_parameter ("x-action",
flags & ENCRYPT ? "pgp-encrypted" : "pgp-signed",
&b->parameter);
mutt_set_parameter ("charset", send_charset, &b->parameter);
- b->filename = safe_strdup (pgpoutfile);
+ b->filename = m_strdup(pgpoutfile);
#if 0
/* The following is intended to give a clue to some completely brain-dead
* "mail environments" which are typically used by large corporations.
*/
- b->d_filename = safe_strdup ("msg.pgp");
+ b->d_filename = m_strdup("msg.pgp");
b->use_disp = 1;
#endif
char prompt[LONG_STRING];
- if (!(WithCrypto & APPLICATION_PGP))
- return msg->security;
-
/* If autoinline and no crypto options set, then set inline. */
if (option (OPTPGPAUTOINLINE) && !((msg->security & APPLICATION_PGP)
&& (msg->security & (SIGN | ENCRYPT))))
pgp_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
PGP_PUBRING))) {
snprintf (input_signas, sizeof (input_signas), "0x%s", pgp_keyid (p));
- str_replace (&PgpSignAs, input_signas);
+ m_strreplace(&PgpSignAs, input_signas);
pgp_free_key (&p);
msg->security |= SIGN;
return (msg->security);
}
-
-
-#endif /* CRYPT_BACKEND_CLASSIC_PGP */