1 //! Packet container support. 2 //! 3 //! Some packets contain other packets. This creates a tree 4 //! structure. 5 6 use std::fmt; 7 use std::hash::{Hash, Hasher}; 8 use std::slice; 9 use std::vec; 10 11 use crate::{ 12 Packet, 13 crypto::hash, 14 packet::Iter, 15 types::HashAlgorithm, 16 }; 17 18 /// A packet's body holds either unprocessed bytes, processed bytes, 19 /// or packets. 20 /// 21 /// We conceptually divide packets into two parts: the header and the 22 /// body. Whereas the header is read eagerly when the packet is 23 /// deserialized, the body is only read on demand. 24 /// 25 /// A packet's body is stored here either when configured via 26 /// [`PacketParserBuilder::buffer_unread_content`], when one of the 27 /// [`PacketPile`] deserialization routines is used, or on demand for 28 /// a particular packet using the 29 /// [`PacketParser::buffer_unread_content`] method. 30 /// 31 /// [`PacketParserBuilder::buffer_unread_content`]: ../parse/struct.PacketParserBuilder.html#method.buffer_unread_content 32 /// [`PacketPile`]: ../struct.PacketPile.html 33 /// [`PacketParser::buffer_unread_content`]: ../parse/struct.PacketParser.html#method.buffer_unread_content 34 /// 35 /// There are three different types of packets: 36 /// 37 /// - Packets like the [`UserID`] and [`Signature`] packets, don't 38 /// actually have a body. 39 /// 40 /// [`UserID`]: ../packet/struct.UserID.html 41 /// [`Signature`]: ../packet/signature/struct.Signature.html 42 /// 43 /// - One packet, the literal data packet, includes unstructured 44 /// data. That data is stored in [`Literal`]. 45 /// 46 /// [`Literal`]: ../packet/struct.Literal.html 47 /// 48 /// - Some packets are containers. If the parser does not parse the 49 /// packet's child, either because the caller used 50 /// [`PacketParser::next`] to get the next packet, or the maximum 51 /// recursion depth was reached, then the packets can be stored here 52 /// as a byte stream. (If the caller so chooses, the content can be 53 /// parsed later using the regular deserialization routines, since 54 /// the content is just an OpenPGP message.) 55 /// 56 /// [`PacketParser::next`]: ../parse/struct.PacketParser.html#method.next 57 #[derive(Clone, Debug)] 58 pub enum Body { 59 /// Unprocessed packet body. 60 /// 61 /// The body has not been processed, i.e. it is still encrypted. 62 /// 63 /// Note: if some of a packet's data is streamed, and the 64 /// `PacketParser` is configured to buffer unread content, then 65 /// this is not the packet's entire content; it is just the unread 66 /// content. 67 Unprocessed(Vec<u8>), 68 69 /// Processed packed body. 70 /// 71 /// The body has been processed, i.e. decompressed or decrypted, 72 /// but not parsed into packets. 73 /// 74 /// Note: if some of a packet's data is streamed, and the 75 /// `PacketParser` is configured to buffer unread content, then 76 /// this is not the packet's entire content; it is just the unread 77 /// content. 78 Processed(Vec<u8>), 79 80 /// Parsed packet body. 81 /// 82 /// Used by container packets (such as the encryption and 83 /// compression packets) to reference their immediate children. 84 /// This results in a tree structure. 85 /// 86 /// This is automatically populated when using the [`PacketPile`] 87 /// deserialization routines, e.g., [`PacketPile::from_file`]. By 88 /// default, it is *not* automatically filled in by the 89 /// [`PacketParser`] deserialization routines; this needs to be 90 /// done manually. 91 /// 92 /// [`PacketPile`]: ../struct.PacketPile.html 93 /// [`PacketPile::from_file`]: ../struct.PacketPile.html#method.from_file 94 /// [`PacketParser`]: ../parse/struct.PacketParser.html 95 Structured(Vec<Packet>), 96 } 97 98 /// Holds packet bodies. 99 /// 100 /// This is used by OpenPGP container packets, like the compressed 101 /// data packet, to store the containing packets. 102 #[derive(Clone)] 103 pub struct Container { 104 /// Holds a packet's body. 105 body: Body, 106 107 /// We compute a digest over the body to implement comparison. 108 body_digest: Vec<u8>, 109 } 110 111 impl std::ops::Deref for Container { 112 type Target = Body; deref(&self) -> &Self::Target113 fn deref(&self) -> &Self::Target { 114 &self.body 115 } 116 } 117 118 // Pick the fastest hash function from the SHA2 family for the 119 // architectures word size. On 64-bit architectures, SHA512 is almost 120 // twice as fast, but on 32-bit ones, SHA256 is faster. 121 #[cfg(target_pointer_width = "64")] 122 const CONTAINER_BODY_HASH: HashAlgorithm = HashAlgorithm::SHA512; 123 #[cfg(not(target_pointer_width = "64"))] 124 const CONTAINER_BODY_HASH: HashAlgorithm = HashAlgorithm::SHA256; 125 126 impl PartialEq for Container { eq(&self, other: &Container) -> bool127 fn eq(&self, other: &Container) -> bool { 128 use Body::*; 129 match (&self.body, &other.body) { 130 (Unprocessed(_), Unprocessed(_)) => 131 self.body_digest == other.body_digest, 132 (Processed(_), Processed(_)) => 133 self.body_digest == other.body_digest, 134 (Structured(a), Structured(b)) => 135 a == b, 136 _ => false, 137 } 138 } 139 } 140 141 impl Eq for Container {} 142 143 impl Hash for Container { hash<H: Hasher>(&self, state: &mut H)144 fn hash<H: Hasher>(&self, state: &mut H) { 145 if let Body::Structured(packets) = &self.body { 146 packets.hash(state); 147 } else { 148 self.body_digest.hash(state); 149 } 150 } 151 } 152 153 impl Default for Container { default() -> Self154 fn default() -> Self { 155 Self { 156 body: Body::Structured(Vec::with_capacity(0)), 157 body_digest: Vec::with_capacity(0), 158 } 159 } 160 } 161 162 impl From<Vec<Packet>> for Container { from(packets: Vec<Packet>) -> Self163 fn from(packets: Vec<Packet>) -> Self { 164 Self { 165 body: Body::Structured(packets), 166 body_digest: Vec::with_capacity(0), 167 } 168 } 169 } 170 171 impl fmt::Debug for Container { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result172 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 173 fn fmt_bytes(f: &mut fmt::Formatter, tag: &str, bytes: &[u8], 174 digest: String) 175 -> fmt::Result 176 { 177 let threshold = 16; 178 let prefix = &bytes[..std::cmp::min(threshold, bytes.len())]; 179 let mut prefix_fmt = crate::fmt::hex::encode(prefix); 180 if bytes.len() > threshold { 181 prefix_fmt.push_str("..."); 182 } 183 prefix_fmt.push_str(&format!(" ({} bytes)", bytes.len())[..]); 184 185 f.debug_struct("Container") 186 .field(tag, &prefix_fmt) 187 .field("digest", &digest) 188 .finish() 189 } 190 191 use Body::*; 192 match &self.body { 193 Unprocessed(bytes) => 194 fmt_bytes(f, "unprocessed", bytes, self.body_digest()), 195 Processed(bytes) => 196 fmt_bytes(f, "processed", bytes, self.body_digest()), 197 Structured(packets) => 198 f.debug_struct("Container").field("packets", packets).finish(), 199 } 200 } 201 } 202 203 impl Container { default_unprocessed() -> Self204 pub(crate) fn default_unprocessed() -> Self { 205 Self { 206 body: Body::Unprocessed(Vec::with_capacity(0)), 207 body_digest: Self::empty_body_digest(), 208 } 209 } 210 211 /// Returns a reference to this Packet's children. 212 /// 213 /// Returns `None` if the body is not structured. children_ref(&self) -> Option<&[Packet]>214 pub fn children_ref(&self) -> Option<&[Packet]> { 215 if let Body::Structured(packets) = &self.body { 216 Some(&packets[..]) 217 } else { 218 None 219 } 220 } 221 222 /// Returns a mutable reference to this Packet's children. 223 /// 224 /// Returns `None` if the body is not structured. children_mut(&mut self) -> Option<&mut Vec<Packet>>225 pub fn children_mut(&mut self) -> Option<&mut Vec<Packet>> { 226 if let Body::Structured(packets) = &mut self.body { 227 Some(packets) 228 } else { 229 None 230 } 231 } 232 233 /// Returns an iterator over the packet's descendants. The 234 /// descendants are visited in depth-first order. 235 /// 236 /// Returns `None` if the body is not structured. descendants(&self) -> Option<Iter>237 pub fn descendants(&self) -> Option<Iter> { 238 Some(Iter { 239 // Iterate over each packet in the message. 240 children: self.children()?, 241 child: None, 242 grandchildren: None, 243 depth: 0, 244 }) 245 } 246 247 /// Returns an iterator over the packet's immediate children. 248 /// 249 /// Returns `None` if the body is not structured. children<'a>(&'a self) -> Option<slice::Iter<'a, Packet>>250 pub fn children<'a>(&'a self) -> Option<slice::Iter<'a, Packet>> { 251 Some(self.children_ref()?.iter()) 252 } 253 254 /// Returns an `IntoIter` over the packet's immediate children. 255 /// 256 /// Returns `None` if the body is not structured. into_children(self) -> Option<vec::IntoIter<Packet>>257 pub fn into_children(self) -> Option<vec::IntoIter<Packet>> { 258 if let Body::Structured(packets) = self.body { 259 Some(packets.into_iter()) 260 } else { 261 None 262 } 263 } 264 265 /// Gets the packet's body. body(&self) -> &Body266 pub fn body(&self) -> &Body { 267 &self.body 268 } 269 270 /// Sets the packet's body. set_body(&mut self, body: Body) -> Body271 pub fn set_body(&mut self, body: Body) -> Body { 272 use Body::*; 273 let mut h = Self::make_body_hash(); 274 match &body { 275 Unprocessed(bytes) => h.update(bytes), 276 Processed(bytes) => h.update(bytes), 277 Structured(_) => (), 278 } 279 self.set_body_hash(h); 280 std::mem::replace(&mut self.body, body) 281 } 282 283 /// Returns the hash for the empty body. empty_body_digest() -> Vec<u8>284 fn empty_body_digest() -> Vec<u8> { 285 lazy_static!{ 286 static ref DIGEST: Vec<u8> = { 287 let mut h = Container::make_body_hash(); 288 let mut d = vec![0; h.digest_size()]; 289 h.digest(&mut d); 290 d 291 }; 292 } 293 294 DIGEST.clone() 295 } 296 297 /// Creates a hash context for hashing the body. 298 pub(crate) // For parse.rs make_body_hash() -> hash::Context299 fn make_body_hash() -> hash::Context { 300 CONTAINER_BODY_HASH.context() 301 .expect("CONTAINER_BODY_HASH must be implemented") 302 } 303 304 /// Hashes content that has been streamed. 305 pub(crate) // For parse.rs set_body_hash(&mut self, mut h: hash::Context)306 fn set_body_hash(&mut self, mut h: hash::Context) { 307 self.body_digest.resize(h.digest_size(), 0); 308 h.digest(&mut self.body_digest); 309 } 310 311 pub(crate) body_digest(&self) -> String312 fn body_digest(&self) -> String { 313 crate::fmt::hex::encode(&self.body_digest) 314 } 315 316 // Converts an indentation level to whitespace. indent(depth: usize) -> &'static str317 fn indent(depth: usize) -> &'static str { 318 use std::cmp; 319 320 let s = " "; 321 return &s[0..cmp::min(depth, s.len())]; 322 } 323 324 // Pretty prints the container to stderr. 325 // 326 // This function is primarily intended for debugging purposes. 327 // 328 // `indent` is the number of spaces to indent the output. pretty_print(&self, indent: usize)329 pub(crate) fn pretty_print(&self, indent: usize) { 330 for (i, p) in self.children_ref().iter().enumerate() { 331 eprintln!("{}{}: {:?}", 332 Self::indent(indent), i + 1, p); 333 if let Some(ref children) = self.children_ref() 334 .and_then(|c| c.get(i)).and_then(|p| p.container_ref()) 335 { 336 children.pretty_print(indent + 1); 337 } 338 } 339 } 340 } 341 342 macro_rules! impl_body_forwards { 343 ($typ:ident) => { 344 /// This packet implements the unprocessed container 345 /// interface. 346 /// 347 /// Container packets like this one can contain unprocessed 348 /// data. 349 impl $typ { 350 /// Returns a reference to the container. 351 pub(crate) fn container_ref(&self) -> &packet::Container { 352 &self.container 353 } 354 355 /// Returns a mutable reference to the container. 356 pub(crate) fn container_mut(&mut self) -> &mut packet::Container { 357 &mut self.container 358 } 359 360 /// Gets a reference to the this packet's body. 361 pub fn body(&self) -> &[u8] { 362 use crate::packet::Body::*; 363 match self.container.body() { 364 Unprocessed(bytes) => bytes, 365 Processed(_) => unreachable!( 366 "Unprocessed container has processed body"), 367 Structured(_) => unreachable!( 368 "Unprocessed container has structured body"), 369 } 370 } 371 372 /// Sets the this packet's body. 373 pub fn set_body(&mut self, data: Vec<u8>) -> Vec<u8> { 374 use crate::packet::{Body, Body::*}; 375 match self.container.set_body(Body::Unprocessed(data)) { 376 Unprocessed(bytes) => bytes, 377 Processed(_) => unreachable!( 378 "Unprocessed container has processed body"), 379 Structured(_) => unreachable!( 380 "Unprocessed container has structured body"), 381 } 382 } 383 } 384 }; 385 } 386 387 impl Packet { 388 pub(crate) // for packet_pile.rs container_ref(&self) -> Option<&Container>389 fn container_ref(&self) -> Option<&Container> { 390 use std::ops::Deref; 391 match self { 392 Packet::CompressedData(p) => Some(p.deref()), 393 Packet::SEIP(p) => Some(p.deref()), 394 Packet::AED(p) => Some(p.deref()), 395 Packet::Literal(p) => Some(p.container_ref()), 396 Packet::Unknown(p) => Some(p.container_ref()), 397 _ => None, 398 } 399 } 400 401 pub(crate) // for packet_pile.rs, packet_pile_parser.rs, parse.rs container_mut(&mut self) -> Option<&mut Container>402 fn container_mut(&mut self) -> Option<&mut Container> { 403 use std::ops::DerefMut; 404 match self { 405 Packet::CompressedData(p) => Some(p.deref_mut()), 406 Packet::SEIP(p) => Some(p.deref_mut()), 407 Packet::AED(p) => Some(p.deref_mut()), 408 Packet::Literal(p) => Some(p.container_mut()), 409 Packet::Unknown(p) => Some(p.container_mut()), 410 _ => None, 411 } 412 } 413 414 /// Returns an iterator over the packet's immediate children. children<'a>(&'a self) -> Option<impl Iterator<Item = &'a Packet>>415 pub(crate) fn children<'a>(&'a self) 416 -> Option<impl Iterator<Item = &'a Packet>> { 417 self.container_ref().and_then(|c| c.children()) 418 } 419 420 /// Returns an iterator over all of the packet's descendants, in 421 /// depth-first order. descendants(&self) -> Option<Iter>422 pub(crate) fn descendants(&self) -> Option<Iter> { 423 self.container_ref().and_then(|c| c.descendants()) 424 } 425 426 /// Retrieves the packet's unprocessed body. 427 #[cfg(test)] unprocessed_body(&self) -> Option<&[u8]>428 pub(crate) fn unprocessed_body(&self) -> Option<&[u8]> { 429 self.container_ref().and_then(|c| match c.body() { 430 Body::Unprocessed(bytes) => Some(&bytes[..]), 431 _ => None, 432 }) 433 } 434 435 /// Retrieves the packet's processed body. 436 #[cfg(test)] processed_body(&self) -> Option<&[u8]>437 pub(crate) fn processed_body(&self) -> Option<&[u8]> { 438 self.container_ref().and_then(|c| match c.body() { 439 Body::Processed(bytes) => Some(&bytes[..]), 440 _ => None, 441 }) 442 } 443 } 444