//! Messages involved in the SSH's **authentication** (`SSH-USERAUTH`) part of the protocol, //! as defined in the [RFC 4252](https://datatracker.ietf.org/doc/html/rfc4252) and [RFC 4256](https://datatracker.ietf.org/doc/html/rfc4256). use binrw::binrw; use crate::arch; /// The `SSH_MSG_USERAUTH_REQUEST` message. /// /// see . #[binrw] #[derive(Debug, Clone)] #[brw(big, magic = 50_u8)] pub struct Request<'b> { /// Username for the auth request. pub username: arch::Utf8<'b>, /// Service name to query. pub service_name: arch::Ascii<'b>, #[bw(calc = method.as_ascii())] auth_method: arch::Ascii<'b>, /// Authentication method used. #[br(args(auth_method))] pub method: Method<'b>, } /// The authentication method in the `SSH_MSG_USERAUTH_REQUEST` message. #[binrw] #[derive(Debug, Clone)] #[br(import(method: arch::Ascii<'_>))] pub enum Method<'b> { /// Authenticate using the `none` method, /// as defined in [RFC4252 section 5.2](https://datatracker.ietf.org/doc/html/rfc4252#section-5.2). #[br(pre_assert(method == Method::NONE))] None, /// Authenticate using the `publickey` method, /// as defined in [RFC4252 section 7](https://datatracker.ietf.org/doc/html/rfc4252#section-7). #[br(pre_assert(method == Method::PUBLICKEY))] Publickey { #[bw(calc = arch::Bool::from(signature.is_some()))] signed: arch::Bool, /// Public key algorithm's name. algorithm: arch::Bytes<'b>, /// Public key blob. blob: arch::Bytes<'b>, /// The optional signature of the authentication packet, /// signed with the according private key. #[br(if(*signed))] signature: Option>, }, /// Authenticate using the `password` method, /// as defined in [RFC4252 section 8](https://datatracker.ietf.org/doc/html/rfc4252#section-8). #[br(pre_assert(method == Method::PASSWORD))] Password { #[bw(calc = arch::Bool::from(new.is_some()))] change: arch::Bool, /// Plaintext password. password: arch::Utf8<'b>, /// In the case of a the receival of a [`PasswdChangereq`], /// the new password to be set in place of the old one. #[br(if(*change))] new: Option>, }, /// Authenticate using the `hostbased` method, /// as defined in [RFC4252 section 9](https://datatracker.ietf.org/doc/html/rfc4252#section-9). #[br(pre_assert(method == Method::HOSTBASED))] Hostbased { /// Public key algorithm for the host key. algorithm: arch::Bytes<'b>, /// Public host key and certificates for client host. host_key: arch::Bytes<'b>, /// Client host name expressed as the FQDN. client_fqdn: arch::Ascii<'b>, /// User name on the client host. username: arch::Utf8<'b>, /// The signature of the authentication packet. signature: arch::Bytes<'b>, }, /// Authenticate using the `keyboard-interactive` method, /// as defined in [RFC4256 section 3.1](https://datatracker.ietf.org/doc/html/rfc4256#section-3.1). #[br(pre_assert(method == Method::KEYBOARD_INTERACTIVE))] KeyboardInteractive { /// Language tag. language: arch::Ascii<'b>, /// A hint for the prefered interactive submethod. submethods: arch::Utf8<'b>, }, } impl Method<'_> { /// The SSH `none` authentication method. pub const NONE: arch::Ascii<'static> = arch::ascii!("none"); /// The SSH `publickey` authentication method. pub const PUBLICKEY: arch::Ascii<'static> = arch::ascii!("publickey"); /// The SSH `password` authentication method. pub const PASSWORD: arch::Ascii<'static> = arch::ascii!("password"); /// The SSH `hostbased` authentication method. pub const HOSTBASED: arch::Ascii<'static> = arch::ascii!("hostbased"); /// The SSH `keyboard-interactive` authentication method. pub const KEYBOARD_INTERACTIVE: arch::Ascii<'static> = arch::ascii!("keyboard-interactive"); /// Get the [`Method`]'s SSH identifier. pub fn as_ascii(&self) -> arch::Ascii<'static> { match self { Self::None { .. } => Self::NONE, Self::Publickey { .. } => Self::PUBLICKEY, Self::Password { .. } => Self::PASSWORD, Self::Hostbased { .. } => Self::HOSTBASED, Self::KeyboardInteractive { .. } => Self::KEYBOARD_INTERACTIVE, } } } /// The `SSH_MSG_USERAUTH_PK_OK` message. /// /// see . #[binrw] #[derive(Debug, Clone)] #[brw(big, magic = 60_u8)] pub struct PkOk<'b> { /// Public key algorithm name from the request. pub algorithm: arch::Bytes<'b>, /// Public key blob from the request. pub blob: arch::Bytes<'b>, } /// The `SSH_MSG_USERAUTH_PASSWD_CHANGEREQ` message. /// /// see . #[binrw] #[derive(Debug, Default, Clone)] #[brw(big, magic = 60_u8)] pub struct PasswdChangereq<'b> { /// Password change prompt. pub prompt: arch::Utf8<'b>, /// Language tag (deprecated). pub language: arch::Ascii<'b>, } /// The `SSH_MSG_USERAUTH_INFO_REQUEST` message. /// /// see . #[binrw] #[derive(Debug, Clone)] #[brw(big, magic = 60_u8)] pub struct InfoRequest<'b> { /// Name of the challenge. pub name: arch::Utf8<'b>, /// Instructions for the challenge. pub instruction: arch::Utf8<'b>, /// Language tag (deprecated). pub language: arch::Ascii<'b>, #[bw(calc = prompts.len() as u32)] num_prompts: u32, /// The challenge's prompts. #[br(count = num_prompts)] pub prompts: Vec>, } /// A prompt in the `SSH_MSG_USERAUTH_INFO_REQUEST` message. #[binrw] #[derive(Debug, Clone)] #[brw(big)] pub struct InfoRequestPrompt<'b> { /// Challenge prompt text. pub prompt: arch::Utf8<'b>, /// Whether the client should echo back typed characters. pub echo: arch::Bool, } /// The `SSH_MSG_USERAUTH_INFO_RESPONSE` message. /// /// see . #[binrw] #[derive(Debug, Clone)] #[brw(big, magic = 61_u8)] pub struct InfoResponse { #[bw(calc = responses.len() as u32)] num_responses: u32, /// Responses to the provided challenge. #[br(count = num_responses)] pub responses: Vec>, } /// The `SSH_MSG_USERAUTH_FAILURE` message. /// /// see . #[binrw] #[derive(Debug, Default, Clone)] #[brw(big, magic = 51_u8)] pub struct Failure<'b> { /// Authentications that can continue. pub continue_with: arch::NameList<'b>, /// Partial success. pub partial_success: arch::Bool, } /// The `SSH_MSG_USERAUTH_SUCCESS` message. /// /// see . #[binrw] #[derive(Debug, Default, Clone)] #[brw(big, magic = 52_u8)] pub struct Success; /// The `SSH_MSG_USERAUTH_BANNER` message. /// /// see . #[binrw] #[derive(Debug, Default, Clone)] #[brw(big, magic = 53_u8)] pub struct Banner<'b> { /// The auth banner message. pub message: arch::Utf8<'b>, /// Language tag. pub language: arch::Ascii<'b>, }