diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2023-07-07 14:06:16 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2023-07-07 14:23:28 +0200 |
commit | a9c4715115ceaf766b277cc89bcda52f42cb0b75 (patch) | |
tree | 2b8bc8735f63dea120454f326c6bb52cfd51687b | |
parent | 5674e70f924202c1cd3d627f75cc9980b4777f7d (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.rs | 50 |
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(()) + } } |