summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2023-07-07 14:06:16 +0200
committerJustus Winter <justus@sequoia-pgp.org>2023-07-07 14:23:28 +0200
commita9c4715115ceaf766b277cc89bcda52f42cb0b75 (patch)
tree2b8bc8735f63dea120454f326c6bb52cfd51687b
parent5674e70f924202c1cd3d627f75cc9980b4777f7d (diff)
openpgp: Fix message structure validation.
- Once we finished processing the message, check that it actually conformed to the message grammar.
-rw-r--r--openpgp/src/parse/stream.rs50
1 files changed, 49 insertions, 1 deletions
diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs
index 23466f20..870c728f 100644
--- a/openpgp/src/parse/stream.rs
+++ b/openpgp/src/parse/stream.rs
@@ -2698,6 +2698,17 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> {
self.push_sig(p)?;
}
+ // If we finished parsing, validate the message structure.
+ if let PacketParserResult::EOF(eof) = ppr {
+ // If we parse a signed message synthesized from a
+ // cleartext signature framework message, we don't
+ // quite get the structure right, so relax the
+ // requirement in this case.
+ if ! self.processing_csf_message.expect("set by now") {
+ eof.is_message()?;
+ }
+ }
+
self.verify_signatures()
} else {
t!("Didn't hit EOF.");
@@ -3002,7 +3013,7 @@ pub mod test {
crypto::Password,
};
- #[derive(PartialEq)]
+ #[derive(Clone, PartialEq)]
pub struct VHelper {
good: usize,
unknown: usize,
@@ -3974,4 +3985,41 @@ xHUDBRY0WIQ+50WENDPP";
.with_policy(&p, None, h);
Ok(())
}
+
+ /// Tests that the message structure is checked at the end of
+ /// parsing the packet stream.
+ #[test]
+ fn message_grammar_check() -> Result<()> {
+ let p = P::new();
+ let certs = vec![Cert::from_bytes(crate::tests::key("neal.pgp"))?];
+ let helper = VHelper::new(1, 0, 0, 0, certs.clone());
+
+ let pp = crate::PacketPile::from_bytes(
+ crate::tests::message("signed-1-notarized-by-ed25519.pgp"))?;
+ let mut buf = Vec::new();
+ assert_eq!(pp.children().count(), 5);
+ // Drop the last signature packet! Now the OPS and Signature
+ // packets no longer bracket.
+ pp.children().take(4).for_each(|p| p.serialize(&mut buf).unwrap());
+
+ // Test verifier.
+ let do_it = || -> Result<()> {
+ let v = VerifierBuilder::from_bytes(&buf)?
+ .with_policy(&p, crate::frozen_time(), helper.clone())?;
+ assert!(v.message_processed());
+ Ok(())
+ };
+ assert!(do_it().is_err());
+
+ // Test decryptor.
+ let do_it = || -> Result<()> {
+ let v = DecryptorBuilder::from_bytes(&buf)?
+ .with_policy(&p, crate::frozen_time(), helper)?;
+ assert!(v.message_processed());
+ Ok(())
+ };
+ assert!(do_it().is_err());
+
+ Ok(())
+ }
}