1use super::{Result, Error, Write, U8, U32};
2use super::parse_dump_struct;
3use super::parsedump::{ParseDump, too_short, try_u32};
4pub use super::userauth::UserauthRequest;
5pub use super::channelrequest::ChannelRequest;
6
7#[doc(hidden)]
11#[macro_export]
12macro_rules! check_msg_type {
13 ($name:ident, $expected:expr, $bytes:ident) => {
14 let raw_msg_type = u8::parse($bytes)?.0;
15 let msg_type = MessageType::try_from(raw_msg_type)?;
16 if msg_type != $expected {
17 let (msg, _) = $crate::messages::Message::parse($bytes)?;
18 log::error!(concat!("Expected ", stringify!($name), " message but got {:#?}"), msg);
19 return Err(Error::UnexpectedMessageType(msg_type));
20 }
21 }
22}
23
24#[derive(Debug)]
25#[allow(dead_code)]
26pub enum Message<'a> {
27 Disconnect(Disconnect<'a>),
28 Ignore,
29 Unimplemented(Unimplemented),
30 Debug,
31 ServiceRequest(ServiceRequest<'a>),
32 ServiceAccept(ServiceAccept<'a>),
33 Kexinit(Kexinit<'a>),
34 Newkeys(Newkeys),
35 KexdhInit(KexdhInit<'a>),
36 KexdhReply(KexdhReply<'a>),
37 UserauthRequest(UserauthRequest<'a>),
38 UserauthFailure(UserauthFailure<'a>),
39 UserauthSuccess(UserauthSuccess),
40 UserauthPkOk(UserauthPkOk<'a>),
41 GlobalRequest(GlobalRequest<'a>),
42 RequestSuccess,
43 RequestFailure,
44 ChannelOpen(ChannelOpen<'a>),
45 ChannelOpenConfirmation(ChannelOpenConfirmation),
46 ChannelOpenFailure(ChannelOpenFailure<'a>),
47 ChannelWindowAdjust(ChannelWindowAdjust),
48 ChannelData(ChannelData<'a>),
49 ChannelExtendedData(ChannelExtendedData<'a>),
50 ChannelEof(ChannelEof),
51 ChannelClose(ChannelClose),
52 ChannelRequest(ChannelRequest<'a>),
53 ChannelSuccess(ChannelSuccess),
54 ChannelFailure(ChannelFailure),
55}
56
57parse_dump_struct!(Unimplemented {
58 packet_number: u32,
59});
60
61parse_dump_struct!(Kexinit<'a> {
62 cookie: [u8; 16],
63 kex_algorithms: &'a str,
64 server_host_key_algorithms: &'a str,
65 encryption_algorithms_client_to_server: &'a str,
66 encryption_algorithms_server_to_client: &'a str,
67 mac_algorithms_client_to_server: &'a str,
68 mac_algorithms_server_to_client: &'a str,
69 compression_algorithms_client_to_server: &'a str,
70 compression_algorithms_server_to_client: &'a str,
71 languages_client_to_server: &'a str,
72 languages_server_to_client: &'a str,
73 first_kex_packet_follows: bool,
74 nop: u32,
75});
76
77parse_dump_struct!(KexdhInit<'a> {
78 client_ephemeral_pubkey: &'a [u8],
79});
80
81parse_dump_struct!(KexdhReply<'a> {
82 server_public_host_key: Blob<'a>,
83 server_ephemeral_pubkey: &'a [u8],
84 exchange_hash_signature: Blob<'a>,
85});
86
87parse_dump_struct!(Newkeys {});
88
89parse_dump_struct!(ServiceRequest<'a> {
90 service_name: &'a str,
91});
92
93parse_dump_struct!(ServiceAccept<'a> {
94 service_name: &'a str,
95});
96
97parse_dump_struct!(Disconnect<'a> {
98 reason_code: DisconnectReasonCode,
99 description: &'a str,
100 language_tag: &'a str,
101});
102
103parse_dump_struct!(UserauthSuccess {});
104
105parse_dump_struct!(UserauthPkOk<'a> {
106 algorithm: &'a str,
107 blob: Blob<'a>,
108});
109
110parse_dump_struct!(UserauthFailure<'a> {
111 allowed_auth: &'a str,
112 partial_success: bool,
113});
114
115parse_dump_struct!(ChannelOpen<'a> {
116 channel_type: &'a str,
117 client_channel: u32,
118 client_initial_window_size: u32,
119 client_max_packet_size: u32,
120});
121
122parse_dump_struct!(ChannelOpenConfirmation {
123 client_channel: u32,
124 server_channel: u32,
125 server_initial_window_size: u32,
126 server_max_packet_size: u32,
127});
128
129parse_dump_struct!(ChannelOpenFailure<'a> {
130 client_channel: u32,
131 reason_code: u32,
132 description: &'a str,
133 language_tag: &'a str,
134});
135
136parse_dump_struct!(ChannelData<'a> {
137 recipient_channel: u32,
138 data: &'a [u8],
139});
140
141parse_dump_struct!(ChannelExtendedData<'a> {
142 recipient_channel: u32,
143 data_type: u32,
144 data: &'a [u8],
145});
146
147parse_dump_struct!(ChannelEof {
148 recipient_channel: u32,
149});
150
151parse_dump_struct!(ChannelClose {
152 recipient_channel: u32,
153});
154
155parse_dump_struct!(ChannelSuccess {
156 recipient_channel: u32,
157});
158
159parse_dump_struct!(ChannelFailure {
160 recipient_channel: u32,
161});
162
163parse_dump_struct!(GlobalRequest<'a> {
164 request_name: &'a str,
165 want_reply: bool,
166});
167
168parse_dump_struct!(ChannelWindowAdjust {
169 recipient_channel: u32,
170 bytes_to_add: u32,
171});
172
173parse_dump_struct!(ExchangeHash<'a> {
176 client_header: &'a [u8],
177 server_header: &'a [u8],
178 client_kexinit_payload: &'a [u8],
179 server_kexinit_payload: &'a [u8],
180 server_public_host_key: Blob<'a>,
181 client_ephemeral_pubkey: &'a [u8],
182 server_ephemeral_pubkey: &'a [u8],
183 shared_secret: UnsignedMpInt<'a>,
184});
185
186parse_dump_struct!(Blob<'a> {
187 blob_len: u32,
188 header: &'a str,
189 content: &'a [u8],
190});
191
192macro_rules! forward_and_wrap {
193 ($variant:ident, $rem:ident) => ( $variant::parse($rem).map(|(inner, p)| (Self::$variant(inner), p)) )
194}
195
196impl<'a, 'b: 'a> ParseDump<'b> for Message<'a> {
197 fn parse(bytes: &'b [u8]) -> Result<(Self, usize)> {
198 let typ = *bytes.get(0).ok_or_else(|| too_short())?;
199 match MessageType::try_from(typ)? {
200
201 MessageType::Disconnect => forward_and_wrap!(Disconnect, bytes),
202 MessageType::Unimplemented => forward_and_wrap!(Unimplemented, bytes),
203 MessageType::ServiceRequest => forward_and_wrap!(ServiceRequest, bytes),
204 MessageType::ServiceAccept => forward_and_wrap!(ServiceAccept, bytes),
205 MessageType::Kexinit => forward_and_wrap!(Kexinit, bytes),
206 MessageType::Newkeys => forward_and_wrap!(Newkeys, bytes),
207 MessageType::KexdhInit => forward_and_wrap!(KexdhInit, bytes),
208 MessageType::KexdhReply => forward_and_wrap!(KexdhReply, bytes),
209 MessageType::UserauthRequest => forward_and_wrap!(UserauthRequest, bytes),
210 MessageType::UserauthFailure => forward_and_wrap!(UserauthFailure, bytes),
211 MessageType::UserauthSuccess => forward_and_wrap!(UserauthSuccess, bytes),
212 MessageType::UserauthPkOk => forward_and_wrap!(UserauthPkOk, bytes),
213 MessageType::ChannelOpen => forward_and_wrap!(ChannelOpen, bytes),
214 MessageType::ChannelOpenConfirmation => forward_and_wrap!(ChannelOpenConfirmation, bytes),
215 MessageType::ChannelOpenFailure => forward_and_wrap!(ChannelOpenFailure, bytes),
216 MessageType::ChannelData => forward_and_wrap!(ChannelData, bytes),
217 MessageType::ChannelExtendedData => forward_and_wrap!(ChannelExtendedData, bytes),
218 MessageType::ChannelEof => forward_and_wrap!(ChannelEof, bytes),
219 MessageType::ChannelWindowAdjust => forward_and_wrap!(ChannelWindowAdjust, bytes),
220 MessageType::ChannelClose => forward_and_wrap!(ChannelClose, bytes),
221 MessageType::ChannelSuccess => forward_and_wrap!(ChannelSuccess, bytes),
222 MessageType::ChannelFailure => forward_and_wrap!(ChannelFailure, bytes),
223 MessageType::ChannelRequest => forward_and_wrap!(ChannelRequest, bytes),
224 MessageType::GlobalRequest => forward_and_wrap!(GlobalRequest, bytes),
225
226 typ => {
227 log::error!("Unimplemented: Message::parse() for {:?}", typ);
228 Err(Error::Unimplemented)
229 },
230 }
231 }
232
233 fn dump<W: Write>(&self, sink: &mut W) -> Result<()> {
234 (self.typ() as u8).dump(sink)?;
235 match self {
236 Self::Disconnect(inner) => inner.dump(sink),
237 Self::Unimplemented(inner) => inner.dump(sink),
238 Self::ServiceRequest(inner) => inner.dump(sink),
239 Self::ServiceAccept(inner) => inner.dump(sink),
240 Self::Kexinit(inner) => inner.dump(sink),
241 Self::Newkeys(inner) => inner.dump(sink),
242 Self::KexdhInit(inner) => inner.dump(sink),
243 Self::KexdhReply(inner) => inner.dump(sink),
244 Self::UserauthRequest(inner) => inner.dump(sink),
245 Self::UserauthFailure(inner) => inner.dump(sink),
246 Self::UserauthSuccess(inner) => inner.dump(sink),
247 Self::UserauthPkOk(inner) => inner.dump(sink),
248 Self::ChannelOpen(inner) => inner.dump(sink),
249 Self::ChannelOpenConfirmation(inner) => inner.dump(sink),
250 Self::ChannelOpenFailure(inner) => inner.dump(sink),
251 Self::ChannelData(inner) => inner.dump(sink),
252 Self::ChannelExtendedData(inner) => inner.dump(sink),
253 Self::ChannelEof(inner) => inner.dump(sink),
254 Self::ChannelWindowAdjust(inner) => inner.dump(sink),
255 Self::ChannelClose(inner) => inner.dump(sink),
256 Self::ChannelSuccess(inner) => inner.dump(sink),
257 Self::ChannelFailure(inner) => inner.dump(sink),
258 Self::ChannelRequest(inner) => inner.dump(sink),
259 Self::GlobalRequest(inner) => inner.dump(sink),
260
261 typ => {
262 log::error!("Unimplemented: Message::dump() for {:?}", typ);
263 Err(Error::Unimplemented)
264 },
265 }
266 }
267}
268
269impl<'a> Message<'a> {
270 pub fn typ(&self) -> MessageType {
271 match self {
272 Self::Disconnect(_) => MessageType::Disconnect,
273 Self::Ignore => MessageType::Ignore,
274 Self::Unimplemented(_) => MessageType::Unimplemented,
275 Self::Debug => MessageType::Debug,
276 Self::ServiceRequest(_) => MessageType::ServiceRequest,
277 Self::ServiceAccept(_) => MessageType::ServiceAccept,
278 Self::Kexinit(_) => MessageType::Kexinit,
279 Self::Newkeys(_) => MessageType::Newkeys,
280 Self::KexdhInit(_) => MessageType::KexdhInit,
281 Self::KexdhReply(_) => MessageType::KexdhReply,
282 Self::UserauthRequest(_) => MessageType::UserauthRequest,
283 Self::UserauthFailure(_) => MessageType::UserauthFailure,
284 Self::UserauthSuccess(_) => MessageType::UserauthSuccess,
285 Self::UserauthPkOk(_) => MessageType::UserauthPkOk,
286 Self::GlobalRequest(_) => MessageType::GlobalRequest,
287 Self::RequestSuccess => MessageType::RequestSuccess,
288 Self::RequestFailure => MessageType::RequestFailure,
289 Self::ChannelOpen(_) => MessageType::ChannelOpen,
290 Self::ChannelOpenConfirmation(_) => MessageType::ChannelOpenConfirmation,
291 Self::ChannelOpenFailure(_) => MessageType::ChannelOpenFailure,
292 Self::ChannelWindowAdjust(_) => MessageType::ChannelWindowAdjust,
293 Self::ChannelData(_) => MessageType::ChannelData,
294 Self::ChannelExtendedData(_) => MessageType::ChannelExtendedData,
295 Self::ChannelEof(_) => MessageType::ChannelEof,
296 Self::ChannelClose(_) => MessageType::ChannelClose,
297 Self::ChannelRequest(_) => MessageType::ChannelRequest,
298 Self::ChannelSuccess(_) => MessageType::ChannelSuccess,
299 Self::ChannelFailure(_) => MessageType::ChannelFailure,
300 }
301 }
302}
303
304#[derive(Copy, Clone, Debug, PartialEq, Eq)]
305#[repr(u8)]
306pub enum MessageType {
307 Disconnect = 1,
308 Ignore = 2,
309 Unimplemented = 3,
310 Debug = 4,
311 ServiceRequest = 5,
312 ServiceAccept = 6,
313 Kexinit = 20,
314 Newkeys = 21,
315 KexdhInit = 30,
316 KexdhReply = 31,
317 UserauthRequest = 50,
318 UserauthFailure = 51,
319 UserauthSuccess = 52,
320 UserauthBanner = 53,
321 UserauthPkOk = 60,
322 GlobalRequest = 80,
323 RequestSuccess = 81,
324 RequestFailure = 82,
325 ChannelOpen = 90,
326 ChannelOpenConfirmation = 91,
327 ChannelOpenFailure = 92,
328 ChannelWindowAdjust = 93,
329 ChannelData = 94,
330 ChannelExtendedData = 95,
331 ChannelEof = 96,
332 ChannelClose = 97,
333 ChannelRequest = 98,
334 ChannelSuccess = 99,
335 ChannelFailure = 100,
336}
337
338impl MessageType {
339 const fn from_struct_name(name: &str) -> Option<Self> {
340 match name.as_bytes() {
341 b"Disconnect" => Some(Self::Disconnect),
342 b"Ignore" => Some(Self::Ignore),
343 b"Unimplemented" => Some(Self::Unimplemented),
344 b"Debug" => Some(Self::Debug),
345 b"ServiceRequest" => Some(Self::ServiceRequest),
346 b"ServiceAccept" => Some(Self::ServiceAccept),
347 b"Kexinit" => Some(Self::Kexinit),
348 b"Newkeys" => Some(Self::Newkeys),
349 b"KexdhInit" => Some(Self::KexdhInit),
350 b"KexdhReply" => Some(Self::KexdhReply),
351 b"UserauthRequest" => Some(Self::UserauthRequest),
352 b"UserauthFailure" => Some(Self::UserauthFailure),
353 b"UserauthSuccess" => Some(Self::UserauthSuccess),
354 b"UserauthBanner" => Some(Self::UserauthBanner),
355 b"UserauthPkOk" => Some(Self::UserauthPkOk),
356 b"GlobalRequest" => Some(Self::GlobalRequest),
357 b"RequestSuccess" => Some(Self::RequestSuccess),
358 b"RequestFailure" => Some(Self::RequestFailure),
359 b"ChannelOpen" => Some(Self::ChannelOpen),
360 b"ChannelOpenConfirmation" => Some(Self::ChannelOpenConfirmation),
361 b"ChannelOpenFailure" => Some(Self::ChannelOpenFailure),
362 b"ChannelWindowAdjust" => Some(Self::ChannelWindowAdjust),
363 b"ChannelData" => Some(Self::ChannelData),
364 b"ChannelExtendedData" => Some(Self::ChannelExtendedData),
365 b"ChannelEof" => Some(Self::ChannelEof),
366 b"ChannelClose" => Some(Self::ChannelClose),
367
368 b"ChannelRequest" => Some(Self::ChannelRequest),
370
371 b"ChannelSuccess" => Some(Self::ChannelSuccess),
372 b"ChannelFailure" => Some(Self::ChannelFailure),
373 _ => None,
374 }
375 }
376}
377
378impl TryFrom<u8> for MessageType {
379 type Error = Error;
380 fn try_from(value: u8) -> Result<Self> {
381 match value {
382 1 => Ok(Self::Disconnect),
383 2 => Ok(Self::Ignore),
384 3 => Ok(Self::Unimplemented),
385 4 => Ok(Self::Debug),
386 5 => Ok(Self::ServiceRequest),
387 6 => Ok(Self::ServiceAccept),
388 20 => Ok(Self::Kexinit),
389 21 => Ok(Self::Newkeys),
390 30 => Ok(Self::KexdhInit),
391 31 => Ok(Self::KexdhReply),
392 50 => Ok(Self::UserauthRequest),
393 51 => Ok(Self::UserauthFailure),
394 52 => Ok(Self::UserauthSuccess),
395 53 => Ok(Self::UserauthBanner),
396 60 => Ok(Self::UserauthPkOk),
397 80 => Ok(Self::GlobalRequest),
398 81 => Ok(Self::RequestSuccess),
399 82 => Ok(Self::RequestFailure),
400 90 => Ok(Self::ChannelOpen),
401 91 => Ok(Self::ChannelOpenConfirmation),
402 92 => Ok(Self::ChannelOpenFailure),
403 93 => Ok(Self::ChannelWindowAdjust),
404 94 => Ok(Self::ChannelData),
405 95 => Ok(Self::ChannelExtendedData),
406 96 => Ok(Self::ChannelEof),
407 97 => Ok(Self::ChannelClose),
408 98 => Ok(Self::ChannelRequest),
409 99 => Ok(Self::ChannelSuccess),
410 100 => Ok(Self::ChannelFailure),
411 value => Err(Error::UnknownMessageType(value)),
412 }
413 }
414}
415
416#[derive(Copy, Clone, Debug)]
417pub struct UnsignedMpInt<'a>(pub &'a [u8]);
418
419impl<'a, 'b: 'a> ParseDump<'b> for UnsignedMpInt<'a> {
420 fn parse(bytes: &'b [u8]) -> Result<(Self, usize)> {
421 let total = U32 + (try_u32(bytes)? as usize);
422 Ok((Self(bytes.get(U32..total).ok_or_else(|| too_short())?), total))
423 }
424
425 fn dump<W: Write>(&self, sink: &mut W) -> Result<()> {
426 let has_non_zero = self.0.iter().position(|b| *b != 0);
427 if has_non_zero.is_some() {
428 let prevent_sign = (self.0[0] & 0x80) != 0;
429 let len = self.0.len() + (prevent_sign as usize);
430
431 sink.write(&(len as u32).to_be_bytes())?;
432 if prevent_sign {
433 sink.write(&[0])?;
434 }
435
436 sink.write(self.0)?;
437 Ok(())
438 } else {
439 0u32.dump(sink)
440 }
441 }
442}
443
444#[derive(Copy, Clone, Debug)]
445#[repr(u8)]
446pub enum DisconnectReasonCode {
447 HostNotAllowedToConnect = 1,
448 ProtocolError = 2,
449 KeyExchangeFailed = 3,
450 Reserved = 4,
451 MacError = 5,
452 CompressionError = 6,
453 ServiceNotAvailable = 7,
454 ProtocolVersionNotSupported = 8,
455 HostKeyNotVerifiable = 9,
456 ConnectionLost = 10,
457 ByApplication = 11,
458 TooManyConnections = 12,
459 AuthCancelledByUser = 13,
460 NoMoreAuthMethodsAvailable = 14,
461 IllegalUserName = 15,
462}
463
464impl<'b> ParseDump<'b> for DisconnectReasonCode {
465 fn parse(bytes: &'b [u8]) -> Result<(Self, usize)> {
466 let (byte, progress) = u8::parse(bytes)?;
467 let reason = match byte {
468 1 => Ok(Self::HostNotAllowedToConnect),
469 2 => Ok(Self::ProtocolError),
470 3 => Ok(Self::KeyExchangeFailed),
471 4 => Ok(Self::Reserved),
472 5 => Ok(Self::MacError),
473 6 => Ok(Self::CompressionError),
474 7 => Ok(Self::ServiceNotAvailable),
475 8 => Ok(Self::ProtocolVersionNotSupported),
476 9 => Ok(Self::HostKeyNotVerifiable),
477 10 => Ok(Self::ConnectionLost),
478 11 => Ok(Self::ByApplication),
479 12 => Ok(Self::TooManyConnections),
480 13 => Ok(Self::AuthCancelledByUser),
481 14 => Ok(Self::NoMoreAuthMethodsAvailable),
482 15 => Ok(Self::IllegalUserName),
483 c => {
484 log::error!("Invalid disconnect reason code: {}", c);
485 Err(Error::InvalidData)
486 },
487 }?;
488 Ok((reason, progress))
489 }
490
491 fn dump<W: Write>(&self, sink: &mut W) -> Result<()> {
492 (*self as u8).dump(sink)
493 }
494}
495
496impl<'a> Kexinit<'a> {
497 pub fn check_compat(&self, client: &Self) -> Result<()> {
498 fn find(haystack: &str, needle: &str) -> Result<()> {
499 match haystack.split(",").position(|alg| alg == needle) {
500 None => {
501 log::error!("Couldn't agree with peer on an algorithm set");
502 Err(Error::Unimplemented)
503 },
504 Some(_) => Ok(()),
505 }
506 }
507
508 find(self.kex_algorithms, client.kex_algorithms)?;
509 find(self.server_host_key_algorithms, client.server_host_key_algorithms)?;
510 find(self.encryption_algorithms_client_to_server, client.encryption_algorithms_client_to_server)?;
511 find(self.encryption_algorithms_server_to_client, client.encryption_algorithms_server_to_client)?;
512 find(self.mac_algorithms_client_to_server, client.mac_algorithms_client_to_server)?;
513 find(self.mac_algorithms_server_to_client, client.mac_algorithms_server_to_client)?;
514 find(self.compression_algorithms_client_to_server, client.compression_algorithms_client_to_server)?;
515 find(self.compression_algorithms_server_to_client, client.compression_algorithms_server_to_client)
516 }
517}