ssh_agent_lib/proto/message/
response.rs1use ssh_encoding::{CheckedSum, Decode, Encode, Reader, Writer};
3use ssh_key::Signature;
4
5use super::{Extension, Identity};
6use crate::proto::{Error, Result};
7
8#[derive(Clone, PartialEq, Debug)]
14pub enum Response {
15 Failure,
17
18 Success,
20
21 IdentitiesAnswer(Vec<Identity>),
24
25 SignResponse(Signature),
28
29 ExtensionFailure,
31
32 ExtensionResponse(Extension),
35}
36
37impl Response {
38 pub fn message_id(&self) -> u8 {
42 match self {
43 Self::Failure => 5,
44 Self::Success => 6,
45 Self::IdentitiesAnswer(_) => 12,
46 Self::SignResponse(_) => 14,
47 Self::ExtensionFailure => 28,
48 Self::ExtensionResponse(_) => 29,
49 }
50 }
51}
52
53impl Decode for Response {
54 type Error = Error;
55
56 fn decode(reader: &mut impl Reader) -> Result<Self> {
57 let message_type = u8::decode(reader)?;
58
59 match message_type {
60 5 => Ok(Self::Failure),
61 6 => Ok(Self::Success),
62 12 => Identity::decode_vec(reader).map(Self::IdentitiesAnswer),
63 14 => {
64 Ok(reader
65 .read_prefixed(|reader| Signature::decode(reader).map(Self::SignResponse))?)
66 }
67 28 => Ok(Self::ExtensionFailure),
68 29 => Extension::decode(reader).map(Self::ExtensionResponse),
69 command => Err(Error::UnsupportedCommand { command }),
70 }
71 }
72}
73
74impl Encode for Response {
75 fn encoded_len(&self) -> ssh_encoding::Result<usize> {
76 let message_id_len = 1;
77 let payload_len = match self {
78 Self::Failure => 0,
79 Self::Success => 0,
80 Self::IdentitiesAnswer(ids) => {
81 let mut lengths = Vec::with_capacity(1 + ids.len());
82 lengths.push(4);
84
85 for id in ids {
86 lengths.push(id.encoded_len()?);
87 }
88
89 lengths.checked_sum()?
90 }
91 Self::SignResponse(response) => response.encoded_len_prefixed()?,
92 Self::ExtensionFailure => 0,
93 Self::ExtensionResponse(extension) => extension.encoded_len()?,
94 };
95
96 [message_id_len, payload_len].checked_sum()
97 }
98
99 fn encode(&self, writer: &mut impl Writer) -> ssh_encoding::Result<()> {
100 let message_id: u8 = self.message_id();
101 message_id.encode(writer)?;
102
103 match self {
104 Self::Failure => {}
105 Self::Success => {}
106 Self::IdentitiesAnswer(ids) => {
107 (ids.len() as u32).encode(writer)?;
108 for id in ids {
109 id.encode(writer)?;
110 }
111 }
112 Self::SignResponse(response) => response.encode_prefixed(writer)?,
113 Self::ExtensionFailure => {}
114 Self::ExtensionResponse(extension) => extension.encode(writer)?,
115 };
116
117 Ok(())
118 }
119}