summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2023-04-13 10:46:00 +0200
committerJustus Winter <justus@sequoia-pgp.org>2023-04-17 18:01:31 +0200
commitd6a77fac8070df37589e3bac89d4f0e7ed87cf15 (patch)
treec969485d72f7a35ec283061e457b33c7bdac0d1e
parent1840f5f3f9d306330dc96b21536037aa7d732439 (diff)
openpgp: Handle concatenated certs in the RawCertParser.
- Fixes #970.
-rw-r--r--openpgp/src/cert/raw.rs33
1 files changed, 33 insertions, 0 deletions
diff --git a/openpgp/src/cert/raw.rs b/openpgp/src/cert/raw.rs
index 49c0adb8..c16de091 100644
--- a/openpgp/src/cert/raw.rs
+++ b/openpgp/src/cert/raw.rs
@@ -696,6 +696,24 @@ impl<'a> Iterator for RawCertParser<'a>
return None;
}
+ if self.reader.eof() && self.dearmor {
+ // We are dearmoring and hit EOF. Maybe there is a second
+ // armor block next to this one!
+
+ // Get the reader,
+ let reader = std::mem::replace(
+ &mut self.reader,
+ EOF::with_cookie(Default::default()).as_boxed());
+
+ // peel off the armor reader,
+ let reader = reader.into_inner().expect("the armor reader");
+
+ // and install a new one!
+ self.reader = armor::Reader::from_buffered_reader(
+ reader, armor::ReaderMode::Tolerant(None),
+ Default::default()).as_boxed();
+ }
+
if self.reader.eof() {
return None;
}
@@ -1606,4 +1624,19 @@ mod test {
matches!(raw.map_err(|e| e.downcast::<Error>()),
Err(Ok(Error::MalformedCert(_)))));
}
+
+ #[test]
+ fn concatenated_armored_certs() -> Result<()> {
+ let mut keyring = Vec::new();
+ keyring.extend_from_slice(b"some\ntext\n");
+ keyring.extend_from_slice(crate::tests::key("testy.asc"));
+ keyring.extend_from_slice(crate::tests::key("testy.asc"));
+ keyring.extend_from_slice(b"some\ntext\n");
+ keyring.extend_from_slice(crate::tests::key("testy.asc"));
+ keyring.extend_from_slice(b"some\ntext\n");
+ let certs = RawCertParser::from_bytes(&keyring)?.collect::<Vec<_>>();
+ assert_eq!(certs.len(), 3);
+ assert!(certs.iter().all(|c| c.is_ok()));
+ Ok(())
+ }
}