wire.rs
1 use super::codec::{ObjectReader, ObjectWriter}; 2 use super::error::ProtocolError; 3 4 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 5 pub enum Message<'a> { 6 ServiceRequest { 7 service_name: &'a str, 8 }, 9 ServiceAccept { 10 service_name: &'a str, 11 }, 12 Disconnect { 13 reason: DisconnectReason, 14 }, 15 Ignore { 16 data: &'a [u8], 17 }, 18 Debug { 19 always_display: bool, 20 message: &'a str, 21 language_tag: &'a str, 22 }, 23 Unimplemented { 24 sequence_number: u32, 25 }, 26 KexInit { 27 cookie: &'a [u8; 16], 28 kex_algorithms: NameList<'a>, 29 server_host_key_algorithms: NameList<'a>, 30 encryption_algorithms_client_to_server: NameList<'a>, 31 encryption_algorithms_server_to_client: NameList<'a>, 32 mac_algorithms_client_to_server: NameList<'a>, 33 mac_algorithms_server_to_client: NameList<'a>, 34 compression_algorithms_client_to_server: NameList<'a>, 35 compression_algorithms_server_to_client: NameList<'a>, 36 languages_client_to_server: NameList<'a>, 37 languages_server_to_client: NameList<'a>, 38 first_kex_packet_follows: bool, 39 reserved: u32, 40 }, 41 NewKeys, 42 KexEcdhInit { 43 client_ephemeral_public_key: &'a [u8], 44 }, 45 KexEcdhReply { 46 server_public_host_key: PublicKey<'a>, 47 server_ephemeral_public_key: &'a [u8], 48 signature: Signature<'a>, 49 }, 50 UserAuthRequest { 51 user_name: &'a str, 52 service_name: &'a str, 53 auth_method: AuthMethod<'a>, 54 }, 55 UserAuthFailure { 56 authentications_that_can_continue: NameList<'a>, 57 partial_success: bool, 58 }, 59 UserAuthSuccess, 60 UserAuthBanner { 61 message: &'a str, 62 language: &'a str, 63 }, 64 UserAuthPkOk { 65 public_key_algorithm_name: &'a str, 66 public_key: PublicKey<'a>, 67 }, 68 GlobalRequest { 69 request_name: &'a str, 70 want_reply: bool, 71 payload: &'a [u8], 72 }, 73 RequestSuccess { 74 payload: &'a [u8], 75 }, 76 RequestFailure, 77 ChannelOpen { 78 channel: ChannelType<'a>, 79 }, 80 ChannelOpenConfirmation { 81 recipient_channel: u32, 82 sender_channel: u32, 83 initial_window_size: u32, 84 maximum_packet_size: u32, 85 payload: &'a [u8], 86 }, 87 ChannelOpenFailure { 88 recipient_channel: u32, 89 reason: ChannelOpenFailureReason, 90 }, 91 ChannelWindowAdjust { 92 recipient_channel: u32, 93 bytes_to_add: u32, 94 }, 95 ChannelData { 96 recipient_channel: u32, 97 data: Data<'a>, 98 }, 99 ChannelExtendedData { 100 recipient_channel: u32, 101 data: ExtendedData<'a>, 102 }, 103 ChannelEof { 104 recipient_channel: u32, 105 }, 106 ChannelClose { 107 recipient_channel: u32, 108 }, 109 ChannelRequest { 110 recipient_channel: u32, 111 request: Request<'a>, 112 }, 113 ChannelSuccess { 114 recipient_channel: u32, 115 }, 116 ChannelFailure { 117 recipient_channel: u32, 118 }, 119 Unknown { 120 message: u8, 121 payload: &'a [u8], 122 }, 123 } 124 125 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 126 pub enum ChannelType<'a> { 127 Session { 128 sender_channel: u32, 129 initial_window_size: u32, 130 maximum_packet_size: u32, 131 }, 132 Other { 133 channel_type: &'a str, 134 sender_channel: u32, 135 initial_window_size: u32, 136 maximum_packet_size: u32, 137 payload: &'a [u8], 138 }, 139 } 140 141 impl<'a> ChannelType<'a> { 142 pub fn decode_with(reader: &mut ObjectReader<'a>) -> Result<Self, ProtocolError> { 143 let decoded = match reader.read_string_utf8()? { 144 "session" => Self::Session { 145 sender_channel: reader.read_uint32()?, 146 initial_window_size: reader.read_uint32()?, 147 maximum_packet_size: reader.read_uint32()?, 148 }, 149 channel_type => Self::Other { 150 channel_type, 151 sender_channel: reader.read_uint32()?, 152 initial_window_size: reader.read_uint32()?, 153 maximum_packet_size: reader.read_uint32()?, 154 payload: reader.read_remaining(), 155 }, 156 }; 157 158 Ok(decoded) 159 } 160 161 pub fn encode_with(self, writer: &mut ObjectWriter) -> Result<(), ProtocolError> { 162 match self { 163 Self::Session { 164 sender_channel, 165 initial_window_size, 166 maximum_packet_size, 167 } => { 168 writer.write_string_utf8("session")?; 169 writer.write_uint32(sender_channel)?; 170 writer.write_uint32(initial_window_size)?; 171 writer.write_uint32(maximum_packet_size)?; 172 } 173 Self::Other { 174 channel_type, 175 sender_channel, 176 initial_window_size, 177 maximum_packet_size, 178 payload, 179 } => { 180 writer.write_string_utf8(channel_type)?; 181 writer.write_uint32(sender_channel)?; 182 writer.write_uint32(initial_window_size)?; 183 writer.write_uint32(maximum_packet_size)?; 184 writer.write_byte_array(payload)?; 185 } 186 } 187 188 Ok(()) 189 } 190 } 191 192 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 193 pub enum Request<'a> { 194 Env { 195 want_reply: bool, 196 variable_name: &'a str, 197 variable_value: &'a str, 198 }, 199 Shell { 200 want_reply: bool, 201 }, 202 Exec { 203 want_reply: bool, 204 command: &'a str, 205 }, 206 ExitStatus { 207 want_reply: bool, 208 exit_status: u32, 209 }, 210 PtyReq { 211 want_reply: bool, 212 term: &'a str, 213 width_chars: u32, 214 height_rows: u32, 215 width_pixels: u32, 216 height_pixels: u32, 217 }, 218 Other { 219 request_type: &'a str, 220 want_reply: bool, 221 payload: &'a [u8], 222 }, 223 } 224 225 impl<'a> Request<'a> { 226 pub fn decode_with(reader: &mut ObjectReader<'a>) -> Result<Self, ProtocolError> { 227 let decoded = match reader.read_string_utf8()? { 228 "env" => Self::Env { 229 want_reply: reader.read_boolean()?, 230 variable_name: reader.read_string_utf8()?, 231 variable_value: reader.read_string_utf8()?, 232 }, 233 "shell" => Self::Shell { 234 want_reply: reader.read_boolean()?, 235 }, 236 "exec" => Self::Exec { 237 want_reply: reader.read_boolean()?, 238 command: reader.read_string_utf8()?, 239 }, 240 "exit-status" => Self::ExitStatus { 241 want_reply: reader.read_boolean()?, 242 exit_status: reader.read_uint32()?, 243 }, 244 "pty-req" => { 245 let want_reply = reader.read_boolean()?; 246 let term = reader.read_string_utf8()?; 247 let width_chars = reader.read_uint32()?; 248 let height_rows = reader.read_uint32()?; 249 let width_pixels = reader.read_uint32()?; 250 let height_pixels = reader.read_uint32()?; 251 // Consume remaining bytes (encoded terminal modes) 252 let _ = reader.read_remaining(); 253 Self::PtyReq { want_reply, term, width_chars, height_rows, width_pixels, height_pixels } 254 } 255 request_type => Self::Other { 256 request_type, 257 want_reply: reader.read_boolean()?, 258 payload: reader.read_remaining(), 259 }, 260 }; 261 262 Ok(decoded) 263 } 264 265 pub fn encode_with(self, writer: &mut ObjectWriter) -> Result<(), ProtocolError> { 266 match self { 267 Self::Env { 268 want_reply, 269 variable_name, 270 variable_value, 271 } => { 272 writer.write_string_utf8("env")?; 273 writer.write_boolean(want_reply)?; 274 writer.write_string_utf8(variable_name)?; 275 writer.write_string_utf8(variable_value)?; 276 } 277 Self::Shell { want_reply } => { 278 writer.write_string_utf8("shell")?; 279 writer.write_boolean(want_reply)?; 280 } 281 Self::Exec { 282 want_reply, 283 command, 284 } => { 285 writer.write_string_utf8("exec")?; 286 writer.write_boolean(want_reply)?; 287 writer.write_string_utf8(command)?; 288 } 289 Self::ExitStatus { 290 want_reply, 291 exit_status, 292 } => { 293 writer.write_string_utf8("exit-status")?; 294 writer.write_boolean(want_reply)?; 295 writer.write_uint32(exit_status)?; 296 } 297 Self::PtyReq { 298 want_reply, 299 term, 300 width_chars, 301 height_rows, 302 width_pixels, 303 height_pixels, 304 } => { 305 writer.write_string_utf8("pty-req")?; 306 writer.write_boolean(want_reply)?; 307 writer.write_string_utf8(term)?; 308 writer.write_uint32(width_chars)?; 309 writer.write_uint32(height_rows)?; 310 writer.write_uint32(width_pixels)?; 311 writer.write_uint32(height_pixels)?; 312 } 313 Self::Other { 314 request_type, 315 want_reply, 316 payload, 317 } => { 318 writer.write_string_utf8(request_type)?; 319 writer.write_boolean(want_reply)?; 320 writer.write_byte_array(payload)?; 321 } 322 } 323 324 Ok(()) 325 } 326 327 pub fn want_reply(self) -> bool { 328 match self { 329 Self::Env { want_reply, .. } => want_reply, 330 Self::Shell { want_reply } => want_reply, 331 Self::Exec { want_reply, .. } => want_reply, 332 Self::ExitStatus { want_reply, .. } => want_reply, 333 Self::PtyReq { want_reply, .. } => want_reply, 334 Self::Other { want_reply, .. } => want_reply, 335 } 336 } 337 } 338 339 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 340 pub enum Data<'a> { 341 Borrowed { bytes: &'a [u8] }, 342 InPlace { len: u32 }, 343 } 344 345 impl<'a> Data<'a> { 346 pub fn decode_with(reader: &mut ObjectReader<'a>) -> Result<Self, ProtocolError> { 347 let decoded = Self::Borrowed { 348 bytes: reader.read_string()?, 349 }; 350 351 Ok(decoded) 352 } 353 354 pub fn encode_with(self, writer: &mut ObjectWriter) -> Result<(), ProtocolError> { 355 match self { 356 Self::Borrowed { bytes } => { 357 writer.write_string(bytes)?; 358 } 359 Self::InPlace { len } => { 360 writer.write_string_len(len)?; 361 writer.skip(from_u32(len))?; 362 } 363 } 364 365 Ok(()) 366 } 367 } 368 369 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 370 pub enum ExtendedData<'a> { 371 Stderr { data: Data<'a> }, 372 Other { data_type_code: u32, data: Data<'a> }, 373 } 374 375 impl<'a> ExtendedData<'a> { 376 pub fn decode_with(reader: &mut ObjectReader<'a>) -> Result<Self, ProtocolError> { 377 let decoded = match reader.read_uint32()? { 378 1 => Self::Stderr { 379 data: Data::decode_with(reader)?, 380 }, 381 data_type_code => Self::Other { 382 data_type_code, 383 data: Data::decode_with(reader)?, 384 }, 385 }; 386 387 Ok(decoded) 388 } 389 390 pub fn encode_with(self, writer: &mut ObjectWriter) -> Result<(), ProtocolError> { 391 match self { 392 Self::Stderr { data } => { 393 writer.write_uint32(1)?; 394 data.encode_with(writer)?; 395 } 396 Self::Other { 397 data_type_code, 398 data, 399 } => { 400 writer.write_uint32(data_type_code)?; 401 data.encode_with(writer)?; 402 } 403 } 404 405 Ok(()) 406 } 407 } 408 409 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 410 pub enum AuthMethod<'a> { 411 PublicKey { 412 public_key_algorithm_name: &'a str, 413 public_key: PublicKey<'a>, 414 signature: Option<Signature<'a>>, 415 }, 416 Unsupported { 417 method_name: &'a str, 418 payload: &'a [u8], 419 }, 420 None, 421 } 422 423 impl<'a> AuthMethod<'a> { 424 pub fn decode_with(reader: &mut ObjectReader<'a>) -> Result<Self, ProtocolError> { 425 let decoded = match reader.read_string_utf8()? { 426 "publickey" => { 427 let has_signature = reader.read_boolean()?; 428 429 let public_key_algorithm_name = reader.read_string_utf8()?; 430 let public_key = PublicKey::decode_with(reader)?; 431 432 let signature = if has_signature { 433 Some(Signature::decode_with(reader)?) 434 } else { 435 None 436 }; 437 438 AuthMethod::PublicKey { 439 public_key_algorithm_name, 440 public_key, 441 signature, 442 } 443 } 444 "none" => AuthMethod::None, 445 method_name => AuthMethod::Unsupported { 446 method_name, 447 payload: reader.read_remaining(), 448 }, 449 }; 450 451 Ok(decoded) 452 } 453 454 pub fn encode_with(self, writer: &mut ObjectWriter) -> Result<(), ProtocolError> { 455 match self { 456 AuthMethod::PublicKey { 457 public_key_algorithm_name, 458 public_key, 459 signature, 460 } => { 461 writer.write_string_utf8("publickey")?; 462 writer.write_boolean(signature.is_some())?; 463 writer.write_string_utf8(public_key_algorithm_name)?; 464 public_key.encode_with(writer)?; 465 466 if let Some(signature) = signature { 467 signature.encode_with(writer)?; 468 } 469 } 470 AuthMethod::Unsupported { 471 method_name, 472 payload, 473 } => { 474 writer.write_string_utf8(method_name)?; 475 writer.write_string(payload)?; 476 } 477 AuthMethod::None => { 478 writer.write_string_utf8("none")?; 479 } 480 } 481 482 Ok(()) 483 } 484 } 485 486 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 487 pub enum PublicKey<'a> { 488 Ed25519 { 489 public_key: &'a [u8; 32], 490 }, 491 Other { 492 identifier: &'a str, 493 payload: &'a [u8], 494 }, 495 } 496 497 impl<'a> PublicKey<'a> { 498 pub fn decode_with(reader: &mut ObjectReader<'a>) -> Result<Self, ProtocolError> { 499 let mut reader = ObjectReader::new(reader.read_string()?); 500 501 let decoded = match reader.read_string_utf8()? { 502 "ssh-ed25519" => Self::Ed25519 { 503 public_key: reader.read_string_fixed::<32>()?, 504 }, 505 identifier => Self::Other { 506 identifier, 507 payload: reader.read_remaining(), 508 }, 509 }; 510 511 if reader.read_remaining().is_empty() { 512 Ok(decoded) 513 } else { 514 Err(ProtocolError::TrailingPayload) 515 } 516 } 517 518 pub fn encode_with(self, writer: &mut ObjectWriter) -> Result<(), ProtocolError> { 519 writer.write_nested(|writer| { 520 match self { 521 Self::Ed25519 { public_key } => { 522 writer.write_string_utf8("ssh-ed25519")?; 523 writer.write_string(public_key)?; 524 } 525 Self::Other { 526 identifier, 527 payload, 528 } => { 529 writer.write_string_utf8(identifier)?; 530 writer.write_string(payload)?; 531 } 532 } 533 534 Ok(()) 535 }) 536 } 537 } 538 539 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 540 pub enum Signature<'a> { 541 Ed25519 { 542 signature: &'a [u8; 64], 543 }, 544 Other { 545 identifier: &'a str, 546 payload: &'a [u8], 547 }, 548 } 549 550 impl<'a> Signature<'a> { 551 pub fn decode_with(reader: &mut ObjectReader<'a>) -> Result<Self, ProtocolError> { 552 let mut reader = ObjectReader::new(reader.read_string()?); 553 554 let decoded = match reader.read_string_utf8()? { 555 "ssh-ed25519" => Self::Ed25519 { 556 signature: reader.read_string_fixed::<64>()?, 557 }, 558 identifier => Self::Other { 559 identifier, 560 payload: reader.read_remaining(), 561 }, 562 }; 563 564 if reader.read_remaining().is_empty() { 565 Ok(decoded) 566 } else { 567 Err(ProtocolError::TrailingPayload) 568 } 569 } 570 571 pub fn encode_with(self, writer: &mut ObjectWriter) -> Result<(), ProtocolError> { 572 writer.write_nested(|writer| { 573 match self { 574 Self::Ed25519 { signature } => { 575 writer.write_string_utf8("ssh-ed25519")?; 576 writer.write_string(signature)?; 577 } 578 Self::Other { 579 identifier, 580 payload, 581 } => { 582 writer.write_string_utf8(identifier)?; 583 writer.write_string(payload)?; 584 } 585 } 586 587 Ok(()) 588 }) 589 } 590 } 591 592 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] 593 pub struct NameList<'a> { 594 string: &'a str, 595 } 596 597 impl<'a> NameList<'a> { 598 pub fn new_from_string(string: &'a str) -> Result<Self, ProtocolError> { 599 if !string.is_ascii() { 600 return Err(ProtocolError::BadStringEncoding); 601 } 602 603 if string 604 .as_bytes() 605 .windows(2) 606 .any(|window| window == [b','; 2]) 607 { 608 Err(ProtocolError::BadNameList) 609 } else { 610 Ok(Self { string }) 611 } 612 } 613 614 pub fn is_empty(&self) -> bool { 615 self.string.is_empty() 616 } 617 618 pub fn iter(&self) -> impl Iterator<Item = &str> { 619 self.string.split(',') 620 } 621 622 pub fn as_str(&self) -> &'a str { 623 self.string 624 } 625 626 pub fn find(&self, name: &str) -> Option<usize> { 627 self.iter().position(|item| item == name) 628 } 629 630 pub fn decode_with(reader: &mut ObjectReader<'a>) -> Result<Self, ProtocolError> { 631 Self::new_from_string(reader.read_string_utf8()?) 632 } 633 } 634 635 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 636 pub enum ChannelOpenFailureReason { 637 AdministrativelyProhibited, 638 ConnectFailed, 639 UnknownChannelType, 640 ResourceShortage, 641 Other(u32), 642 } 643 644 impl ChannelOpenFailureReason { 645 pub fn decode_with(reader: &mut ObjectReader) -> Result<Self, ProtocolError> { 646 let reason_code = reader.read_uint32()?; 647 let _description = reader.read_string_utf8()?; 648 let _language_tag = reader.read_string_utf8()?; 649 650 Ok(Self::from_reason_code(reason_code)) 651 } 652 653 pub fn encode_with(self, writer: &mut ObjectWriter) -> Result<(), ProtocolError> { 654 writer.write_uint32(self.into_reason_code())?; 655 writer.write_string_utf8(self.description())?; 656 writer.write_string_utf8("en-US")?; 657 658 Ok(()) 659 } 660 661 pub fn into_reason_code(self) -> u32 { 662 match self { 663 Self::AdministrativelyProhibited => 1, 664 Self::ConnectFailed => 2, 665 Self::UnknownChannelType => 3, 666 Self::ResourceShortage => 4, 667 Self::Other(reason_code) => reason_code, 668 } 669 } 670 671 pub fn from_reason_code(reason_code: u32) -> Self { 672 match reason_code { 673 1 => Self::AdministrativelyProhibited, 674 2 => Self::ConnectFailed, 675 3 => Self::UnknownChannelType, 676 4 => Self::ResourceShortage, 677 _ => Self::Other(reason_code), 678 } 679 } 680 681 pub fn description(self) -> &'static str { 682 match self { 683 Self::AdministrativelyProhibited => "Administratively prohibited", 684 Self::ConnectFailed => "Connect failed", 685 Self::UnknownChannelType => "Unknown channel type", 686 Self::ResourceShortage => "Resource shortage", 687 Self::Other(_) => "No description available", 688 } 689 } 690 } 691 692 /// Set of possible disconnection reasons. 693 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 694 pub enum DisconnectReason { 695 /// Standard RFC4253 disconnect reason. 696 HostNotAllowedToConnect, 697 /// Standard RFC4253 disconnect reason. 698 ProtocolError, 699 /// Standard RFC4253 disconnect reason. 700 KeyExchangeFailed, 701 /// Standard RFC4253 disconnect reason. 702 Reserved, 703 /// Standard RFC4253 disconnect reason. 704 MacError, 705 /// Standard RFC4253 disconnect reason. 706 CompressionError, 707 /// Standard RFC4253 disconnect reason. 708 ServiceNotAvailable, 709 /// Standard RFC4253 disconnect reason. 710 ProtocolVersionNotSupported, 711 /// Standard RFC4253 disconnect reason. 712 HostKeyNotVerifiable, 713 /// Standard RFC4253 disconnect reason. 714 ConnectionLost, 715 /// Standard RFC4253 disconnect reason. 716 ByApplication, 717 /// Standard RFC4253 disconnect reason. 718 TooManyConnections, 719 /// Standard RFC4253 disconnect reason. 720 AuthCancelledByUser, 721 /// Standard RFC4253 disconnect reason. 722 NoMoreAuthMethodsAvailable, 723 /// Standard RFC4253 disconnect reason. 724 IllegalUserName, 725 /// Some other disconnect reason. 726 Other(u32), 727 } 728 729 impl DisconnectReason { 730 /// Decodes an instance of this type from an object reader. 731 pub fn decode_with(reader: &mut ObjectReader) -> Result<Self, ProtocolError> { 732 let reason_code = reader.read_uint32()?; 733 let _description = reader.read_string_utf8()?; 734 let _language_tag = reader.read_string_utf8()?; 735 736 Ok(Self::from_reason_code(reason_code)) 737 } 738 739 /// Encodes this instance into an object writer. 740 pub fn encode_with(self, writer: &mut ObjectWriter) -> Result<(), ProtocolError> { 741 writer.write_uint32(self.into_reason_code())?; 742 writer.write_string_utf8(self.description())?; 743 writer.write_string_utf8("en-US")?; 744 745 Ok(()) 746 } 747 748 /// Retrieves the underlying reason code. 749 pub fn into_reason_code(self) -> u32 { 750 match self { 751 Self::HostNotAllowedToConnect => 1, 752 Self::ProtocolError => 2, 753 Self::KeyExchangeFailed => 3, 754 Self::Reserved => 4, 755 Self::MacError => 5, 756 Self::CompressionError => 6, 757 Self::ServiceNotAvailable => 7, 758 Self::ProtocolVersionNotSupported => 8, 759 Self::HostKeyNotVerifiable => 9, 760 Self::ConnectionLost => 10, 761 Self::ByApplication => 11, 762 Self::TooManyConnections => 12, 763 Self::AuthCancelledByUser => 13, 764 Self::NoMoreAuthMethodsAvailable => 14, 765 Self::IllegalUserName => 15, 766 Self::Other(reason_code) => reason_code, 767 } 768 } 769 770 /// Constructs an instance of this type from a reason code. 771 pub fn from_reason_code(reason_code: u32) -> Self { 772 match reason_code { 773 1 => Self::HostNotAllowedToConnect, 774 2 => Self::ProtocolError, 775 3 => Self::KeyExchangeFailed, 776 4 => Self::Reserved, 777 5 => Self::MacError, 778 6 => Self::CompressionError, 779 7 => Self::ServiceNotAvailable, 780 8 => Self::ProtocolVersionNotSupported, 781 9 => Self::HostKeyNotVerifiable, 782 10 => Self::ConnectionLost, 783 11 => Self::ByApplication, 784 12 => Self::TooManyConnections, 785 13 => Self::AuthCancelledByUser, 786 14 => Self::NoMoreAuthMethodsAvailable, 787 15 => Self::IllegalUserName, 788 _ => Self::Other(reason_code), 789 } 790 } 791 792 /// Retrieves a description message for this disconnect reason instance. 793 pub fn description(self) -> &'static str { 794 match self { 795 Self::HostNotAllowedToConnect => "Host not allowed to connect", 796 Self::ProtocolError => "Protocol error", 797 Self::KeyExchangeFailed => "Key exchange failed", 798 Self::Reserved => "Reserved", 799 Self::MacError => "MAC error", 800 Self::CompressionError => "Compression error", 801 Self::ServiceNotAvailable => "Service not available", 802 Self::ProtocolVersionNotSupported => "Protocol version not supported", 803 Self::HostKeyNotVerifiable => "Host key not verifiable", 804 Self::ConnectionLost => "Connection lost", 805 Self::ByApplication => "By application", 806 Self::TooManyConnections => "Too many connections", 807 Self::AuthCancelledByUser => "Auth cancelled by user", 808 Self::NoMoreAuthMethodsAvailable => "No more auth methods available", 809 Self::IllegalUserName => "Illegal user name", 810 Self::Other(_) => "No description available", 811 } 812 } 813 } 814 815 pub const MSG_SERVICE_REQUEST: u8 = 5; 816 pub const MSG_SERVICE_ACCEPT: u8 = 6; 817 pub const MSG_DISCONNECT: u8 = 1; 818 pub const MSG_IGNORE: u8 = 2; 819 pub const MSG_DEBUG: u8 = 4; 820 pub const MSG_UNIMPLEMENTED: u8 = 3; 821 pub const MSG_KEX_INIT: u8 = 20; 822 pub const MSG_NEW_KEYS: u8 = 21; 823 pub const MSG_KEX_ECDH_INIT: u8 = 30; 824 pub const MSG_KEX_ECDH_REPLY: u8 = 31; 825 pub const MSG_USERAUTH_REQUEST: u8 = 50; 826 pub const MSG_USERAUTH_FAILURE: u8 = 51; 827 pub const MSG_USERAUTH_SUCCESS: u8 = 52; 828 pub const MSG_USERAUTH_BANNER: u8 = 53; 829 pub const MSG_USERAUTH_PK_OK: u8 = 60; 830 pub const MSG_GLOBAL_REQUEST: u8 = 80; 831 pub const MSG_REQUEST_SUCCESS: u8 = 81; 832 pub const MSG_REQUEST_FAILURE: u8 = 82; 833 pub const MSG_CHANNEL_OPEN: u8 = 90; 834 pub const MSG_CHANNEL_OPEN_CONFIRMATION: u8 = 91; 835 pub const MSG_CHANNEL_OPEN_FAILURE: u8 = 92; 836 pub const MSG_CHANNEL_WINDOW_ADJUST: u8 = 93; 837 pub const MSG_CHANNEL_DATA: u8 = 94; 838 pub const MSG_CHANNEL_EXTENDED_DATA: u8 = 95; 839 pub const MSG_CHANNEL_EOF: u8 = 96; 840 pub const MSG_CHANNEL_CLOSE: u8 = 97; 841 pub const MSG_CHANNEL_REQUEST: u8 = 98; 842 pub const MSG_CHANNEL_SUCCESS: u8 = 99; 843 pub const MSG_CHANNEL_FAILURE: u8 = 100; 844 845 impl<'a> Message<'a> { 846 pub fn decode(buffer: &'a [u8]) -> Result<Self, ProtocolError> { 847 let mut reader = ObjectReader::new(buffer); 848 849 let decoded = match reader.read_byte()? { 850 MSG_SERVICE_REQUEST => Self::ServiceRequest { 851 service_name: reader.read_internal_name()?, 852 }, 853 MSG_SERVICE_ACCEPT => Self::ServiceAccept { 854 service_name: reader.read_internal_name()?, 855 }, 856 MSG_DISCONNECT => Self::Disconnect { 857 reason: DisconnectReason::decode_with(&mut reader)?, 858 }, 859 MSG_IGNORE => Self::Ignore { 860 data: reader.read_string()?, 861 }, 862 MSG_DEBUG => Self::Debug { 863 always_display: reader.read_boolean()?, 864 message: reader.read_string_utf8()?, 865 language_tag: reader.read_string_utf8()?, 866 }, 867 MSG_UNIMPLEMENTED => Self::Unimplemented { 868 sequence_number: reader.read_uint32()?, 869 }, 870 MSG_NEW_KEYS => Self::NewKeys, 871 MSG_KEX_INIT => Self::KexInit { 872 cookie: reader.read_byte_array::<16>()?, 873 kex_algorithms: NameList::decode_with(&mut reader)?, 874 server_host_key_algorithms: NameList::decode_with(&mut reader)?, 875 encryption_algorithms_client_to_server: NameList::decode_with(&mut reader)?, 876 encryption_algorithms_server_to_client: NameList::decode_with(&mut reader)?, 877 mac_algorithms_client_to_server: NameList::decode_with(&mut reader)?, 878 mac_algorithms_server_to_client: NameList::decode_with(&mut reader)?, 879 compression_algorithms_client_to_server: NameList::decode_with(&mut reader)?, 880 compression_algorithms_server_to_client: NameList::decode_with(&mut reader)?, 881 languages_client_to_server: NameList::decode_with(&mut reader)?, 882 languages_server_to_client: NameList::decode_with(&mut reader)?, 883 first_kex_packet_follows: reader.read_boolean()?, 884 reserved: reader.read_uint32()?, 885 }, 886 MSG_KEX_ECDH_INIT => Self::KexEcdhInit { 887 client_ephemeral_public_key: reader.read_string()?, 888 }, 889 MSG_KEX_ECDH_REPLY => Self::KexEcdhReply { 890 server_public_host_key: PublicKey::decode_with(&mut reader)?, 891 server_ephemeral_public_key: reader.read_string()?, 892 signature: Signature::decode_with(&mut reader)?, 893 }, 894 MSG_USERAUTH_REQUEST => Self::UserAuthRequest { 895 user_name: reader.read_string_utf8()?, 896 service_name: reader.read_string_utf8()?, 897 auth_method: AuthMethod::decode_with(&mut reader)?, 898 }, 899 MSG_USERAUTH_FAILURE => Self::UserAuthFailure { 900 authentications_that_can_continue: NameList::decode_with(&mut reader)?, 901 partial_success: reader.read_boolean()?, 902 }, 903 MSG_USERAUTH_SUCCESS => Self::UserAuthSuccess, 904 MSG_USERAUTH_BANNER => Self::UserAuthBanner { 905 message: reader.read_string_utf8()?, 906 language: reader.read_string_utf8()?, 907 }, 908 MSG_USERAUTH_PK_OK => Self::UserAuthPkOk { 909 public_key_algorithm_name: reader.read_string_utf8()?, 910 public_key: PublicKey::decode_with(&mut reader)?, 911 }, 912 MSG_GLOBAL_REQUEST => Self::GlobalRequest { 913 request_name: reader.read_string_utf8()?, 914 want_reply: reader.read_boolean()?, 915 payload: reader.read_remaining(), 916 }, 917 MSG_REQUEST_SUCCESS => Self::RequestSuccess { 918 payload: reader.read_remaining(), 919 }, 920 MSG_REQUEST_FAILURE => Self::RequestFailure, 921 MSG_CHANNEL_OPEN => Self::ChannelOpen { 922 channel: ChannelType::decode_with(&mut reader)?, 923 }, 924 MSG_CHANNEL_OPEN_CONFIRMATION => Self::ChannelOpenConfirmation { 925 recipient_channel: reader.read_uint32()?, 926 sender_channel: reader.read_uint32()?, 927 initial_window_size: reader.read_uint32()?, 928 maximum_packet_size: reader.read_uint32()?, 929 payload: reader.read_remaining(), 930 }, 931 MSG_CHANNEL_OPEN_FAILURE => Self::ChannelOpenFailure { 932 recipient_channel: reader.read_uint32()?, 933 reason: ChannelOpenFailureReason::decode_with(&mut reader)?, 934 }, 935 MSG_CHANNEL_WINDOW_ADJUST => Self::ChannelWindowAdjust { 936 recipient_channel: reader.read_uint32()?, 937 bytes_to_add: reader.read_uint32()?, 938 }, 939 MSG_CHANNEL_DATA => Self::ChannelData { 940 recipient_channel: reader.read_uint32()?, 941 data: Data::decode_with(&mut reader)?, 942 }, 943 MSG_CHANNEL_EXTENDED_DATA => Self::ChannelExtendedData { 944 recipient_channel: reader.read_uint32()?, 945 data: ExtendedData::decode_with(&mut reader)?, 946 }, 947 MSG_CHANNEL_EOF => Self::ChannelEof { 948 recipient_channel: reader.read_uint32()?, 949 }, 950 MSG_CHANNEL_CLOSE => Self::ChannelClose { 951 recipient_channel: reader.read_uint32()?, 952 }, 953 MSG_CHANNEL_REQUEST => Self::ChannelRequest { 954 recipient_channel: reader.read_uint32()?, 955 request: Request::decode_with(&mut reader)?, 956 }, 957 MSG_CHANNEL_SUCCESS => Self::ChannelSuccess { 958 recipient_channel: reader.read_uint32()?, 959 }, 960 MSG_CHANNEL_FAILURE => Self::ChannelFailure { 961 recipient_channel: reader.read_uint32()?, 962 }, 963 unknown_message => Self::Unknown { 964 message: unknown_message, 965 payload: reader.read_remaining(), 966 }, 967 }; 968 969 if reader.read_remaining().is_empty() { 970 Ok(decoded) 971 } else { 972 Err(ProtocolError::TrailingPayload) 973 } 974 } 975 976 pub fn encode(self, buffer: &mut [u8]) -> Result<&[u8], ProtocolError> { 977 let mut writer = ObjectWriter::new(buffer); 978 979 match self { 980 Self::Ignore { data } => { 981 writer.write_byte(MSG_IGNORE)?; 982 writer.write_string(data)?; 983 } 984 Self::Debug { 985 always_display, 986 message, 987 language_tag, 988 } => { 989 writer.write_byte(MSG_DEBUG)?; 990 writer.write_boolean(always_display)?; 991 writer.write_string_utf8(message)?; 992 writer.write_string_utf8(language_tag)?; 993 } 994 Self::KexInit { 995 cookie, 996 kex_algorithms, 997 server_host_key_algorithms, 998 encryption_algorithms_client_to_server, 999 encryption_algorithms_server_to_client, 1000 mac_algorithms_client_to_server, 1001 mac_algorithms_server_to_client, 1002 compression_algorithms_client_to_server, 1003 compression_algorithms_server_to_client, 1004 languages_client_to_server, 1005 languages_server_to_client, 1006 first_kex_packet_follows, 1007 reserved, 1008 } => { 1009 writer.write_byte(MSG_KEX_INIT)?; 1010 writer.write_byte_array(cookie)?; 1011 writer.write_name_list(kex_algorithms)?; 1012 writer.write_name_list(server_host_key_algorithms)?; 1013 writer.write_name_list(encryption_algorithms_client_to_server)?; 1014 writer.write_name_list(encryption_algorithms_server_to_client)?; 1015 writer.write_name_list(mac_algorithms_client_to_server)?; 1016 writer.write_name_list(mac_algorithms_server_to_client)?; 1017 writer.write_name_list(compression_algorithms_client_to_server)?; 1018 writer.write_name_list(compression_algorithms_server_to_client)?; 1019 writer.write_name_list(languages_client_to_server)?; 1020 writer.write_name_list(languages_server_to_client)?; 1021 writer.write_boolean(first_kex_packet_follows)?; 1022 writer.write_uint32(reserved)?; 1023 } 1024 Self::Unimplemented { sequence_number } => { 1025 writer.write_byte(MSG_UNIMPLEMENTED)?; 1026 writer.write_uint32(sequence_number)?; 1027 } 1028 Self::KexEcdhInit { 1029 client_ephemeral_public_key, 1030 } => { 1031 writer.write_byte(MSG_KEX_ECDH_INIT)?; 1032 writer.write_string(client_ephemeral_public_key)?; 1033 } 1034 Self::KexEcdhReply { 1035 server_public_host_key, 1036 server_ephemeral_public_key, 1037 signature, 1038 } => { 1039 writer.write_byte(MSG_KEX_ECDH_REPLY)?; 1040 server_public_host_key.encode_with(&mut writer)?; 1041 writer.write_string(server_ephemeral_public_key)?; 1042 signature.encode_with(&mut writer)?; 1043 } 1044 Self::Disconnect { reason } => { 1045 writer.write_byte(MSG_DISCONNECT)?; 1046 reason.encode_with(&mut writer)?; 1047 } 1048 Self::NewKeys => { 1049 writer.write_byte(MSG_NEW_KEYS)?; 1050 } 1051 Self::ServiceAccept { service_name } => { 1052 writer.write_byte(MSG_SERVICE_ACCEPT)?; 1053 writer.write_string_utf8(service_name)?; 1054 } 1055 Self::ServiceRequest { service_name } => { 1056 writer.write_byte(MSG_SERVICE_REQUEST)?; 1057 writer.write_string_utf8(service_name)?; 1058 } 1059 Self::UserAuthRequest { 1060 user_name, 1061 service_name, 1062 auth_method, 1063 } => { 1064 writer.write_byte(MSG_USERAUTH_SUCCESS)?; 1065 writer.write_string_utf8(user_name)?; 1066 writer.write_string_utf8(service_name)?; 1067 auth_method.encode_with(&mut writer)?; 1068 } 1069 Self::UserAuthFailure { 1070 authentications_that_can_continue, 1071 partial_success, 1072 } => { 1073 writer.write_byte(MSG_USERAUTH_FAILURE)?; 1074 writer.write_name_list(authentications_that_can_continue)?; 1075 writer.write_boolean(partial_success)?; 1076 } 1077 Self::UserAuthSuccess => { 1078 writer.write_byte(MSG_USERAUTH_SUCCESS)?; 1079 } 1080 Self::UserAuthBanner { message, language } => { 1081 writer.write_byte(MSG_USERAUTH_BANNER)?; 1082 writer.write_string_utf8(message)?; 1083 writer.write_string_utf8(language)?; 1084 } 1085 Self::UserAuthPkOk { 1086 public_key_algorithm_name, 1087 public_key, 1088 } => { 1089 writer.write_byte(MSG_USERAUTH_PK_OK)?; 1090 writer.write_string_utf8(public_key_algorithm_name)?; 1091 public_key.encode_with(&mut writer)?; 1092 } 1093 Self::GlobalRequest { 1094 request_name, 1095 want_reply, 1096 payload, 1097 } => { 1098 writer.write_byte(MSG_GLOBAL_REQUEST)?; 1099 writer.write_string_utf8(request_name)?; 1100 writer.write_boolean(want_reply)?; 1101 writer.write_string(payload)?; 1102 } 1103 Self::RequestSuccess { payload } => { 1104 writer.write_byte(MSG_REQUEST_SUCCESS)?; 1105 writer.write_string(payload)?; 1106 } 1107 Self::RequestFailure => { 1108 writer.write_byte(MSG_REQUEST_FAILURE)?; 1109 } 1110 Self::ChannelOpen { channel } => { 1111 writer.write_byte(MSG_CHANNEL_OPEN)?; 1112 channel.encode_with(&mut writer)?; 1113 } 1114 Self::ChannelOpenConfirmation { 1115 recipient_channel, 1116 sender_channel, 1117 initial_window_size, 1118 maximum_packet_size, 1119 payload, 1120 } => { 1121 writer.write_byte(MSG_CHANNEL_OPEN_CONFIRMATION)?; 1122 writer.write_uint32(recipient_channel)?; 1123 writer.write_uint32(sender_channel)?; 1124 writer.write_uint32(initial_window_size)?; 1125 writer.write_uint32(maximum_packet_size)?; 1126 writer.write_byte_array(payload)?; 1127 } 1128 Self::ChannelOpenFailure { 1129 recipient_channel, 1130 reason, 1131 } => { 1132 writer.write_byte(MSG_CHANNEL_OPEN_FAILURE)?; 1133 writer.write_uint32(recipient_channel)?; 1134 reason.encode_with(&mut writer)?; 1135 } 1136 Self::ChannelWindowAdjust { 1137 recipient_channel, 1138 bytes_to_add, 1139 } => { 1140 writer.write_byte(MSG_CHANNEL_WINDOW_ADJUST)?; 1141 writer.write_uint32(recipient_channel)?; 1142 writer.write_uint32(bytes_to_add)?; 1143 } 1144 Self::ChannelData { 1145 recipient_channel, 1146 data, 1147 } => { 1148 writer.write_byte(MSG_CHANNEL_DATA)?; 1149 writer.write_uint32(recipient_channel)?; 1150 data.encode_with(&mut writer)?; 1151 } 1152 Self::ChannelExtendedData { 1153 recipient_channel, 1154 data, 1155 } => { 1156 writer.write_byte(MSG_CHANNEL_EXTENDED_DATA)?; 1157 writer.write_uint32(recipient_channel)?; 1158 data.encode_with(&mut writer)?; 1159 } 1160 Self::ChannelEof { recipient_channel } => { 1161 writer.write_byte(MSG_CHANNEL_EOF)?; 1162 writer.write_uint32(recipient_channel)?; 1163 } 1164 Self::ChannelClose { recipient_channel } => { 1165 writer.write_byte(MSG_CHANNEL_CLOSE)?; 1166 writer.write_uint32(recipient_channel)?; 1167 } 1168 Self::ChannelRequest { 1169 recipient_channel, 1170 request, 1171 } => { 1172 writer.write_byte(MSG_CHANNEL_REQUEST)?; 1173 writer.write_uint32(recipient_channel)?; 1174 request.encode_with(&mut writer)?; 1175 } 1176 Self::ChannelSuccess { recipient_channel } => { 1177 writer.write_byte(MSG_CHANNEL_SUCCESS)?; 1178 writer.write_uint32(recipient_channel)?; 1179 } 1180 Self::ChannelFailure { recipient_channel } => { 1181 writer.write_byte(MSG_CHANNEL_FAILURE)?; 1182 writer.write_uint32(recipient_channel)?; 1183 } 1184 Self::Unknown { .. } => unreachable!(), 1185 } 1186 1187 Ok(writer.into_written()) 1188 } 1189 } 1190 1191 // The SSH protocol uses 32-bit integers for various size quantities; these conversion 1192 // utilities will convert them to/from usize while avoiding silent integer truncation. 1193 1194 pub fn into_u32(value: usize) -> u32 { 1195 value.try_into().expect("failed to convert usize to u32") 1196 } 1197 1198 pub fn from_u32(value: u32) -> usize { 1199 value.try_into().expect("failed to convert u32 to usize") 1200 }