diff --git a/src/proto/de.rs b/src/proto/de.rs index 404eed5..0e1e2df 100644 --- a/src/proto/de.rs +++ b/src/proto/de.rs @@ -49,8 +49,10 @@ pub fn from_bytes<'a, T: Deserialize<'a>>(bytes: &[u8]) -> ProtoResult { impl<'de, 'a, R: io::Read> de::Deserializer<'de> for &'a mut Deserializer { type Error = ProtoError; - fn deserialize_any>(self, _visitor: V) -> ProtoResult { - unimplemented!() + fn deserialize_any>(self, visitor: V) -> ProtoResult { + let mut bytes = vec![]; + self.reader.read_to_end(&mut bytes)?; + visitor.visit_byte_buf(bytes) } fn deserialize_bool>(self, visitor: V) -> ProtoResult { diff --git a/src/proto/message.rs b/src/proto/message.rs index 067df1a..178b972 100644 --- a/src/proto/message.rs +++ b/src/proto/message.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use serde::de::{Deserializer, Visitor}; use super::private_key::PrivateKey; @@ -52,8 +53,42 @@ pub struct AddSmartcardKeyConstrained { #[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] pub struct Extension { - extension_type: String, - extension_contents: Vec + pub extension_type: String, + pub extension_contents: ExtensionContents, +} + +#[derive(Debug, PartialEq, Clone)] +pub struct ExtensionContents(pub Vec); + +impl Serialize for ExtensionContents { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer { + serializer.serialize_bytes(&self.0) + } +} + +impl<'de> Deserialize<'de> for ExtensionContents { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ContentsVisitor; + + impl<'de> Visitor<'de> for ContentsVisitor { + type Value = ExtensionContents; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("raw bytes buffer") + } + + fn visit_byte_buf(self, v: Vec) -> Result { + Ok(ExtensionContents(v)) + } + } + + deserializer.deserialize_any(ContentsVisitor) + } } pub type Passphrase = String; diff --git a/src/proto/tests/mod.rs b/src/proto/tests/mod.rs index 98d9b1c..8888c85 100644 --- a/src/proto/tests/mod.rs +++ b/src/proto/tests/mod.rs @@ -1,7 +1,7 @@ use super::{to_bytes, from_bytes, Blob}; use super::public_key::*; use super::private_key::*; -use super::message::{Message, SignRequest, Identity}; +use super::message::{Message, SignRequest, Identity, Extension}; use super::signature::Signature; #[test] @@ -163,3 +163,10 @@ fn raw_protocol_test() { assert_eq!(response_bytes.as_slice(), &include_bytes!("id_ans_response.bin")[..]); } + +#[test] +fn test_extension() { + let extension_bytes: &[u8] = &[0, 0, 0, 24, 115, 101, 115, 115, 105, 111, 110, 45, 98, 105, 110, 100, 64, 111, 112, 101, 110, 115, 115, 104, 46, 99, 111, 109, 0, 0, 0, 51, 0, 0, 0, 11, 115, 115, 104, 45, 101, 100, 50, 53, 53, 49, 57, 0, 0, 0, 32, 177, 185, 198, 92, 165, 45, 127, 95, 202, 195, 226, 63, 6, 115, 10, 104, 18, 137, 172, 240, 153, 154, 174, 74, 83, 7, 1, 204, 14, 177, 153, 40, 0, 0, 0, 32, 175, 96, 42, 133, 218, 171, 58, 220, 97, 78, 155, 114, 20, 67, 90, 133, 24, 185, 156, 71, 128, 163, 234, 195, 202, 15, 160, 177, 130, 229, 114, 164, 0, 0, 0, 83, 0, 0, 0, 11, 115, 115, 104, 45, 101, 100, 50, 53, 53, 49, 57, 0, 0, 0, 64, 4, 235, 93, 135, 144, 110, 220, 24, 17, 150, 40, 11, 143, 37, 207, 58, 215, 159, 23, 233, 95, 218, 115, 22, 205, 101, 55, 159, 146, 42, 121, 190, 229, 82, 75, 174, 143, 199, 121, 141, 52, 155, 73, 215, 119, 220, 104, 241, 116, 83, 96, 129, 184, 12, 93, 93, 33, 243, 171, 236, 201, 123, 17, 1, 0]; + let extension: Extension = from_bytes(&extension_bytes).unwrap(); + assert_eq!(extension.extension_type, "session-bind@openssh.com"); +}