mirror of
https://github.com/Noratrieb/cluelessh.git
synced 2026-01-14 16:35:06 +01:00
more moves
This commit is contained in:
parent
8a627949a3
commit
362d8c57ce
16 changed files with 164 additions and 175 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -324,6 +324,7 @@ dependencies = [
|
||||||
name = "cluelessh-connection"
|
name = "cluelessh-connection"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"cluelessh-format",
|
||||||
"cluelessh-transport",
|
"cluelessh-transport",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,10 @@ pub enum AuthError {
|
||||||
|
|
||||||
impl UserPublicKey {
|
impl UserPublicKey {
|
||||||
/// Blocking!
|
/// Blocking!
|
||||||
pub async fn for_user_and_key(user: String, provided_key: &PublicKey) -> Result<Self, AuthError> {
|
pub async fn for_user_and_key(
|
||||||
|
user: String,
|
||||||
|
provided_key: &PublicKey,
|
||||||
|
) -> Result<Self, AuthError> {
|
||||||
let user = tokio::task::spawn_blocking(move || {
|
let user = tokio::task::spawn_blocking(move || {
|
||||||
users::get_user_by_name(&user).ok_or(AuthError::UnknownUser)
|
users::get_user_by_name(&user).ok_or(AuthError::UnknownUser)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
cluelessh-format = { version = "0.1.0", path = "../cluelessh-format" }
|
||||||
cluelessh-transport = { path = "../cluelessh-transport" }
|
cluelessh-transport = { path = "../cluelessh-transport" }
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,10 @@ use std::cmp;
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
use tracing::{debug, info, trace, warn};
|
use tracing::{debug, info, trace, warn};
|
||||||
|
|
||||||
|
use cluelessh_format::numbers;
|
||||||
use cluelessh_transport::packet::Packet;
|
use cluelessh_transport::packet::Packet;
|
||||||
|
use cluelessh_transport::peer_error;
|
||||||
use cluelessh_transport::Result;
|
use cluelessh_transport::Result;
|
||||||
use cluelessh_transport::{numbers, peer_error};
|
|
||||||
|
|
||||||
/// A channel number (on our side).
|
/// A channel number (on our side).
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
|
@ -728,7 +729,8 @@ impl ChannelOperation {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use cluelessh_transport::{numbers, packet::Packet};
|
use cluelessh_format::numbers;
|
||||||
|
use cluelessh_transport::packet::Packet;
|
||||||
|
|
||||||
use crate::{ChannelNumber, ChannelOperation, ChannelOperationKind, ChannelsState};
|
use crate::{ChannelNumber, ChannelOperation, ChannelOperationKind, ChannelsState};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
pub mod numbers;
|
||||||
|
|
||||||
use core::str;
|
use core::str;
|
||||||
use std::fmt::{Debug, Display};
|
use std::fmt::{Debug, Display};
|
||||||
|
|
||||||
|
|
|
||||||
111
lib/cluelessh-format/src/numbers.rs
Normal file
111
lib/cluelessh-format/src/numbers.rs
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
//! Constants for SSH.
|
||||||
|
//! <https://datatracker.ietf.org/doc/html/rfc4250>
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! consts {
|
||||||
|
(
|
||||||
|
$ty:ty, fn $to_str_name:ident,
|
||||||
|
$(const $NAME:ident = $value:expr;)*
|
||||||
|
) => {
|
||||||
|
$(
|
||||||
|
pub const $NAME: $ty = $value;
|
||||||
|
)*
|
||||||
|
|
||||||
|
pub fn $to_str_name(v: $ty) -> &'static str {
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
|
match v {
|
||||||
|
$(
|
||||||
|
$NAME => stringify!($NAME),
|
||||||
|
)*
|
||||||
|
_ => "<unknown>",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
consts! {
|
||||||
|
u8, fn packet_type_to_string,
|
||||||
|
// -----
|
||||||
|
// Transport layer protocol:
|
||||||
|
|
||||||
|
// 1 to 19 Transport layer generic (e.g., disconnect, ignore, debug, etc.)
|
||||||
|
const SSH_MSG_DISCONNECT = 1;
|
||||||
|
const SSH_MSG_IGNORE = 2;
|
||||||
|
const SSH_MSG_UNIMPLEMENTED = 3;
|
||||||
|
const SSH_MSG_DEBUG = 4;
|
||||||
|
const SSH_MSG_SERVICE_REQUEST = 5;
|
||||||
|
const SSH_MSG_SERVICE_ACCEPT = 6;
|
||||||
|
|
||||||
|
// 20 to 29 Algorithm negotiation
|
||||||
|
const SSH_MSG_KEXINIT = 20;
|
||||||
|
const SSH_MSG_NEWKEYS = 21;
|
||||||
|
|
||||||
|
// 30 to 49 Key exchange method specific (numbers can be reused for different authentication methods)
|
||||||
|
const SSH_MSG_KEXDH_INIT = 30;
|
||||||
|
const SSH_MSG_KEX_ECDH_INIT = 30; // Same number
|
||||||
|
const SSH_MSG_KEXDH_REPLY = 31;
|
||||||
|
const SSH_MSG_KEX_ECDH_REPLY = 31;
|
||||||
|
|
||||||
|
// -----
|
||||||
|
// User authentication protocol:
|
||||||
|
|
||||||
|
// 50 to 59 User authentication generic
|
||||||
|
const SSH_MSG_USERAUTH_REQUEST = 50;
|
||||||
|
const SSH_MSG_USERAUTH_FAILURE = 51;
|
||||||
|
const SSH_MSG_USERAUTH_SUCCESS = 52;
|
||||||
|
const SSH_MSG_USERAUTH_BANNER = 53;
|
||||||
|
|
||||||
|
// 60 to 79 User authentication method specific (numbers can be reused for different authentication methods)
|
||||||
|
const SSH_MSG_USERAUTH_PK_OK = 60;
|
||||||
|
|
||||||
|
// -----
|
||||||
|
// Connection protocol:
|
||||||
|
|
||||||
|
// 80 to 89 Connection protocol generic
|
||||||
|
const SSH_MSG_GLOBAL_REQUEST = 80;
|
||||||
|
const SSH_MSG_REQUEST_SUCCESS = 81;
|
||||||
|
const SSH_MSG_REQUEST_FAILURE = 82;
|
||||||
|
|
||||||
|
// 90 to 127 Channel related messages
|
||||||
|
const SSH_MSG_CHANNEL_OPEN = 90;
|
||||||
|
const SSH_MSG_CHANNEL_OPEN_CONFIRMATION = 91;
|
||||||
|
const SSH_MSG_CHANNEL_OPEN_FAILURE = 92;
|
||||||
|
const SSH_MSG_CHANNEL_WINDOW_ADJUST = 93;
|
||||||
|
const SSH_MSG_CHANNEL_DATA = 94;
|
||||||
|
const SSH_MSG_CHANNEL_EXTENDED_DATA = 95;
|
||||||
|
const SSH_MSG_CHANNEL_EOF = 96;
|
||||||
|
const SSH_MSG_CHANNEL_CLOSE = 97;
|
||||||
|
const SSH_MSG_CHANNEL_REQUEST = 98;
|
||||||
|
const SSH_MSG_CHANNEL_SUCCESS = 99;
|
||||||
|
const SSH_MSG_CHANNEL_FAILURE = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
consts! {
|
||||||
|
u32, fn disconnect_reason_to_string,
|
||||||
|
const SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT = 1;
|
||||||
|
const SSH_DISCONNECT_PROTOCOL_ERROR = 2;
|
||||||
|
const SSH_DISCONNECT_KEY_EXCHANGE_FAILED = 3;
|
||||||
|
const SSH_DISCONNECT_RESERVED = 4;
|
||||||
|
const SSH_DISCONNECT_MAC_ERROR = 5;
|
||||||
|
const SSH_DISCONNECT_COMPRESSION_ERROR = 6;
|
||||||
|
const SSH_DISCONNECT_SERVICE_NOT_AVAILABLE = 7;
|
||||||
|
const SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED = 8;
|
||||||
|
const SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE = 9;
|
||||||
|
const SSH_DISCONNECT_CONNECTION_LOST = 10;
|
||||||
|
const SSH_DISCONNECT_BY_APPLICATION = 11;
|
||||||
|
const SSH_DISCONNECT_TOO_MANY_CONNECTIONS = 12;
|
||||||
|
const SSH_DISCONNECT_AUTH_CANCELLED_BY_USER = 13;
|
||||||
|
const SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE = 14;
|
||||||
|
const SSH_DISCONNECT_ILLEGAL_USER_NAME = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
consts! {
|
||||||
|
u32, fn channel_connection_failure_to_string,
|
||||||
|
|
||||||
|
const SSH_OPEN_ADMINISTRATIVELY_PROHIBITED = 1;
|
||||||
|
const SSH_OPEN_CONNECT_FAILED = 2;
|
||||||
|
const SSH_OPEN_UNKNOWN_CHANNEL_TYPE = 3;
|
||||||
|
const SSH_OPEN_RESOURCE_SHORTAGE = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const SSH_EXTENDED_DATA_STDERR: u32 = 1;
|
||||||
|
|
@ -81,14 +81,16 @@ impl Kdf {
|
||||||
let salt = opts.string()?;
|
let salt = opts.string()?;
|
||||||
let rounds = opts.u32()?;
|
let rounds = opts.u32()?;
|
||||||
Kdf::BCrypt {
|
Kdf::BCrypt {
|
||||||
salt: salt
|
salt: salt.try_into().map_err(|_| {
|
||||||
.try_into()
|
cluelessh_format::ParseError(format!("incorrect bcrypt salt len"))
|
||||||
.map_err(|_| cluelessh_format::ParseError(format!("incorrect bcrypt salt len")))?,
|
})?,
|
||||||
rounds,
|
rounds,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(cluelessh_format::ParseError(format!("unsupported KDF: {kdfname}")));
|
return Err(cluelessh_format::ParseError(format!(
|
||||||
|
"unsupported KDF: {kdfname}"
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(kdf)
|
Ok(kdf)
|
||||||
|
|
@ -113,12 +115,18 @@ impl Kdf {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn derive(&self, passphrase: &str, output: &mut [u8]) -> cluelessh_format::Result<()> {
|
pub(crate) fn derive(
|
||||||
|
&self,
|
||||||
|
passphrase: &str,
|
||||||
|
output: &mut [u8],
|
||||||
|
) -> cluelessh_format::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
Self::None => unreachable!("should not attempt to derive passphrase from none"),
|
Self::None => unreachable!("should not attempt to derive passphrase from none"),
|
||||||
Self::BCrypt { salt, rounds } => {
|
Self::BCrypt { salt, rounds } => {
|
||||||
bcrypt_pbkdf::bcrypt_pbkdf(passphrase, salt, *rounds, output).map_err(|err| {
|
bcrypt_pbkdf::bcrypt_pbkdf(passphrase, salt, *rounds, output).map_err(|err| {
|
||||||
cluelessh_format::ParseError(format!("error when performing key derivation: {err}"))
|
cluelessh_format::ParseError(format!(
|
||||||
|
"error when performing key derivation: {err}"
|
||||||
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,9 @@ impl EncryptedPrivateKeys {
|
||||||
let content = if content.starts_with(b"openssh-key-v1") {
|
let content = if content.starts_with(b"openssh-key-v1") {
|
||||||
content
|
content
|
||||||
} else if content.starts_with(b"-----BEGIN OPENSSH PRIVATE KEY-----") {
|
} else if content.starts_with(b"-----BEGIN OPENSSH PRIVATE KEY-----") {
|
||||||
pem = pem::parse(content)
|
pem = pem::parse(content).map_err(|err| {
|
||||||
.map_err(|err| cluelessh_format::ParseError(format!("invalid PEM format: {err}")))?;
|
cluelessh_format::ParseError(format!("invalid PEM format: {err}"))
|
||||||
|
})?;
|
||||||
pem.contents()
|
pem.contents()
|
||||||
} else {
|
} else {
|
||||||
return Err(cluelessh_format::ParseError("invalid SSH key".to_owned()));
|
return Err(cluelessh_format::ParseError("invalid SSH key".to_owned()));
|
||||||
|
|
@ -115,7 +116,10 @@ impl EncryptedPrivateKeys {
|
||||||
(!matches!(self.kdf, Kdf::None)) && (!matches!(self.cipher, Cipher::None))
|
(!matches!(self.kdf, Kdf::None)) && (!matches!(self.cipher, Cipher::None))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrypt_encrypted_part(&self, passphrase: Option<&str>) -> cluelessh_format::Result<Vec<u8>> {
|
pub fn decrypt_encrypted_part(
|
||||||
|
&self,
|
||||||
|
passphrase: Option<&str>,
|
||||||
|
) -> cluelessh_format::Result<Vec<u8>> {
|
||||||
let mut data = self.encrypted_private_keys.clone();
|
let mut data = self.encrypted_private_keys.clone();
|
||||||
if self.requires_passphrase() {
|
if self.requires_passphrase() {
|
||||||
let Some(passphrase) = passphrase else {
|
let Some(passphrase) = passphrase else {
|
||||||
|
|
@ -145,7 +149,9 @@ impl EncryptedPrivateKeys {
|
||||||
let checkint1 = p.u32()?;
|
let checkint1 = p.u32()?;
|
||||||
let checkint2 = p.u32()?;
|
let checkint2 = p.u32()?;
|
||||||
if checkint1 != checkint2 {
|
if checkint1 != checkint2 {
|
||||||
return Err(cluelessh_format::ParseError(format!("invalid key or password")));
|
return Err(cluelessh_format::ParseError(format!(
|
||||||
|
"invalid key or password"
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result_keys = Vec::new();
|
let mut result_keys = Vec::new();
|
||||||
|
|
@ -246,7 +252,10 @@ impl PlaintextPrivateKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encrypt(&self, params: KeyEncryptionParams) -> cluelessh_format::Result<EncryptedPrivateKeys> {
|
pub fn encrypt(
|
||||||
|
&self,
|
||||||
|
params: KeyEncryptionParams,
|
||||||
|
) -> cluelessh_format::Result<EncryptedPrivateKeys> {
|
||||||
let public_keys = vec![self.private_key.public_key()];
|
let public_keys = vec![self.private_key.public_key()];
|
||||||
|
|
||||||
let mut enc = Writer::new();
|
let mut enc = Writer::new();
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ pub fn signature_data(session_id: [u8; 32], username: &str, pubkey: &PublicKey)
|
||||||
let mut s = Writer::new();
|
let mut s = Writer::new();
|
||||||
|
|
||||||
s.string(session_id);
|
s.string(session_id);
|
||||||
s.u8(cluelessh_transport::numbers::SSH_MSG_USERAUTH_REQUEST);
|
s.u8(cluelessh_format::numbers::SSH_MSG_USERAUTH_REQUEST);
|
||||||
s.string(username);
|
s.string(username);
|
||||||
s.string("ssh-connection");
|
s.string("ssh-connection");
|
||||||
s.string("publickey");
|
s.string("publickey");
|
||||||
|
|
|
||||||
|
|
@ -266,8 +266,8 @@ impl ClientConnection {
|
||||||
pub mod auth {
|
pub mod auth {
|
||||||
use std::collections::{HashSet, VecDeque};
|
use std::collections::{HashSet, VecDeque};
|
||||||
|
|
||||||
use cluelessh_format::NameList;
|
use cluelessh_format::{numbers, NameList};
|
||||||
use cluelessh_transport::{numbers, packet::Packet, peer_error, Result};
|
use cluelessh_transport::{packet::Packet, peer_error, Result};
|
||||||
use tracing::{debug, info};
|
use tracing::{debug, info};
|
||||||
|
|
||||||
pub struct ServerAuth {
|
pub struct ServerAuth {
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,10 @@ use crate::{
|
||||||
self, AlgorithmName, EncodedSshSignature, EncryptionAlgorithm, HostKeySigningAlgorithm,
|
self, AlgorithmName, EncodedSshSignature, EncryptionAlgorithm, HostKeySigningAlgorithm,
|
||||||
KeyExchangeSecret, SupportedAlgorithms,
|
KeyExchangeSecret, SupportedAlgorithms,
|
||||||
},
|
},
|
||||||
numbers,
|
|
||||||
packet::{Packet, PacketTransport, ProtocolIdentParser},
|
packet::{Packet, PacketTransport, ProtocolIdentParser},
|
||||||
peer_error, Msg, Result, SshRng, SshStatus,
|
peer_error, Msg, Result, SshRng, SshStatus,
|
||||||
};
|
};
|
||||||
use cluelessh_format::{NameList, Reader, Writer};
|
use cluelessh_format::{numbers, NameList, Reader, Writer};
|
||||||
|
|
||||||
pub struct ClientConnection {
|
pub struct ClientConnection {
|
||||||
state: ClientState,
|
state: ClientState,
|
||||||
|
|
@ -111,8 +110,7 @@ impl ClientConnection {
|
||||||
let description = p.utf8_string()?;
|
let description = p.utf8_string()?;
|
||||||
let _language_tag = p.utf8_string()?;
|
let _language_tag = p.utf8_string()?;
|
||||||
|
|
||||||
let reason_string =
|
let reason_string = numbers::disconnect_reason_to_string(reason);
|
||||||
numbers::disconnect_reason_to_string(reason).unwrap_or("<unknown>");
|
|
||||||
|
|
||||||
info!(%reason, %reason_string, %description, "Server disconnecting");
|
info!(%reason, %reason_string, %description, "Server disconnecting");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
pub mod client;
|
pub mod client;
|
||||||
mod crypto;
|
mod crypto;
|
||||||
pub mod key;
|
pub mod key;
|
||||||
pub mod numbers;
|
|
||||||
pub mod packet;
|
pub mod packet;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
|
||||||
|
|
@ -27,7 +26,6 @@ impl From<ParseError> for SshStatus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub trait SshRng {
|
pub trait SshRng {
|
||||||
fn fill_bytes(&mut self, dest: &mut [u8]);
|
fn fill_bytes(&mut self, dest: &mut [u8]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,145 +0,0 @@
|
||||||
//! Constants for SSH.
|
|
||||||
//! <https://datatracker.ietf.org/doc/html/rfc4250>
|
|
||||||
|
|
||||||
// -----
|
|
||||||
// Transport layer protocol:
|
|
||||||
|
|
||||||
// 1 to 19 Transport layer generic (e.g., disconnect, ignore, debug, etc.)
|
|
||||||
pub const SSH_MSG_DISCONNECT: u8 = 1;
|
|
||||||
pub const SSH_MSG_IGNORE: u8 = 2;
|
|
||||||
pub const SSH_MSG_UNIMPLEMENTED: u8 = 3;
|
|
||||||
pub const SSH_MSG_DEBUG: u8 = 4;
|
|
||||||
pub const SSH_MSG_SERVICE_REQUEST: u8 = 5;
|
|
||||||
pub const SSH_MSG_SERVICE_ACCEPT: u8 = 6;
|
|
||||||
|
|
||||||
// 20 to 29 Algorithm negotiation
|
|
||||||
pub const SSH_MSG_KEXINIT: u8 = 20;
|
|
||||||
pub const SSH_MSG_NEWKEYS: u8 = 21;
|
|
||||||
|
|
||||||
// 30 to 49 Key exchange method specific (numbers can be reused for different authentication methods)
|
|
||||||
pub const SSH_MSG_KEXDH_INIT: u8 = 30;
|
|
||||||
pub const SSH_MSG_KEX_ECDH_INIT: u8 = 30; // Same number
|
|
||||||
pub const SSH_MSG_KEXDH_REPLY: u8 = 31;
|
|
||||||
pub const SSH_MSG_KEX_ECDH_REPLY: u8 = 31;
|
|
||||||
|
|
||||||
// -----
|
|
||||||
// User authentication protocol:
|
|
||||||
|
|
||||||
// 50 to 59 User authentication generic
|
|
||||||
pub const SSH_MSG_USERAUTH_REQUEST: u8 = 50;
|
|
||||||
pub const SSH_MSG_USERAUTH_FAILURE: u8 = 51;
|
|
||||||
pub const SSH_MSG_USERAUTH_SUCCESS: u8 = 52;
|
|
||||||
pub const SSH_MSG_USERAUTH_BANNER: u8 = 53;
|
|
||||||
|
|
||||||
// 60 to 79 User authentication method specific (numbers can be reused for different authentication methods)
|
|
||||||
pub const SSH_MSG_USERAUTH_PK_OK: u8 = 60;
|
|
||||||
|
|
||||||
// -----
|
|
||||||
// Connection protocol:
|
|
||||||
|
|
||||||
// 80 to 89 Connection protocol generic
|
|
||||||
pub const SSH_MSG_GLOBAL_REQUEST: u8 = 80;
|
|
||||||
pub const SSH_MSG_REQUEST_SUCCESS: u8 = 81;
|
|
||||||
pub const SSH_MSG_REQUEST_FAILURE: u8 = 82;
|
|
||||||
|
|
||||||
// 90 to 127 Channel related messages
|
|
||||||
pub const SSH_MSG_CHANNEL_OPEN: u8 = 90;
|
|
||||||
pub const SSH_MSG_CHANNEL_OPEN_CONFIRMATION: u8 = 91;
|
|
||||||
pub const SSH_MSG_CHANNEL_OPEN_FAILURE: u8 = 92;
|
|
||||||
pub const SSH_MSG_CHANNEL_WINDOW_ADJUST: u8 = 93;
|
|
||||||
pub const SSH_MSG_CHANNEL_DATA: u8 = 94;
|
|
||||||
pub const SSH_MSG_CHANNEL_EXTENDED_DATA: u8 = 95;
|
|
||||||
pub const SSH_MSG_CHANNEL_EOF: u8 = 96;
|
|
||||||
pub const SSH_MSG_CHANNEL_CLOSE: u8 = 97;
|
|
||||||
pub const SSH_MSG_CHANNEL_REQUEST: u8 = 98;
|
|
||||||
pub const SSH_MSG_CHANNEL_SUCCESS: u8 = 99;
|
|
||||||
pub const SSH_MSG_CHANNEL_FAILURE: u8 = 100;
|
|
||||||
|
|
||||||
pub fn packet_type_to_string(packet_type: u8) -> &'static str {
|
|
||||||
match packet_type {
|
|
||||||
1 => "SSH_MSG_DISCONNECT",
|
|
||||||
2 => "SSH_MSG_IGNORE",
|
|
||||||
3 => "SSH_MSG_UNIMPLEMENTED",
|
|
||||||
4 => "SSH_MSG_DEBUG",
|
|
||||||
5 => "SSH_MSG_SERVICE_REQUEST",
|
|
||||||
6 => "SSH_MSG_SERVICE_ACCEPT",
|
|
||||||
20 => "SSH_MSG_KEXINIT",
|
|
||||||
21 => "SSH_MSG_NEWKEYS",
|
|
||||||
30 => "SSH_MSG_KEX_ECDH_INIT",
|
|
||||||
31 => "SSH_MSG_KEX_ECDH_REPLY",
|
|
||||||
50 => "SSH_MSG_USERAUTH_REQUEST",
|
|
||||||
51 => "SSH_MSG_USERAUTH_FAILURE",
|
|
||||||
52 => "SSH_MSG_USERAUTH_SUCCESS",
|
|
||||||
53 => "SSH_MSG_USERAUTH_BANNER",
|
|
||||||
60 => "SSH_MSG_USERAUTH_PK_OK",
|
|
||||||
80 => "SSH_MSG_GLOBAL_REQUEST",
|
|
||||||
81 => "SSH_MSG_REQUEST_SUCCESS",
|
|
||||||
82 => "SSH_MSG_REQUEST_FAILURE",
|
|
||||||
90 => "SSH_MSG_CHANNEL_OPEN",
|
|
||||||
91 => "SSH_MSG_CHANNEL_OPEN_CONFIRMATION",
|
|
||||||
92 => "SSH_MSG_CHANNEL_OPEN_FAILURE",
|
|
||||||
93 => "SSH_MSG_CHANNEL_WINDOW_ADJUST",
|
|
||||||
94 => "SSH_MSG_CHANNEL_DATA",
|
|
||||||
95 => "SSH_MSG_CHANNEL_EXTENDED_DATA",
|
|
||||||
96 => "SSH_MSG_CHANNEL_EOF",
|
|
||||||
97 => "SSH_MSG_CHANNEL_CLOSE",
|
|
||||||
98 => "SSH_MSG_CHANNEL_REQUEST",
|
|
||||||
99 => "SSH_MSG_CHANNEL_SUCCESS",
|
|
||||||
100 => "SSH_MSG_CHANNEL_FAILURE",
|
|
||||||
_ => "<unknown>",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT: u32 = 1;
|
|
||||||
pub const SSH_DISCONNECT_PROTOCOL_ERROR: u32 = 2;
|
|
||||||
pub const SSH_DISCONNECT_KEY_EXCHANGE_FAILED: u32 = 3;
|
|
||||||
pub const SSH_DISCONNECT_RESERVED: u32 = 4;
|
|
||||||
pub const SSH_DISCONNECT_MAC_ERROR: u32 = 5;
|
|
||||||
pub const SSH_DISCONNECT_COMPRESSION_ERROR: u32 = 6;
|
|
||||||
pub const SSH_DISCONNECT_SERVICE_NOT_AVAILABLE: u32 = 7;
|
|
||||||
pub const SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED: u32 = 8;
|
|
||||||
pub const SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE: u32 = 9;
|
|
||||||
pub const SSH_DISCONNECT_CONNECTION_LOST: u32 = 10;
|
|
||||||
pub const SSH_DISCONNECT_BY_APPLICATION: u32 = 11;
|
|
||||||
pub const SSH_DISCONNECT_TOO_MANY_CONNECTIONS: u32 = 12;
|
|
||||||
pub const SSH_DISCONNECT_AUTH_CANCELLED_BY_USER: u32 = 13;
|
|
||||||
pub const SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE: u32 = 14;
|
|
||||||
pub const SSH_DISCONNECT_ILLEGAL_USER_NAME: u32 = 15;
|
|
||||||
|
|
||||||
pub fn disconnect_reason_to_string(reason: u32) -> Option<&'static str> {
|
|
||||||
Some(match reason {
|
|
||||||
1 => "SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT",
|
|
||||||
2 => "SSH_DISCONNECT_PROTOCOL_ERROR",
|
|
||||||
3 => "SSH_DISCONNECT_KEY_EXCHANGE_FAILED",
|
|
||||||
4 => "SSH_DISCONNECT_RESERVED",
|
|
||||||
5 => "SSH_DISCONNECT_MAC_ERROR",
|
|
||||||
6 => "SSH_DISCONNECT_COMPRESSION_ERROR",
|
|
||||||
7 => "SSH_DISCONNECT_SERVICE_NOT_AVAILABLE",
|
|
||||||
8 => "SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED",
|
|
||||||
9 => "SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE",
|
|
||||||
10 => "SSH_DISCONNECT_CONNECTION_LOST",
|
|
||||||
11 => "SSH_DISCONNECT_BY_APPLICATION",
|
|
||||||
12 => "SSH_DISCONNECT_TOO_MANY_CONNECTIONS",
|
|
||||||
13 => "SSH_DISCONNECT_AUTH_CANCELLED_BY_USER",
|
|
||||||
14 => "SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE",
|
|
||||||
15 => "SSH_DISCONNECT_ILLEGAL_USER_NAME",
|
|
||||||
_ => return None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const SSH_OPEN_ADMINISTRATIVELY_PROHIBITED: u32 = 1;
|
|
||||||
pub const SSH_OPEN_CONNECT_FAILED: u32 = 2;
|
|
||||||
pub const SSH_OPEN_UNKNOWN_CHANNEL_TYPE: u32 = 3;
|
|
||||||
pub const SSH_OPEN_RESOURCE_SHORTAGE: u32 = 4;
|
|
||||||
|
|
||||||
pub fn channel_connection_failure_to_string(reason: u32) -> Option<&'static str> {
|
|
||||||
Some(match reason {
|
|
||||||
1 => "SSH_OPEN_ADMINISTRATIVELY_PROHIBITED",
|
|
||||||
2 => "SSH_OPEN_CONNECT_FAILED",
|
|
||||||
3 => "SSH_OPEN_UNKNOWN_CHANNEL_TYPE",
|
|
||||||
4 => "SSH_OPEN_RESOURCE_SHORTAGE",
|
|
||||||
_ => return None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const SSH_EXTENDED_DATA_STDERR: u32 = 1;
|
|
||||||
|
|
@ -6,9 +6,10 @@ use std::mem;
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, trace};
|
||||||
|
|
||||||
use crate::crypto::{self, EncryptionAlgorithm, Keys, Plaintext, Session};
|
use crate::crypto::{self, EncryptionAlgorithm, Keys, Plaintext, Session};
|
||||||
use cluelessh_format::{NameList, Reader, Writer};
|
use crate::peer_error;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use crate::{numbers, peer_error};
|
use cluelessh_format::numbers;
|
||||||
|
use cluelessh_format::{NameList, Reader, Writer};
|
||||||
|
|
||||||
/// Frames the byte stream into packets.
|
/// Frames the byte stream into packets.
|
||||||
pub(crate) struct PacketTransport {
|
pub(crate) struct PacketTransport {
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ macro_rules! ctors {
|
||||||
) -> Packet {
|
) -> Packet {
|
||||||
let mut w = Writer::new();
|
let mut w = Writer::new();
|
||||||
|
|
||||||
w.u8($crate::numbers::$msg_type);
|
w.u8(cluelessh_format::numbers::$msg_type);
|
||||||
|
|
||||||
$(
|
$(
|
||||||
w.$ssh_type($name);
|
w.$ssh_type($name);
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,10 @@ use crate::crypto::{
|
||||||
use crate::packet::{
|
use crate::packet::{
|
||||||
KeyExchangeEcDhInitPacket, KeyExchangeInitPacket, Packet, PacketTransport, ProtocolIdentParser,
|
KeyExchangeEcDhInitPacket, KeyExchangeInitPacket, Packet, PacketTransport, ProtocolIdentParser,
|
||||||
};
|
};
|
||||||
use cluelessh_format::{NameList, Reader, Writer};
|
use crate::Result;
|
||||||
use crate::{numbers, Result};
|
|
||||||
use crate::{peer_error, Msg, SshRng, SshStatus};
|
use crate::{peer_error, Msg, SshRng, SshStatus};
|
||||||
|
use cluelessh_format::numbers;
|
||||||
|
use cluelessh_format::{NameList, Reader, Writer};
|
||||||
use tracing::{debug, info, trace};
|
use tracing::{debug, info, trace};
|
||||||
|
|
||||||
// This is definitely who we are.
|
// This is definitely who we are.
|
||||||
|
|
@ -96,8 +97,7 @@ impl ServerConnection {
|
||||||
let description = disconnect.utf8_string()?;
|
let description = disconnect.utf8_string()?;
|
||||||
let _language_tag = disconnect.utf8_string()?;
|
let _language_tag = disconnect.utf8_string()?;
|
||||||
|
|
||||||
let reason_string =
|
let reason_string = numbers::disconnect_reason_to_string(reason);
|
||||||
numbers::disconnect_reason_to_string(reason).unwrap_or("<unknown>");
|
|
||||||
|
|
||||||
info!(%reason, %reason_string, %description, "Client disconnecting");
|
info!(%reason, %reason_string, %description, "Client disconnecting");
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue