summaryrefslogtreecommitdiffstats
path: root/pgp.c
diff options
context:
space:
mode:
authorKevin McCarthy <kevin@8t8.us>2018-06-04 21:31:33 -0700
committerKevin McCarthy <kevin@8t8.us>2018-06-04 21:37:49 -0700
commitedb4ec84f7078a188ee4c9491405418adf26eb1c (patch)
tree1a82dd6e8304a928fabeb3f613c53c68d2878d35 /pgp.c
parent8ec6d766c7557e42462d0db1ceeb7ccc83556345 (diff)
Add GnuPG status fd checks for inline pgp.
The difficulty is that "BEGIN PGP MESSAGE" could be a signed and armored part, so we can't fail hard if it isn't encrypted. Change pgp_check_decryption_okay() to return more status codes, with >=0 indicating an actual decryption; -2 and -1 indicating plaintext found; and -3 indicating an actual DECRYPTION_FAILED status code seen. Fail hard on -3, but change the message for -2 and -1 to indicate the message was not encrypted.
Diffstat (limited to 'pgp.c')
-rw-r--r--pgp.c110
1 files changed, 74 insertions, 36 deletions
diff --git a/pgp.c b/pgp.c
index c9a4c91f..60971119 100644
--- a/pgp.c
+++ b/pgp.c
@@ -268,6 +268,20 @@ static int pgp_check_pgp_decryption_okay_regexp (FILE *fpin)
/* Checks GnuPGP status fd output for various status codes indicating
* an issue. If $pgp_check_gpg_decrypt_status_fd is unset, it falls
* back to the old behavior of just scanning for $pgp_decryption_okay.
+ *
+ * pgp_decrypt_part() should fail if the part is not encrypted, so we return
+ * less than 0 to indicate part or all was NOT actually encrypted.
+ *
+ * On the other hand, for pgp_application_pgp_handler(), a
+ * "BEGIN PGP MESSAGE" could indicate a signed and armored message.
+ * For that we allow -1 and -2 as "valid" (with a warning).
+ *
+ * Returns:
+ * 1 - no patterns were matched (if delegated to decryption_okay_regexp)
+ * 0 - DECRYPTION_OKAY was seen, with no PLAINTEXT outside.
+ * -1 - No decryption status codes were encountered
+ * -2 - PLAINTEXT was encountered outside of DECRYPTION delimeters.
+ * -3 - DECRYPTION_FAILED was encountered
*/
static int pgp_check_decryption_okay (FILE *fpin)
{
@@ -295,15 +309,15 @@ static int pgp_check_decryption_okay (FILE *fpin)
{
if (!inside_decrypt)
{
- dprint (2, (debugfile, "\tPLAINTEXT encountered outside of DECRYPTION. Failure.\n"));
- rv = -1;
- break;
+ dprint (2, (debugfile, "\tPLAINTEXT encountered outside of DECRYPTION.\n"));
+ if (rv > -2)
+ rv = -2;
}
}
else if (mutt_strncmp (s, "DECRYPTION_FAILED", 17) == 0)
{
dprint (2, (debugfile, "\tDECRYPTION_FAILED encountered. Failure.\n"));
- rv = -1;
+ rv = -3;
break;
}
else if (mutt_strncmp (s, "DECRYPTION_OKAY", 15) == 0)
@@ -311,7 +325,8 @@ static int pgp_check_decryption_okay (FILE *fpin)
/* Don't break out because we still have to check for
* PLAINTEXT outside of the decryption boundaries. */
dprint (2, (debugfile, "\tDECRYPTION_OKAY encountered.\n"));
- rv = 0;
+ if (rv > -2)
+ rv = 0;
}
}
FREE (&line);
@@ -386,14 +401,15 @@ static void pgp_copy_clearsigned (FILE *fpin, STATE *s, char *charset)
int pgp_application_pgp_handler (BODY *m, STATE *s)
{
- int could_not_decrypt = 0;
+ int could_not_decrypt, decrypt_okay_rc;
int needpass = -1, pgp_keyblock = 0;
int clearsign = 0, rv, rc;
int c = 1; /* silence GCC warning */
long bytes;
LOFF_T last_pos, offset;
char buf[HUGE_STRING];
- char outfile[_POSIX_PATH_MAX];
+ char pgpoutfile[_POSIX_PATH_MAX];
+ char pgperrfile[_POSIX_PATH_MAX];
char tmpfname[_POSIX_PATH_MAX];
FILE *pgpout = NULL, *pgpin = NULL, *pgperr = NULL;
FILE *tmpfp = NULL;
@@ -423,6 +439,8 @@ int pgp_application_pgp_handler (BODY *m, STATE *s)
if (mutt_strncmp ("-----BEGIN PGP ", buf, 15) == 0)
{
clearsign = 0;
+ could_not_decrypt = 0;
+ decrypt_okay_rc = 0;
if (mutt_strcmp ("MESSAGE-----\n", buf + 15) == 0)
needpass = 1;
@@ -487,21 +505,31 @@ int pgp_application_pgp_handler (BODY *m, STATE *s)
/* Invoke PGP if needed */
if (!clearsign || (s->flags & MUTT_VERIFY))
{
- mutt_mktemp (outfile, sizeof (outfile));
- if ((pgpout = safe_fopen (outfile, "w+")) == NULL)
+ mutt_mktemp (pgpoutfile, sizeof (pgpoutfile));
+ if ((pgpout = safe_fopen (pgpoutfile, "w+")) == NULL)
{
- mutt_perror (outfile);
- return -1;
+ mutt_perror (pgpoutfile);
+ rc = -1;
+ goto out;
}
-
- if ((thepid = pgp_invoke_decode (&pgpin, NULL, &pgperr, -1,
- fileno (pgpout), -1, tmpfname,
- needpass)) == -1)
+ unlink (pgpoutfile);
+
+ mutt_mktemp (pgperrfile, sizeof (pgperrfile));
+ if ((pgperr = safe_fopen (pgperrfile, "w+")) == NULL)
+ {
+ mutt_perror (pgperrfile);
+ rc = -1;
+ goto out;
+ }
+ unlink (pgperrfile);
+
+ if ((thepid = pgp_invoke_decode (&pgpin, NULL, NULL,
+ -1, fileno (pgpout), fileno (pgperr),
+ tmpfname, needpass)) == -1)
{
safe_fclose (&pgpout);
maybe_goodsig = 0;
pgpin = NULL;
- pgperr = NULL;
state_attach_puts (_("[-- Error: unable to create PGP subprocess! --]\n"), s);
}
else /* PGP started successfully */
@@ -513,20 +541,33 @@ int pgp_application_pgp_handler (BODY *m, STATE *s)
*PgpPass = 0;
fprintf (pgpin, "%s\n", PgpPass);
}
-
+
safe_fclose (&pgpin);
+ rv = mutt_wait_filter (thepid);
+
+ fflush (pgperr);
+ /* If we are expecting an encrypted message, verify status fd output.
+ * Note that BEGIN PGP MESSAGE does not guarantee the content is encrypted,
+ * so we need to be more selective about the value of decrypt_okay_rc.
+ *
+ * -3 indicates we actively found a DECRYPTION_FAILED.
+ * -2 and -1 indicate part or all of the content was plaintext.
+ */
+ if (needpass)
+ {
+ rewind (pgperr);
+ decrypt_okay_rc = pgp_check_decryption_okay (pgperr);
+ if (decrypt_okay_rc <= -3)
+ safe_fclose (&pgpout);
+ }
+
if (s->flags & MUTT_DISPLAY)
{
+ rewind (pgperr);
crypt_current_time (s, "PGP");
rc = pgp_copy_checksig (pgperr, s->fpout);
- }
-
- safe_fclose (&pgperr);
- rv = mutt_wait_filter (thepid);
-
- if (s->flags & MUTT_DISPLAY)
- {
+
if (rc == 0) have_any_sigs = 1;
/*
* Sig is bad if
@@ -556,7 +597,8 @@ int pgp_application_pgp_handler (BODY *m, STATE *s)
pgp_void_passphrase ();
}
- if (could_not_decrypt && !(s->flags & MUTT_DISPLAY))
+ if ((could_not_decrypt || (decrypt_okay_rc <= -3)) &&
+ !(s->flags & MUTT_DISPLAY))
{
mutt_error _("Could not decrypt PGP message");
mutt_sleep (1);
@@ -608,11 +650,8 @@ int pgp_application_pgp_handler (BODY *m, STATE *s)
*/
safe_fclose (&tmpfp);
mutt_unlink (tmpfname);
- if (pgpout)
- {
- safe_fclose (&pgpout);
- mutt_unlink (outfile);
- }
+ safe_fclose (&pgpout);
+ safe_fclose (&pgperr);
if (s->flags & MUTT_DISPLAY)
{
@@ -620,8 +659,10 @@ int pgp_application_pgp_handler (BODY *m, STATE *s)
if (needpass)
{
state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
- if (could_not_decrypt)
+ if (could_not_decrypt || (decrypt_okay_rc <= -3))
mutt_error _("Could not decrypt PGP message");
+ else if (decrypt_okay_rc < 0)
+ mutt_error _("PGP message was not encrypted.");
else
mutt_message _("PGP message successfully decrypted.");
}
@@ -651,11 +692,8 @@ out:
safe_fclose (&tmpfp);
mutt_unlink (tmpfname);
}
- if (pgpout)
- {
- safe_fclose (&pgpout);
- mutt_unlink (outfile);
- }
+ safe_fclose (&pgpout);
+ safe_fclose (&pgperr);
FREE(&gpgcharset);