diff --git a/Cargo.lock b/Cargo.lock index 1571e7fbd..6e88e48c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4204,7 +4204,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.5", + "winnow 0.6.6", ] [[package]] @@ -5025,9 +5025,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" dependencies = [ "memchr", ] diff --git a/crates/ironrdp-acceptor/src/connection.rs b/crates/ironrdp-acceptor/src/connection.rs index a8a4a477c..eacf60761 100644 --- a/crates/ironrdp-acceptor/src/connection.rs +++ b/crates/ironrdp-acceptor/src/connection.rs @@ -8,6 +8,7 @@ use ironrdp_pdu as pdu; use ironrdp_svc::{StaticChannelSet, SvcServerProcessor}; use pdu::rdp::capability_sets::CapabilitySet; use pdu::rdp::headers::ShareControlPdu; +use pdu::rdp::server_license::{LicensePdu, LicensingErrorMessage}; use pdu::write_buf::WriteBuf; use pdu::{decode, gcc, mcs, nego, rdp}; @@ -392,7 +393,9 @@ impl Sequence for Acceptor { early_capability, channels, } => { - let license = rdp::server_license::InitialServerLicenseMessage::new_status_valid_client_message(); + let license: LicensePdu = LicensingErrorMessage::new_valid_client() + .map_err(ConnectorError::pdu)? + .into(); debug!(message = ?license, "Send"); diff --git a/crates/ironrdp-connector/src/connection.rs b/crates/ironrdp-connector/src/connection.rs index 99c114158..69902bed1 100644 --- a/crates/ironrdp-connector/src/connection.rs +++ b/crates/ironrdp-connector/src/connection.rs @@ -700,13 +700,16 @@ fn create_client_info_pdu(config: &Config, routing_addr: &SocketAddr) -> rdp::Cl }; // Default flags for all sessions - let mut flags = ClientInfoFlags::UNICODE + let mut flags = ClientInfoFlags::MOUSE + | ClientInfoFlags::MOUSE_HAS_WHEEL + | ClientInfoFlags::UNICODE | ClientInfoFlags::DISABLE_CTRL_ALT_DEL | ClientInfoFlags::LOGON_NOTIFY | ClientInfoFlags::LOGON_ERRORS | ClientInfoFlags::NO_AUDIO_PLAYBACK | ClientInfoFlags::VIDEO_DISABLE - | ClientInfoFlags::ENABLE_WINDOWS_KEY; + | ClientInfoFlags::ENABLE_WINDOWS_KEY + | ClientInfoFlags::MAXIMIZE_SHELL; if config.autologon { flags |= ClientInfoFlags::AUTOLOGON; diff --git a/crates/ironrdp-connector/src/connection_finalization.rs b/crates/ironrdp-connector/src/connection_finalization.rs index 2932bb8ba..e3a6483f3 100644 --- a/crates/ironrdp-connector/src/connection_finalization.rs +++ b/crates/ironrdp-connector/src/connection_finalization.rs @@ -160,34 +160,42 @@ impl Sequence for ConnectionFinalizationSequence { debug!("Server Synchronize"); ConnectionFinalizationState::WaitForResponse } - ShareDataPdu::Control(control_pdu) => match control_pdu.action { - finalization_messages::ControlAction::Cooperate => { - if control_pdu.grant_id == 0 && control_pdu.control_id == 0 { - debug!("Server Control (Cooperate)"); + ShareDataPdu::Control(control_pdu) => { + match control_pdu.action { + finalization_messages::ControlAction::Cooperate => { + if control_pdu.grant_id == 0 && control_pdu.control_id == 0 { + debug!("Server Control (Cooperate)"); + } else { + warn!( + control_pdu.grant_id, + control_pdu.control_id, + user_channel_id = self.user_channel_id, + "Server Control (Cooperate) has non-zero grant_id or control_id", + ); + } ConnectionFinalizationState::WaitForResponse - } else { - return Err(general_err!("invalid Control Cooperate PDU")); } - } - finalization_messages::ControlAction::GrantedControl => { - debug!( - control_pdu.grant_id, - control_pdu.control_id, - user_channel_id = self.user_channel_id, - SERVER_CHANNEL_ID - ); - - if control_pdu.grant_id == self.user_channel_id - && control_pdu.control_id == u32::from(SERVER_CHANNEL_ID) - { - debug!("Server Control (Granted Control)"); + finalization_messages::ControlAction::GrantedControl => { + debug!( + control_pdu.grant_id, + control_pdu.control_id, + user_channel_id = self.user_channel_id, + SERVER_CHANNEL_ID + ); + + if control_pdu.grant_id != self.user_channel_id { + warn!("Server Control (Granted Control) had invalid grant_id, expected {}, but got {}", self.user_channel_id, control_pdu.grant_id); + } + + if control_pdu.control_id != u32::from(SERVER_CHANNEL_ID) { + warn!("Server Control (Granted Control) had invalid control_id, expected {}, but got {}", SERVER_CHANNEL_ID, control_pdu.control_id); + } + ConnectionFinalizationState::WaitForResponse - } else { - return Err(general_err!("invalid Granted Control PDU")); } + _ => return Err(general_err!("unexpected control action")), } - _ => return Err(general_err!("unexpected control action")), - }, + } ShareDataPdu::ServerSetErrorInfo(server_error_info::ServerSetErrorInfoPdu(error_info)) => { match error_info { server_error_info::ErrorInfo::ProtocolIndependentCode( diff --git a/crates/ironrdp-connector/src/license_exchange.rs b/crates/ironrdp-connector/src/license_exchange.rs index b9e04e4d7..f8ee31a44 100644 --- a/crates/ironrdp-connector/src/license_exchange.rs +++ b/crates/ironrdp-connector/src/license_exchange.rs @@ -1,15 +1,13 @@ use core::fmt; use std::mem; -use ironrdp_pdu::rdp::server_license; +use ironrdp_pdu::rdp::server_license::{self, LicensePdu, ServerLicenseError}; use ironrdp_pdu::write_buf::WriteBuf; use ironrdp_pdu::PduHint; use rand_core::{OsRng, RngCore as _}; use super::legacy; -use crate::{ - encode_send_data_request, ConnectorError, ConnectorResult, ConnectorResultExt as _, Sequence, State, Written, -}; +use crate::{encode_send_data_request, ConnectorResult, ConnectorResultExt as _, Sequence, State, Written}; #[derive(Default, Debug)] #[non_exhaustive] @@ -98,14 +96,12 @@ impl Sequence for LicenseExchangeSequence { LicenseExchangeState::NewLicenseRequest => { let send_data_indication_ctx = legacy::decode_send_data_indication(input)?; - let initial_server_license = send_data_indication_ctx - .decode_user_data::() - .with_context("decode initial server license PDU")?; + let license_pdu = send_data_indication_ctx + .decode_user_data::() + .with_context("decode during LicenseExchangeState::NewLicenseRequest")?; - debug!(message = ?initial_server_license, "Received"); - - match initial_server_license.message_type { - server_license::InitialMessageType::LicenseRequest(license_request) => { + match license_pdu { + LicensePdu::ServerLicenseRequest(license_request) => { let mut client_random = [0u8; server_license::RANDOM_NUMBER_SIZE]; OsRng.fill_bytes(&mut client_random); @@ -123,10 +119,10 @@ impl Sequence for LicenseExchangeSequence { trace!(?encryption_data, "Successfully generated Client New License Request"); info!(message = ?new_license_request, "Send"); - let written = encode_send_data_request( + let written = encode_send_data_request::( send_data_indication_ctx.initiator_id, send_data_indication_ctx.channel_id, - &new_license_request, + &new_license_request.into(), output, )?; @@ -161,21 +157,33 @@ impl Sequence for LicenseExchangeSequence { } } } - server_license::InitialMessageType::StatusValidClient(_) => { + LicensePdu::LicensingErrorMessage(error_message) => { + if error_message.error_code != server_license::LicenseErrorCode::StatusValidClient { + return Err(custom_err!( + "LicensingErrorMessage", + ServerLicenseError::from(error_message) + )); + } info!("Server did not initiate license exchange"); (Written::Nothing, LicenseExchangeState::LicenseExchanged) } + _ => { + return Err(general_err!( + "unexpected PDU received during LicenseExchangeState::NewLicenseRequest" + )); + } } } LicenseExchangeState::PlatformChallenge { encryption_data } => { let send_data_indication_ctx = legacy::decode_send_data_indication(input)?; - match send_data_indication_ctx - .decode_user_data::() - .with_context("decode SERVER_PLATFORM_CHALLENGE") - { - Ok(challenge) => { + let license_pdu = send_data_indication_ctx + .decode_user_data::() + .with_context("decode during LicenseExchangeState::PlatformChallenge")?; + + match license_pdu { + LicensePdu::ServerPlatformChallenge(challenge) => { debug!(message = ?challenge, "Received"); let challenge_response = @@ -188,10 +196,10 @@ impl Sequence for LicenseExchangeSequence { debug!(message = ?challenge_response, "Send"); - let written = encode_send_data_request( + let written = encode_send_data_request::( send_data_indication_ctx.initiator_id, send_data_indication_ctx.channel_id, - &challenge_response, + &challenge_response.into(), output, )?; @@ -200,13 +208,21 @@ impl Sequence for LicenseExchangeSequence { LicenseExchangeState::UpgradeLicense { encryption_data }, ) } - Err(error) => { - // FIXME(#269): weird control flow pattern - downcast_if_status_valid_client(error, |licensing_error_message| { - debug!(message = ?licensing_error_message, "Received"); - info!("Client licensing completed"); - (Written::Nothing, LicenseExchangeState::LicenseExchanged) - })? + LicensePdu::LicensingErrorMessage(error_message) => { + if error_message.error_code != server_license::LicenseErrorCode::StatusValidClient { + return Err(custom_err!( + "LicensingErrorMessage", + ServerLicenseError::from(error_message) + )); + } + debug!(message = ?error_message, "Received"); + info!("Client licensing completed"); + (Written::Nothing, LicenseExchangeState::LicenseExchanged) + } + _ => { + return Err(general_err!( + "unexpected PDU received during LicenseExchangeState::PlatformChallenge" + )); } } } @@ -214,14 +230,12 @@ impl Sequence for LicenseExchangeSequence { LicenseExchangeState::UpgradeLicense { encryption_data } => { let send_data_indication_ctx = legacy::decode_send_data_indication(input)?; - // FIXME: The ServerUpgradeLicense type is handling both SERVER_UPGRADE_LICENSE and SERVER_NEW_LICENSE PDUs. - // It’s expected that fixing #263 will also lead to a better alternative here. + let license_pdu = send_data_indication_ctx + .decode_user_data::() + .with_context("decode during SERVER_NEW_LICENSE/LicenseExchangeState::UpgradeLicense")?; - match send_data_indication_ctx - .decode_user_data::() - .with_context("decode SERVER_NEW_LICENSE/SERVER_UPGRADE_LICENSE") - { - Ok(upgrade_license) => { + match license_pdu { + LicensePdu::ServerUpgradeLicense(upgrade_license) => { debug!(message = ?upgrade_license, "Received"); upgrade_license @@ -230,12 +244,21 @@ impl Sequence for LicenseExchangeSequence { debug!("License verified with success"); } - Err(error) => { - // FIXME(#269): weird control flow pattern - downcast_if_status_valid_client(error, |licensing_error_message| { - debug!(message = ?licensing_error_message, "Received"); - info!("Client licensing completed"); - })?; + LicensePdu::LicensingErrorMessage(error_message) => { + if error_message.error_code != server_license::LicenseErrorCode::StatusValidClient { + return Err(custom_err!( + "LicensingErrorMessage", + ServerLicenseError::from(error_message) + )); + } + + debug!(message = ?error_message, "Received"); + info!("Client licensing completed"); + } + _ => { + return Err(general_err!( + "unexpected PDU received during LicenseExchangeState::UpgradeLicense" + )); } } @@ -250,20 +273,3 @@ impl Sequence for LicenseExchangeSequence { Ok(written) } } - -// FIXME(#269): server_license::ServerLicenseError should not be retrieved from an error type. -fn downcast_if_status_valid_client(error: ConnectorError, op: Fn) -> ConnectorResult -where - Fn: FnOnce(&server_license::LicensingErrorMessage) -> T, -{ - match std::error::Error::source(&error) - .and_then(|source| source.downcast_ref::()) - { - Some(server_license::ServerLicenseError::ValidClientStatus(licensing_error_message)) - if licensing_error_message.error_code == server_license::LicenseErrorCode::StatusValidClient => - { - Ok(op(licensing_error_message)) - } - _ => Err(error), - } -} diff --git a/crates/ironrdp-fuzzing/src/oracles/mod.rs b/crates/ironrdp-fuzzing/src/oracles/mod.rs index 179e8ef5f..7acbe7876 100644 --- a/crates/ironrdp-fuzzing/src/oracles/mod.rs +++ b/crates/ironrdp-fuzzing/src/oracles/mod.rs @@ -35,11 +35,7 @@ pub fn pdu_decode(data: &[u8]) { let _ = decode::(data); let _ = decode::(data); - let _ = decode::(data); - let _ = decode::(data); - let _ = decode::(data); - let _ = decode::(data); - let _ = decode::(data); + let _ = decode::(data); let _ = decode::(data); diff --git a/crates/ironrdp-pdu/src/rdp/capability_sets.rs b/crates/ironrdp-pdu/src/rdp/capability_sets.rs index 699a302b4..c304525e4 100644 --- a/crates/ironrdp-pdu/src/rdp/capability_sets.rs +++ b/crates/ironrdp-pdu/src/rdp/capability_sets.rs @@ -227,6 +227,7 @@ impl<'de> PduDecode<'de> for DemandActive { let _padding = src.read_u16(); let mut capability_sets = Vec::with_capacity(capability_sets_count); + for _ in 0..capability_sets_count { capability_sets.push(CapabilitySet::decode(src)?); } @@ -267,12 +268,13 @@ pub enum CapabilitySet { BitmapCodecs(BitmapCodecs), // other + FrameAcknowledge(FrameAcknowledge), ColorCache(Vec), DrawNineGridCache(Vec), DrawGdiPlus(Vec), Rail(Vec), WindowList(Vec), - FrameAcknowledge(FrameAcknowledge), + BitmapCacheV3(Vec), } impl CapabilitySet { @@ -485,7 +487,8 @@ impl PduEncode for CapabilitySet { | CapabilitySet::DrawNineGridCache(buffer) | CapabilitySet::DrawGdiPlus(buffer) | CapabilitySet::Rail(buffer) - | CapabilitySet::WindowList(buffer) => buffer.len(), + | CapabilitySet::WindowList(buffer) + | CapabilitySet::BitmapCacheV3(buffer) => buffer.len(), } } } @@ -494,8 +497,13 @@ impl<'de> PduDecode<'de> for CapabilitySet { fn decode(src: &mut ReadCursor<'de>) -> PduResult { ensure_fixed_part_size!(in: src); - let capability_set_type = CapabilitySetType::from_u16(src.read_u16()) - .ok_or_else(|| invalid_message_err!("capabilitySetType", "invalid capability set type"))?; + let capability_set_type_raw = src.read_u16(); + let capability_set_type = CapabilitySetType::from_u16(capability_set_type_raw).ok_or_else(|| { + unsupported_pdu_err!( + "capabilitySetType", + format!("invalid capability set type: {}", capability_set_type_raw) + ) + })?; let length = src.read_u16() as usize; @@ -545,6 +553,7 @@ impl<'de> PduDecode<'de> for CapabilitySet { CapabilitySetType::Rail => Ok(CapabilitySet::Rail(capability_set_buffer.into())), CapabilitySetType::WindowList => Ok(CapabilitySet::WindowList(capability_set_buffer.into())), CapabilitySetType::FrameAcknowledge => Ok(CapabilitySet::FrameAcknowledge(decode(capability_set_buffer)?)), + CapabilitySetType::BitmapCacheV3CodecID => Ok(CapabilitySet::BitmapCacheV3(capability_set_buffer.into())), } } } @@ -556,6 +565,7 @@ enum CapabilitySetType { Order = 0x03, BitmapCache = 0x04, Control = 0x05, + BitmapCacheV3CodecID = 0x06, WindowActivation = 0x07, Pointer = 0x08, Share = 0x09, diff --git a/crates/ironrdp-pdu/src/rdp/capability_sets/bitmap.rs b/crates/ironrdp-pdu/src/rdp/capability_sets/bitmap.rs index 5d078cb65..ac7c7ab4d 100644 --- a/crates/ironrdp-pdu/src/rdp/capability_sets/bitmap.rs +++ b/crates/ironrdp-pdu/src/rdp/capability_sets/bitmap.rs @@ -88,13 +88,11 @@ impl<'de> PduDecode<'de> for Bitmap { let _high_color_flags = src.read_u8(); let drawing_flags = BitmapDrawingFlags::from_bits_truncate(src.read_u8()); - let is_multiple_rect_supported = src.read_u16() != 0; - if !is_multiple_rect_supported { - return Err(invalid_message_err!( - "isMultipleRectSupported", - "invalid multiple rect support" - )); - } + // According to the spec: + // "This field MUST be set to TRUE (0x0001) because multiple rectangle support is required for a connection to proceed." + // however like FreeRDP, we will ignore this field. + // https://github.com/FreeRDP/FreeRDP/blob/ba8cf8cf2158018fb7abbedb51ab245f369be813/libfreerdp/core/capabilities.c#L391 + let _ = src.read_u16(); read_padding!(src, 2); diff --git a/crates/ironrdp-pdu/src/rdp/headers.rs b/crates/ironrdp-pdu/src/rdp/headers.rs index 0ed869d81..1ee105f97 100644 --- a/crates/ironrdp-pdu/src/rdp/headers.rs +++ b/crates/ironrdp-pdu/src/rdp/headers.rs @@ -322,6 +322,18 @@ pub enum ShareDataPdu { ShutdownDenied, SuppressOutput(SuppressOutputPdu), RefreshRectangle(RefreshRectanglePdu), + Update(Vec), + Pointer(Vec), + PlaySound(Vec), + SetKeyboardIndicators(Vec), + BitmapCachePersistentList(Vec), + BitmapCacheErrorPdu(Vec), + SetKeyboardImeStatus(Vec), + OffscreenCacheErrorPdu(Vec), + DrawNineGridErrorPdu(Vec), + DrawGdiPusErrorPdu(Vec), + ArcStatusPdu(Vec), + StatusInfoPdu(Vec), } impl ShareDataPdu { @@ -342,6 +354,18 @@ impl ShareDataPdu { ShareDataPdu::ShutdownDenied => "Shutdown Denied PDU", ShareDataPdu::SuppressOutput(_) => "Suppress Output PDU", ShareDataPdu::RefreshRectangle(_) => "Refresh Rectangle PDU", + ShareDataPdu::Update(_) => "Update PDU", + ShareDataPdu::Pointer(_) => "Pointer PDU", + ShareDataPdu::PlaySound(_) => "Play Sound PDU", + ShareDataPdu::SetKeyboardIndicators(_) => "Set Keyboard Indicators PDU", + ShareDataPdu::BitmapCachePersistentList(_) => "Bitmap Cache Persistent List PDU", + ShareDataPdu::BitmapCacheErrorPdu(_) => "Bitmap Cache Error PDU", + ShareDataPdu::SetKeyboardImeStatus(_) => "Set Keyboard IME Status PDU", + ShareDataPdu::OffscreenCacheErrorPdu(_) => "Offscreen Cache Error PDU", + ShareDataPdu::DrawNineGridErrorPdu(_) => "Draw Nine Grid Error PDU", + ShareDataPdu::DrawGdiPusErrorPdu(_) => "Draw GDI PUS Error PDU", + ShareDataPdu::ArcStatusPdu(_) => "Arc Status PDU", + ShareDataPdu::StatusInfoPdu(_) => "Status Info PDU", } } @@ -360,6 +384,18 @@ impl ShareDataPdu { ShareDataPdu::ShutdownDenied => ShareDataPduType::ShutdownDenied, ShareDataPdu::SuppressOutput(_) => ShareDataPduType::SuppressOutput, ShareDataPdu::RefreshRectangle(_) => ShareDataPduType::RefreshRectangle, + ShareDataPdu::Update(_) => ShareDataPduType::Update, + ShareDataPdu::Pointer(_) => ShareDataPduType::Pointer, + ShareDataPdu::PlaySound(_) => ShareDataPduType::PlaySound, + ShareDataPdu::SetKeyboardIndicators(_) => ShareDataPduType::SetKeyboardIndicators, + ShareDataPdu::BitmapCachePersistentList(_) => ShareDataPduType::BitmapCachePersistentList, + ShareDataPdu::BitmapCacheErrorPdu(_) => ShareDataPduType::BitmapCacheErrorPdu, + ShareDataPdu::SetKeyboardImeStatus(_) => ShareDataPduType::SetKeyboardImeStatus, + ShareDataPdu::OffscreenCacheErrorPdu(_) => ShareDataPduType::OffscreenCacheErrorPdu, + ShareDataPdu::DrawNineGridErrorPdu(_) => ShareDataPduType::DrawNineGridErrorPdu, + ShareDataPdu::DrawGdiPusErrorPdu(_) => ShareDataPduType::DrawGdiPusErrorPdu, + ShareDataPdu::ArcStatusPdu(_) => ShareDataPduType::ArcStatusPdu, + ShareDataPdu::StatusInfoPdu(_) => ShareDataPduType::StatusInfoPdu, } } @@ -382,18 +418,24 @@ impl ShareDataPdu { ShareDataPduType::ShutdownDenied => Ok(ShareDataPdu::ShutdownDenied), ShareDataPduType::SuppressOutput => Ok(ShareDataPdu::SuppressOutput(SuppressOutputPdu::decode(src)?)), ShareDataPduType::RefreshRectangle => Ok(ShareDataPdu::RefreshRectangle(RefreshRectanglePdu::decode(src)?)), - ShareDataPduType::Update - | ShareDataPduType::Pointer - | ShareDataPduType::PlaySound - | ShareDataPduType::SetKeyboardIndicators - | ShareDataPduType::BitmapCachePersistentList - | ShareDataPduType::BitmapCacheErrorPdu - | ShareDataPduType::SetKeyboardImeStatus - | ShareDataPduType::OffscreenCacheErrorPdu - | ShareDataPduType::DrawNineGridErrorPdu - | ShareDataPduType::DrawGdiPusErrorPdu - | ShareDataPduType::ArcStatusPdu - | ShareDataPduType::StatusInfoPdu => Err(other_err!("unsupported share data PDU")), + ShareDataPduType::Update => Ok(ShareDataPdu::Update(src.remaining().to_vec())), + ShareDataPduType::Pointer => Ok(ShareDataPdu::Pointer(src.remaining().to_vec())), + ShareDataPduType::PlaySound => Ok(ShareDataPdu::PlaySound(src.remaining().to_vec())), + ShareDataPduType::SetKeyboardIndicators => { + Ok(ShareDataPdu::SetKeyboardIndicators(src.remaining().to_vec())) + } + ShareDataPduType::BitmapCachePersistentList => { + Ok(ShareDataPdu::BitmapCachePersistentList(src.remaining().to_vec())) + } + ShareDataPduType::BitmapCacheErrorPdu => Ok(ShareDataPdu::BitmapCacheErrorPdu(src.remaining().to_vec())), + ShareDataPduType::SetKeyboardImeStatus => Ok(ShareDataPdu::SetKeyboardImeStatus(src.remaining().to_vec())), + ShareDataPduType::OffscreenCacheErrorPdu => { + Ok(ShareDataPdu::OffscreenCacheErrorPdu(src.remaining().to_vec())) + } + ShareDataPduType::DrawNineGridErrorPdu => Ok(ShareDataPdu::DrawNineGridErrorPdu(src.remaining().to_vec())), + ShareDataPduType::DrawGdiPusErrorPdu => Ok(ShareDataPdu::DrawGdiPusErrorPdu(src.remaining().to_vec())), + ShareDataPduType::ArcStatusPdu => Ok(ShareDataPdu::ArcStatusPdu(src.remaining().to_vec())), + ShareDataPduType::StatusInfoPdu => Ok(ShareDataPdu::StatusInfoPdu(src.remaining().to_vec())), } } } @@ -412,6 +454,7 @@ impl PduEncode for ShareDataPdu { ShareDataPdu::ShutdownRequest | ShareDataPdu::ShutdownDenied => Ok(()), ShareDataPdu::SuppressOutput(pdu) => pdu.encode(dst), ShareDataPdu::RefreshRectangle(pdu) => pdu.encode(dst), + _ => Err(other_err!("Encoding not implemented")), } } @@ -432,6 +475,18 @@ impl PduEncode for ShareDataPdu { ShareDataPdu::ShutdownRequest | ShareDataPdu::ShutdownDenied => 0, ShareDataPdu::SuppressOutput(pdu) => pdu.size(), ShareDataPdu::RefreshRectangle(pdu) => pdu.size(), + ShareDataPdu::Update(buffer) + | ShareDataPdu::Pointer(buffer) + | ShareDataPdu::PlaySound(buffer) + | ShareDataPdu::SetKeyboardIndicators(buffer) + | ShareDataPdu::BitmapCachePersistentList(buffer) + | ShareDataPdu::BitmapCacheErrorPdu(buffer) + | ShareDataPdu::SetKeyboardImeStatus(buffer) + | ShareDataPdu::OffscreenCacheErrorPdu(buffer) + | ShareDataPdu::DrawNineGridErrorPdu(buffer) + | ShareDataPdu::DrawGdiPusErrorPdu(buffer) + | ShareDataPdu::ArcStatusPdu(buffer) + | ShareDataPdu::StatusInfoPdu(buffer) => buffer.len(), } } } diff --git a/crates/ironrdp-pdu/src/rdp/server_license.rs b/crates/ironrdp-pdu/src/rdp/server_license.rs index c309d2031..c3863749b 100644 --- a/crates/ironrdp-pdu/src/rdp/server_license.rs +++ b/crates/ironrdp-pdu/src/rdp/server_license.rs @@ -23,9 +23,7 @@ mod server_upgrade_license; pub use self::client_new_license_request::{ClientNewLicenseRequest, PLATFORM_ID}; pub use self::client_platform_challenge_response::ClientPlatformChallengeResponse; pub use self::licensing_error_message::{LicenseErrorCode, LicensingErrorMessage, LicensingStateTransition}; -pub use self::server_license_request::{ - cert, InitialMessageType, InitialServerLicenseMessage, ProductInfo, Scope, ServerCertificate, ServerLicenseRequest, -}; +pub use self::server_license_request::{cert, ProductInfo, Scope, ServerCertificate, ServerLicenseRequest}; pub use self::server_platform_challenge::ServerPlatformChallenge; pub use self::server_upgrade_license::{NewLicenseInformation, ServerUpgradeLicense}; @@ -155,20 +153,22 @@ pub enum PreambleVersion { V3 = 3, // RDP 5.0, 5.1, 5.2, 6.0, 6.1, 7.0, 7.1, 8.0, 8.1, 10.0, 10.1, 10.2, 10.3, 10.4, and 10.5 } -#[derive(Debug, PartialEq, Eq, FromPrimitive, ToPrimitive)] -pub enum BlobType { - Any = 0x00, - Data = 0x01, - Random = 0x02, - Certificate = 0x03, - Error = 0x04, - RsaKey = 0x06, - EncryptedData = 0x09, - RsaSignature = 0x08, - KeyExchangeAlgorithm = 0x0d, - Scope = 0x0e, - ClientUserName = 0x0f, - ClientMachineNameBlob = 0x10, +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct BlobType(u16); + +impl BlobType { + pub const ANY: Self = Self(0x00); + pub const DATA: Self = Self(0x01); + pub const RANDOM: Self = Self(0x02); + pub const CERTIFICATE: Self = Self(0x03); + pub const ERROR: Self = Self(0x04); + pub const RSA_KEY: Self = Self(0x06); + pub const ENCRYPTED_DATA: Self = Self(0x09); + pub const RSA_SIGNATURE: Self = Self(0x08); + pub const KEY_EXCHANGE_ALGORITHM: Self = Self(0x0d); + pub const SCOPE: Self = Self(0x0e); + pub const CLIENT_USER_NAME: Self = Self(0x0f); + pub const CLIENT_MACHINE_NAME_BLOB: Self = Self(0x10); } #[derive(Debug, Error)] @@ -256,6 +256,12 @@ impl From for ServerLicenseError { } } +impl From for ServerLicenseError { + fn from(e: LicensingErrorMessage) -> Self { + Self::UnexpectedError(e) + } +} + #[cfg(feature = "std")] impl ironrdp_error::legacy::ErrorContext for ServerLicenseError { fn context(&self) -> &'static str { @@ -263,6 +269,7 @@ impl ironrdp_error::legacy::ErrorContext for ServerLicenseError { } } +#[derive(Debug, PartialEq)] pub struct BlobHeader { pub blob_type: BlobType, pub length: usize, @@ -282,7 +289,7 @@ impl PduEncode for BlobHeader { fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> { ensure_fixed_part_size!(in: dst); - dst.write_u16(self.blob_type.to_u16().unwrap()); + dst.write_u16(self.blob_type.0); dst.write_u16(cast_length!("len", self.length)?); Ok(()) @@ -301,10 +308,7 @@ impl<'de> PduDecode<'de> for BlobHeader { fn decode(src: &mut ReadCursor<'de>) -> PduResult { ensure_fixed_part_size!(in: src); - let blob_type = src.read_u16(); - let blob_type = - BlobType::from_u16(blob_type).ok_or_else(|| invalid_message_err!("blobType", "invalid blob type"))?; - + let blob_type = BlobType(src.read_u16()); let length = cast_length!("len", src.read_u16())?; Ok(Self { blob_type, length }) @@ -336,38 +340,106 @@ fn compute_mac_data(mac_salt_key: &[u8], data: &[u8]) -> Vec { md5.finalize().to_vec() } -fn read_license_header( - required_preamble_message_type: PreambleType, - src: &mut ReadCursor<'_>, -) -> Result { - let license_header = LicenseHeader::decode(src)?; - - // FIXME(#269): ERROR_ALERT licensing packets should not be returned as error by the parser. - // Such packets should be handled by the caller, and the caller is responsible for turning - // those into "Result::Err" if necessary. It should be possible to decode a `LICENSE_ERROR_MESSAGE` - // structure like any other PDU. - // Otherwise it requires the caller to match on the error kind in order to check for variants that are - // not actual errors, it makes the flow of control harder to write correctly and less obvious. - // See `ConnectionConfirm` from the `nego` module for prior art. - - if license_header.preamble_message_type != required_preamble_message_type { - if license_header.preamble_message_type == PreambleType::ErrorAlert { - let license_error = LicensingErrorMessage::decode(src)?; - - if license_error.error_code == LicenseErrorCode::StatusValidClient - && license_error.state_transition == LicensingStateTransition::NoTransition - { - return Err(invalid_message_err!( - "preambleType", - "the server has returned STATUS_VALID_CLIENT (not an error)" - )); - } else { - return Err(invalid_message_err!("preambleType", "invalid preamble type")); +#[derive(Debug, PartialEq)] +pub enum LicensePdu { + ClientNewLicenseRequest(ClientNewLicenseRequest), + ClientPlatformChallengeResponse(ClientPlatformChallengeResponse), + ServerLicenseRequest(ServerLicenseRequest), + ServerPlatformChallenge(ServerPlatformChallenge), + ServerUpgradeLicense(ServerUpgradeLicense), + LicensingErrorMessage(LicensingErrorMessage), +} + +impl<'de> PduDecode<'de> for LicensePdu { + fn decode(src: &mut ReadCursor<'de>) -> PduResult { + let license_header = LicenseHeader::decode(src)?; + + match license_header.preamble_message_type { + PreambleType::LicenseRequest => Ok(ServerLicenseRequest::decode(license_header, src)?.into()), + PreambleType::PlatformChallenge => Ok(ServerPlatformChallenge::decode(license_header, src)?.into()), + PreambleType::NewLicense | PreambleType::UpgradeLicense => { + Ok(ServerUpgradeLicense::decode(license_header, src)?.into()) + } + PreambleType::LicenseInfo => Err(unsupported_pdu_err!( + "LicensePdu::LicenseInfo", + "LicenseInfo is not supported".to_owned() + )), + PreambleType::NewLicenseRequest => Ok(ClientNewLicenseRequest::decode(license_header, src)?.into()), + PreambleType::PlatformChallengeResponse => { + Ok(ClientPlatformChallengeResponse::decode(license_header, src)?.into()) } - } else { - return Err(invalid_message_err!("preambleType", "got unexptected preamble type")); + PreambleType::ErrorAlert => Ok(LicensingErrorMessage::decode(license_header, src)?.into()), + } + } +} + +impl PduEncode for LicensePdu { + fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> { + match self { + Self::ClientNewLicenseRequest(ref pdu) => pdu.encode(dst), + Self::ClientPlatformChallengeResponse(ref pdu) => pdu.encode(dst), + Self::ServerLicenseRequest(ref pdu) => pdu.encode(dst), + Self::ServerPlatformChallenge(ref pdu) => pdu.encode(dst), + Self::ServerUpgradeLicense(ref pdu) => pdu.encode(dst), + Self::LicensingErrorMessage(ref pdu) => pdu.encode(dst), + } + } + + fn name(&self) -> &'static str { + match self { + Self::ClientNewLicenseRequest(pdu) => pdu.name(), + Self::ClientPlatformChallengeResponse(pdu) => pdu.name(), + Self::ServerLicenseRequest(pdu) => pdu.name(), + Self::ServerPlatformChallenge(pdu) => pdu.name(), + Self::ServerUpgradeLicense(pdu) => pdu.name(), + Self::LicensingErrorMessage(pdu) => pdu.name(), + } + } + + fn size(&self) -> usize { + match self { + Self::ClientNewLicenseRequest(pdu) => pdu.size(), + Self::ClientPlatformChallengeResponse(pdu) => pdu.size(), + Self::ServerLicenseRequest(pdu) => pdu.size(), + Self::ServerPlatformChallenge(pdu) => pdu.size(), + Self::ServerUpgradeLicense(pdu) => pdu.size(), + Self::LicensingErrorMessage(pdu) => pdu.size(), } } +} + +impl From for LicensePdu { + fn from(pdu: ClientNewLicenseRequest) -> Self { + Self::ClientNewLicenseRequest(pdu) + } +} + +impl From for LicensePdu { + fn from(pdu: ClientPlatformChallengeResponse) -> Self { + Self::ClientPlatformChallengeResponse(pdu) + } +} + +impl From for LicensePdu { + fn from(pdu: ServerLicenseRequest) -> Self { + Self::ServerLicenseRequest(pdu) + } +} + +impl From for LicensePdu { + fn from(pdu: ServerPlatformChallenge) -> Self { + Self::ServerPlatformChallenge(pdu) + } +} - Ok(license_header) +impl From for LicensePdu { + fn from(pdu: ServerUpgradeLicense) -> Self { + Self::ServerUpgradeLicense(pdu) + } +} + +impl From for LicensePdu { + fn from(pdu: LicensingErrorMessage) -> Self { + Self::LicensingErrorMessage(pdu) + } } diff --git a/crates/ironrdp-pdu/src/rdp/server_license/client_new_license_request.rs b/crates/ironrdp-pdu/src/rdp/server_license/client_new_license_request.rs index 9a3c5baf9..a4ce2af3f 100644 --- a/crates/ironrdp-pdu/src/rdp/server_license/client_new_license_request.rs +++ b/crates/ironrdp-pdu/src/rdp/server_license/client_new_license_request.rs @@ -124,8 +124,8 @@ impl ClientNewLicenseRequest { } } -impl PduEncode for ClientNewLicenseRequest { - fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> { +impl ClientNewLicenseRequest { + pub fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> { ensure_size!(in: dst, size: self.size()); self.license_header.encode(dst)?; @@ -134,18 +134,18 @@ impl PduEncode for ClientNewLicenseRequest { dst.write_u32(PLATFORM_ID); dst.write_slice(&self.client_random); - BlobHeader::new(BlobType::Random, self.encrypted_premaster_secret.len()).encode(dst)?; + BlobHeader::new(BlobType::RANDOM, self.encrypted_premaster_secret.len()).encode(dst)?; dst.write_slice(&self.encrypted_premaster_secret); BlobHeader::new( - BlobType::ClientUserName, + BlobType::CLIENT_USER_NAME, self.client_username.len() + UTF8_NULL_TERMINATOR_SIZE, ) .encode(dst)?; utils::write_string_to_cursor(dst, &self.client_username, CharacterSet::Ansi, true)?; BlobHeader::new( - BlobType::ClientMachineNameBlob, + BlobType::CLIENT_MACHINE_NAME_BLOB, self.client_machine_name.len() + UTF8_NULL_TERMINATOR_SIZE, ) .encode(dst)?; @@ -154,11 +154,11 @@ impl PduEncode for ClientNewLicenseRequest { Ok(()) } - fn name(&self) -> &'static str { + pub fn name(&self) -> &'static str { Self::NAME } - fn size(&self) -> usize { + pub fn size(&self) -> usize { self.license_header.size() + LICENSE_REQUEST_STATIC_FIELDS_SIZE + RANDOM_NUMBER_SIZE @@ -170,9 +170,8 @@ impl PduEncode for ClientNewLicenseRequest { } } -impl<'de> PduDecode<'de> for ClientNewLicenseRequest { - fn decode(src: &mut ReadCursor<'de>) -> PduResult { - let license_header = LicenseHeader::decode(src)?; +impl ClientNewLicenseRequest { + pub fn decode(license_header: LicenseHeader, src: &mut ReadCursor<'_>) -> PduResult { if license_header.preamble_message_type != PreambleType::NewLicenseRequest { return Err(invalid_message_err!("preambleMessageType", "unexpected preamble type")); } @@ -190,14 +189,14 @@ impl<'de> PduDecode<'de> for ClientNewLicenseRequest { let client_random = src.read_slice(RANDOM_NUMBER_SIZE).into(); let premaster_secret_blob_header = BlobHeader::decode(src)?; - if premaster_secret_blob_header.blob_type != BlobType::Random { + if premaster_secret_blob_header.blob_type != BlobType::RANDOM { return Err(invalid_message_err!("blobType", "invalid blob type")); } ensure_size!(in: src, size: premaster_secret_blob_header.length); let encrypted_premaster_secret = src.read_slice(premaster_secret_blob_header.length).into(); let username_blob_header = BlobHeader::decode(src)?; - if username_blob_header.blob_type != BlobType::ClientUserName { + if username_blob_header.blob_type != BlobType::CLIENT_USER_NAME { return Err(invalid_message_err!("blobType", "invalid blob type")); } ensure_size!(in: src, size: username_blob_header.length); @@ -205,7 +204,7 @@ impl<'de> PduDecode<'de> for ClientNewLicenseRequest { utils::decode_string(src.read_slice(username_blob_header.length), CharacterSet::Ansi, false)?; let machine_name_blob = BlobHeader::decode(src)?; - if machine_name_blob.blob_type != BlobType::ClientMachineNameBlob { + if machine_name_blob.blob_type != BlobType::CLIENT_MACHINE_NAME_BLOB { return Err(invalid_message_err!("blobType", "invalid blob type")); } ensure_size!(in: src, size: machine_name_blob.length); diff --git a/crates/ironrdp-pdu/src/rdp/server_license/client_new_license_request/tests.rs b/crates/ironrdp-pdu/src/rdp/server_license/client_new_license_request/tests.rs index f5c85e3da..8820fab72 100644 --- a/crates/ironrdp-pdu/src/rdp/server_license/client_new_license_request/tests.rs +++ b/crates/ironrdp-pdu/src/rdp/server_license/client_new_license_request/tests.rs @@ -4,7 +4,7 @@ use lazy_static::lazy_static; use super::*; use crate::rdp::server_license::server_license_request::cert::{CertificateType, X509CertificateChain}; use crate::rdp::server_license::server_license_request::{ProductInfo, Scope, ServerCertificate}; -use crate::rdp::server_license::PREAMBLE_SIZE; +use crate::rdp::server_license::{LicensePdu, PREAMBLE_SIZE}; use crate::{decode, encode_vec}; const LICENSE_HEADER_BUFFER_NO_SIZE: [u8; 6] = [ @@ -60,7 +60,7 @@ const CLIENT_USERNAME: &str = "sample-user"; const CLIENT_MACHINE_NAME: &str = "sample-machine-name"; lazy_static! { - pub static ref CLIENT_NEW_LICENSE_REQUEST: ClientNewLicenseRequest = ClientNewLicenseRequest { + pub static ref CLIENT_NEW_LICENSE_REQUEST: LicensePdu = ClientNewLicenseRequest { license_header: LicenseHeader { security_header: BasicSecurityHeader { flags: BasicSecurityHeaderFlags::LICENSE_PKT, @@ -81,7 +81,7 @@ lazy_static! { encrypted_premaster_secret: Vec::from(ENCRYPTED_PREMASTER_SECRET.as_ref()), client_username: CLIENT_USERNAME.to_string(), client_machine_name: CLIENT_MACHINE_NAME.to_string(), - }; + }.into(); pub static ref REQUEST_BUFFER: Vec = { let username_len = CLIENT_USERNAME.len() + UTF8_NULL_TERMINATOR_SIZE; @@ -119,146 +119,159 @@ lazy_static! { .concat() }; - pub(crate) static ref SERVER_LICENSE_REQUEST: ServerLicenseRequest = ServerLicenseRequest { - server_random: Vec::from(SERVER_RANDOM_BUFFER.as_ref()), - product_info: ProductInfo { - version: 0x60000, - company_name: "Microsoft Corporation".to_string(), - product_id: "A02".to_string(), - }, - server_certificate: Some(ServerCertificate { - issued_permanently: true, - certificate: CertificateType::X509(X509CertificateChain { - certificate_array: vec![ - vec![0x30, 0x82, 0x03, 0xda, 0x30, 0x82, 0x02, 0xc2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x7f, - 0x00, 0x00, 0x01, 0x76, 0x00, 0x8f, 0x08, 0x64, 0x08, 0x68, 0xa7, 0x63, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x76, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, - 0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x50, 0x72, 0x6f, 0x64, 0x32, - 0x4c, 0x53, 0x52, 0x41, 0x73, 0x68, 0x61, 0x32, 0x52, 0x44, 0x53, 0x4c, 0x4d, 0x30, 0x1e, 0x17, 0x0d, - 0x31, 0x39, 0x31, 0x30, 0x32, 0x36, 0x32, 0x32, 0x35, 0x33, 0x34, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x37, - 0x30, 0x36, 0x30, 0x36, 0x32, 0x30, 0x34, 0x32, 0x33, 0x38, 0x5a, 0x30, 0x11, 0x31, 0x0f, 0x30, 0x0d, - 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x06, 0x42, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x30, 0x82, 0x01, 0x22, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, - 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa8, 0x6b, 0xda, 0xae, 0x08, - 0x1d, 0xc5, 0x05, 0x70, 0x7d, 0xa0, 0x41, 0x46, 0xb4, 0x14, 0xcf, 0xfb, 0x8e, 0x09, 0x0b, 0x0a, 0x52, - 0x8a, 0x7f, 0x7a, 0x35, 0xb6, 0xe3, 0x0d, 0x1c, 0xbe, 0x49, 0x63, 0x41, 0x92, 0x86, 0x00, 0xa2, 0xd3, - 0xff, 0x5b, 0x08, 0x7d, 0x2b, 0x65, 0xe4, 0xc3, 0x09, 0x68, 0x72, 0x21, 0xc4, 0xd8, 0x0a, 0x21, 0x9e, - 0x1f, 0xdf, 0xb2, 0xaa, 0x2b, 0x42, 0x68, 0xe7, 0xeb, 0x52, 0xf8, 0x9e, 0xfc, 0x7f, 0x0f, 0x55, 0x26, - 0x7d, 0x44, 0xfb, 0x35, 0xe5, 0xc2, 0x2c, 0xb6, 0x8d, 0x06, 0xc5, 0xdc, 0xbf, 0x66, 0xf6, 0xb2, 0xf2, - 0x9b, 0xe2, 0x49, 0xaf, 0xfd, 0x4c, 0x69, 0x46, 0x72, 0xe0, 0x2f, 0x31, 0x77, 0x86, 0x7b, 0x5b, 0x6d, - 0x49, 0xe6, 0xc7, 0x84, 0xd1, 0xdd, 0x56, 0x89, 0x8d, 0xbd, 0x07, 0x18, 0x01, 0x43, 0x70, 0x9b, 0x00, - 0x71, 0x16, 0x89, 0x66, 0x2e, 0xb6, 0x5f, 0x62, 0xeb, 0x96, 0xed, 0xf2, 0xdb, 0xdb, 0xcf, 0xdd, 0xa8, - 0xab, 0xde, 0x93, 0xb3, 0xdb, 0x54, 0xf0, 0x34, 0x4a, 0x28, 0xc3, 0x11, 0xf6, 0xb9, 0xd6, 0x45, 0x3f, - 0x07, 0xc0, 0x8e, 0x10, 0x7a, 0x2b, 0x56, 0x15, 0xbb, 0x00, 0x9d, 0x82, 0x27, 0xf2, 0x11, 0xa3, 0xda, - 0x03, 0xaa, 0x51, 0xc0, 0xfd, 0x90, 0xc8, 0x73, 0x81, 0xce, 0x97, 0x30, 0xa2, 0x54, 0x63, 0x6f, 0xfc, - 0x7f, 0x5b, 0x71, 0xec, 0x11, 0xb0, 0xa0, 0xc8, 0x74, 0x3a, 0xcc, 0x1b, 0x5e, 0xcd, 0x91, 0xa8, 0x18, - 0x92, 0xeb, 0x33, 0xc4, 0x6d, 0xb8, 0x16, 0x67, 0xe1, 0xc5, 0xa6, 0x26, 0x35, 0x48, 0xc4, 0xe7, 0x94, - 0xeb, 0xbb, 0xb8, 0xde, 0xd3, 0xe1, 0xc0, 0xcb, 0x00, 0x20, 0xf6, 0xbc, 0xa9, 0xc5, 0x70, 0xc4, 0xda, - 0x1b, 0x61, 0x0b, 0x9f, 0x0b, 0x19, 0x93, 0xaf, 0x8f, 0x40, 0xbb, 0x26, 0x79, 0x02, 0x03, 0x01, 0x00, - 0x01, 0xa3, 0x82, 0x01, 0x1d, 0x30, 0x82, 0x01, 0x19, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, - 0x16, 0x04, 0x14, 0xa3, 0xda, 0xe5, 0xef, 0xc3, 0x1c, 0x7a, 0xcf, 0x34, 0x2b, 0xa2, 0x42, 0x2b, 0x77, - 0xcb, 0x62, 0xfb, 0x4c, 0x28, 0x51, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, - 0x80, 0x14, 0x9c, 0xe1, 0xad, 0x8f, 0xd4, 0x86, 0xd2, 0x1c, 0x7e, 0x48, 0x32, 0xf2, 0x28, 0xfe, 0x87, - 0x90, 0xe3, 0xb1, 0xc5, 0x8e, 0x30, 0x4a, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x43, 0x30, 0x41, 0x30, - 0x3f, 0xa0, 0x3d, 0xa0, 0x3b, 0x86, 0x39, 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x2f, 0x2f, 0x2f, 0x2f, 0x52, - 0x44, 0x32, 0x38, 0x31, 0x38, 0x37, 0x38, 0x30, 0x45, 0x33, 0x45, 0x45, 0x43, 0x2f, 0x43, 0x65, 0x72, - 0x74, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x50, 0x72, 0x6f, 0x64, 0x32, 0x4c, 0x53, 0x52, 0x41, - 0x73, 0x68, 0x61, 0x32, 0x52, 0x44, 0x53, 0x4c, 0x4d, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x64, 0x06, 0x08, - 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x58, 0x30, 0x56, 0x30, 0x54, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x48, 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x2f, 0x2f, 0x2f, - 0x2f, 0x52, 0x44, 0x32, 0x38, 0x31, 0x38, 0x37, 0x38, 0x30, 0x45, 0x33, 0x45, 0x45, 0x43, 0x2f, 0x43, - 0x65, 0x72, 0x74, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x52, 0x44, 0x32, 0x38, 0x31, 0x38, 0x37, - 0x38, 0x30, 0x45, 0x33, 0x45, 0x45, 0x43, 0x5f, 0x50, 0x72, 0x6f, 0x64, 0x32, 0x4c, 0x53, 0x52, 0x41, - 0x73, 0x68, 0x61, 0x32, 0x52, 0x44, 0x53, 0x4c, 0x4d, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x0c, 0x06, 0x03, - 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x17, 0x06, 0x08, 0x2b, 0x06, 0x01, - 0x04, 0x01, 0x82, 0x37, 0x12, 0x04, 0x0b, 0x16, 0x09, 0x54, 0x4c, 0x53, 0x7e, 0x42, 0x41, 0x53, 0x49, - 0x43, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, - 0x82, 0x01, 0x01, 0x00, 0x55, 0xd5, 0x94, 0x3b, 0x06, 0xef, 0xf2, 0xb0, 0xf9, 0xd7, 0x36, 0x2a, 0x36, - 0xe0, 0xf1, 0xd9, 0x18, 0xc1, 0x89, 0x7e, 0xa2, 0xcf, 0x01, 0x6f, 0x22, 0x7b, 0x34, 0x81, 0xf0, 0x7a, - 0x45, 0x11, 0x6e, 0x75, 0x4b, 0x0b, 0xa8, 0xcd, 0x92, 0x57, 0x19, 0x80, 0xb7, 0x6e, 0x1a, 0x4d, 0x12, - 0x65, 0x91, 0x56, 0x38, 0x17, 0x22, 0xa2, 0x75, 0xae, 0xf9, 0x12, 0x75, 0x38, 0xf3, 0x19, 0x74, 0xea, - 0x87, 0x46, 0x1f, 0x98, 0x2c, 0x2f, 0xf9, 0xfc, 0xb4, 0xdc, 0x25, 0xa0, 0xd3, 0x34, 0x1b, 0xbc, 0x21, - 0xbb, 0x3d, 0x82, 0xad, 0x15, 0xc6, 0x3d, 0x02, 0x75, 0x33, 0x70, 0x25, 0x0a, 0x1a, 0xf7, 0x4c, 0xcb, - 0x84, 0xa3, 0xc1, 0x78, 0xe6, 0xf5, 0xa1, 0x44, 0x54, 0xc8, 0x34, 0xfd, 0xef, 0xbf, 0x86, 0x81, 0x9d, - 0x9a, 0x7e, 0xb6, 0xad, 0x71, 0x7e, 0xe4, 0xd9, 0x71, 0x6c, 0xb9, 0xe7, 0xf2, 0xd6, 0xd7, 0xbb, 0x66, - 0x5a, 0x30, 0xf5, 0x29, 0xae, 0x02, 0x39, 0x3d, 0xea, 0x7a, 0x79, 0x1b, 0x53, 0xc5, 0xbe, 0x8d, 0xfb, - 0xe2, 0xe4, 0x8e, 0xc2, 0x04, 0xb3, 0x0a, 0x94, 0x75, 0xa3, 0xbf, 0xd4, 0x87, 0xd2, 0x74, 0x15, 0x05, - 0x5e, 0xd5, 0x8f, 0x94, 0x23, 0x41, 0x13, 0x3f, 0xbd, 0xed, 0x21, 0x55, 0x96, 0xe9, 0xc4, 0x93, 0x34, - 0x7f, 0xaa, 0xea, 0xe7, 0xb1, 0x9a, 0xca, 0x25, 0x91, 0x18, 0xdf, 0x28, 0x05, 0x8e, 0x53, 0xb3, 0x8c, - 0x8d, 0xcc, 0xf3, 0xf4, 0x78, 0x76, 0x76, 0x7b, 0x82, 0xd6, 0x75, 0x7a, 0x7d, 0xb3, 0x23, 0x2c, 0xc7, - 0xbe, 0xa6, 0xb0, 0x50, 0x4d, 0x6c, 0xe2, 0x90, 0x85, 0x97, 0x77, 0x0d, 0x2f, 0xf5, 0x7b, 0xb0, 0xc6, - 0xad, 0xfa, 0x9a, 0x2c, 0xdf, 0xeb, 0x0d, 0x60, 0xd3, 0x0e, 0xa8, 0x5c, 0x43, 0xab, 0x09, 0x85, 0xa3, - 0xa9, 0x31, 0x66, 0xbd, 0xe4], - vec![0x30, 0x82, 0x04, 0x59, 0x30, 0x82, 0x03, 0x45, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x05, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x11, - 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x06, 0x42, 0x65, 0x63, 0x6b, 0x65, 0x72, - 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x30, 0x32, 0x36, 0x32, 0x33, 0x32, 0x36, 0x34, 0x35, 0x5a, - 0x17, 0x0d, 0x33, 0x38, 0x30, 0x31, 0x31, 0x39, 0x30, 0x33, 0x31, 0x34, 0x30, 0x37, 0x5a, 0x30, 0x81, - 0xa6, 0x31, 0x81, 0xa3, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x1e, 0x20, 0x00, 0x6e, 0x00, 0x63, - 0x00, 0x61, 0x00, 0x63, 0x00, 0x6e, 0x00, 0x5f, 0x00, 0x69, 0x00, 0x70, 0x00, 0x5f, 0x00, 0x74, 0x00, - 0x63, 0x00, 0x70, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x32, 0x00, 0x37, 0x30, 0x33, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x1e, 0x2c, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6e, 0x00, 0x5f, 0x00, 0x69, - 0x00, 0x70, 0x00, 0x5f, 0x00, 0x74, 0x00, 0x63, 0x00, 0x70, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x32, 0x00, - 0x37, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x31, 0x30, 0x43, 0x06, 0x03, - 0x55, 0x04, 0x05, 0x1e, 0x3c, 0x00, 0x31, 0x00, 0x42, 0x00, 0x63, 0x00, 0x4b, 0x00, 0x65, 0x00, 0x56, - 0x00, 0x33, 0x00, 0x4d, 0x00, 0x67, 0x00, 0x74, 0x00, 0x6a, 0x00, 0x55, 0x00, 0x74, 0x00, 0x6f, 0x00, - 0x32, 0x00, 0x50, 0x00, 0x49, 0x00, 0x68, 0x00, 0x35, 0x00, 0x52, 0x00, 0x57, 0x00, 0x56, 0x00, 0x36, - 0x00, 0x42, 0x00, 0x58, 0x00, 0x48, 0x00, 0x77, 0x00, 0x3d, 0x00, 0x0d, 0x00, 0x0a, 0x30, 0x58, 0x30, - 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x0f, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, - 0x00, 0xab, 0xac, 0x87, 0x11, 0x83, 0xbf, 0xe9, 0x48, 0x25, 0x00, 0x2c, 0x33, 0x31, 0x5e, 0x3d, 0x78, - 0xc8, 0x5f, 0x82, 0xcb, 0x36, 0x41, 0xf5, 0xb4, 0x65, 0x15, 0xee, 0x04, 0x31, 0xae, 0xe2, 0x48, 0x58, - 0x99, 0x7f, 0x4f, 0x90, 0x1d, 0xf7, 0x7c, 0xd7, 0xf8, 0x47, 0x93, 0xa0, 0xca, 0x9c, 0xdf, 0x91, 0xb0, - 0x41, 0xe8, 0x05, 0x4b, 0xdc, 0x24, 0x5b, 0x72, 0xf7, 0x68, 0x91, 0x84, 0xfb, 0x19, 0x02, 0x03, 0x01, - 0x00, 0x01, 0xa3, 0x82, 0x01, 0xf4, 0x30, 0x82, 0x01, 0xf0, 0x30, 0x14, 0x06, 0x09, 0x2b, 0x06, 0x01, - 0x04, 0x01, 0x82, 0x37, 0x12, 0x04, 0x01, 0x01, 0xff, 0x04, 0x04, 0x01, 0x00, 0x05, 0x00, 0x30, 0x3c, - 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x12, 0x02, 0x01, 0x01, 0xff, 0x04, 0x2c, 0x4d, - 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, - 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, - 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x30, 0x81, 0xdd, 0x06, 0x09, 0x2b, 0x06, 0x01, - 0x04, 0x01, 0x82, 0x37, 0x12, 0x05, 0x01, 0x01, 0xff, 0x04, 0x81, 0xcc, 0x00, 0x30, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x22, 0x04, 0x00, 0x00, 0x1c, 0x00, 0x4a, 0x00, 0x66, 0x00, - 0x4a, 0x00, 0xb0, 0x00, 0x03, 0x00, 0x33, 0x00, 0x64, 0x00, 0x32, 0x00, 0x36, 0x00, 0x37, 0x00, 0x39, - 0x00, 0x35, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x65, 0x00, 0x65, 0x00, 0x62, 0x00, 0x37, 0x00, 0x2d, 0x00, - 0x31, 0x00, 0x31, 0x00, 0x64, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x39, 0x00, 0x34, 0x00, 0x65, - 0x00, 0x2d, 0x00, 0x30, 0x00, 0x30, 0x00, 0x63, 0x00, 0x30, 0x00, 0x34, 0x00, 0x66, 0x00, 0x61, 0x00, - 0x33, 0x00, 0x30, 0x00, 0x38, 0x00, 0x30, 0x00, 0x64, 0x00, 0x00, 0x00, 0x33, 0x00, 0x64, 0x00, 0x32, - 0x00, 0x36, 0x00, 0x37, 0x00, 0x39, 0x00, 0x35, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x65, 0x00, 0x65, 0x00, - 0x62, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x31, 0x00, 0x64, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x62, - 0x00, 0x39, 0x00, 0x34, 0x00, 0x65, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x30, 0x00, 0x63, 0x00, 0x30, 0x00, - 0x34, 0x00, 0x66, 0x00, 0x61, 0x00, 0x33, 0x00, 0x30, 0x00, 0x38, 0x00, 0x30, 0x00, 0x64, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x81, 0x80, 0x06, 0x09, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x12, 0x06, 0x01, 0x01, 0xff, 0x04, 0x70, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x00, 0x50, 0x00, 0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x2d, 0x00, 0x34, 0x00, - 0x4c, 0x00, 0x34, 0x00, 0x4c, 0x00, 0x36, 0x00, 0x41, 0x00, 0x4d, 0x00, 0x42, 0x00, 0x43, 0x00, 0x53, - 0x00, 0x51, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x34, 0x00, 0x32, 0x00, 0x39, 0x00, 0x2d, 0x00, - 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x2d, 0x00, 0x33, 0x00, 0x34, 0x00, 0x39, - 0x00, 0x37, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x41, 0x00, 0x54, 0x00, 0x33, 0x00, 0x35, 0x00, 0x33, 0x00, - 0x00, 0x00, 0x57, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x4b, 0x00, 0x47, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x55, - 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x01, 0x01, 0xff, - 0x04, 0x2d, 0x30, 0x2b, 0xa1, 0x22, 0xa4, 0x20, 0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x2d, 0x00, 0x34, - 0x00, 0x4c, 0x00, 0x34, 0x00, 0x4c, 0x00, 0x36, 0x00, 0x41, 0x00, 0x4d, 0x00, 0x42, 0x00, 0x43, 0x00, - 0x53, 0x00, 0x51, 0x00, 0x00, 0x00, 0x82, 0x05, 0x01, 0x00, 0x00, 0x00, 0x02, 0x30, 0x09, 0x06, 0x05, - 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x3e, 0xd3, 0xd5, 0x61, 0x8a, - 0x87, 0x7b, 0x98, 0x2c, 0x6d, 0x20, 0x38, 0x12, 0x08, 0xd8, 0xf7, 0x83, 0x08, 0xf8, 0xe6, 0xb2, 0xe1, - 0x21, 0xe1, 0x30, 0x61, 0x12, 0x19, 0xe8, 0xc1, 0x41, 0xaf, 0x59, 0x7c, 0x1e, 0x3e, 0xc8, 0x40, 0x9e, - 0x24, 0xe8, 0x8d, 0x0c, 0x41, 0xfd, 0xf8, 0x3e, 0xa1, 0xb3, 0xac, 0x56, 0xac, 0x52, 0x91, 0x5a, 0xf8, - 0xd0, 0x40, 0x8e, 0x13, 0x47, 0xa9, 0x8a, 0x0a, 0x62, 0x6d, 0x11, 0x89, 0x20, 0x56, 0xe7, 0xd6, 0x5f, - 0x12, 0x44, 0x94, 0xbf, 0x63, 0x99, 0xa3, 0x42, 0x40, 0xd5, 0xc6, 0x8c, 0x1f, 0x4b, 0xf8, 0xaf, 0x83, - 0x8e, 0xf6, 0x74, 0xb2, 0x0b, 0x55, 0x13, 0x4a, 0x76, 0xed, 0x37, 0xd8, 0x3d, 0x13, 0xe7, 0xae, 0x43, - 0x4c, 0x9a, 0x61, 0x6c, 0x7b, 0x1b, 0xd1, 0xaa, 0x00, 0x97, 0xdf, 0x5b, 0x85, 0x9f, 0xc8, 0xee, 0x6c, - 0xe5, 0xa2, 0x63, 0x76, 0xe4, 0x06, 0xd3, 0x2a, 0xe0, 0x55, 0xe1, 0x92, 0x78, 0xed, 0x03, 0x7b, 0x7d, - 0x1a, 0x6e, 0xc2, 0x56, 0xdc, 0xad, 0x6e, 0xd7, 0xa9, 0xfe, 0xa7, 0xfd, 0x09, 0x0a, 0xa6, 0xd5, 0x8a, - 0x99, 0xa4, 0x75, 0x89, 0xad, 0x84, 0xc7, 0x09, 0xf7, 0x4c, 0x6e, 0xd0, 0xe2, 0x80, 0x17, 0x62, 0xfa, - 0x86, 0xfe, 0x43, 0x51, 0xf2, 0xb4, 0xf6, 0xef, 0x3b, 0xb3, 0x3d, 0x1f, 0xef, 0xa3, 0xcb, 0xa2, 0x57, - 0x25, 0x7c, 0x02, 0xf2, 0x27, 0x1c, 0x87, 0x70, 0x8e, 0x84, 0x20, 0xfe, 0x1d, 0x4a, 0xc4, 0x87, 0x24, - 0x3b, 0xba, 0xff, 0x34, 0x1a, 0xe2, 0xff, 0xa2, 0x43, 0x39, 0xd8, 0x19, 0x97, 0xf8, 0xf0, 0xf9, 0x73, - 0xa6, 0xb6, 0x55, 0x64, 0xa6, 0xca, 0xa3, 0x48, 0x22, 0xb7, 0x1a, 0x9b, 0x98, 0x1a, 0x8e, 0x2f, 0xaa, - 0xec, 0xc1, 0xfe, 0x25, 0x36, 0x2b, 0x70, 0x97, 0x8c, 0x5b, 0x62, 0x21, 0xc3], - ], + pub(crate) static ref SERVER_LICENSE_REQUEST: LicensePdu = { + let mut req = ServerLicenseRequest { + license_header: LicenseHeader { + security_header: BasicSecurityHeader { + flags: BasicSecurityHeaderFlags::LICENSE_PKT, + }, + preamble_message_type: PreambleType::LicenseRequest, + preamble_flags: PreambleFlags::empty(), + preamble_version: PreambleVersion::V3, + preamble_message_size: 0, + }, + server_random: Vec::from(SERVER_RANDOM_BUFFER.as_ref()), + product_info: ProductInfo { + version: 0x60000, + company_name: "Microsoft Corporation".to_string(), + product_id: "A02".to_string(), + }, + server_certificate: Some(ServerCertificate { + issued_permanently: true, + certificate: CertificateType::X509(X509CertificateChain { + certificate_array: vec![ + vec![0x30, 0x82, 0x03, 0xda, 0x30, 0x82, 0x02, 0xc2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x7f, + 0x00, 0x00, 0x01, 0x76, 0x00, 0x8f, 0x08, 0x64, 0x08, 0x68, 0xa7, 0x63, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x76, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, + 0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x50, 0x72, 0x6f, 0x64, 0x32, + 0x4c, 0x53, 0x52, 0x41, 0x73, 0x68, 0x61, 0x32, 0x52, 0x44, 0x53, 0x4c, 0x4d, 0x30, 0x1e, 0x17, 0x0d, + 0x31, 0x39, 0x31, 0x30, 0x32, 0x36, 0x32, 0x32, 0x35, 0x33, 0x34, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x37, + 0x30, 0x36, 0x30, 0x36, 0x32, 0x30, 0x34, 0x32, 0x33, 0x38, 0x5a, 0x30, 0x11, 0x31, 0x0f, 0x30, 0x0d, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x06, 0x42, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x30, 0x82, 0x01, 0x22, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, + 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa8, 0x6b, 0xda, 0xae, 0x08, + 0x1d, 0xc5, 0x05, 0x70, 0x7d, 0xa0, 0x41, 0x46, 0xb4, 0x14, 0xcf, 0xfb, 0x8e, 0x09, 0x0b, 0x0a, 0x52, + 0x8a, 0x7f, 0x7a, 0x35, 0xb6, 0xe3, 0x0d, 0x1c, 0xbe, 0x49, 0x63, 0x41, 0x92, 0x86, 0x00, 0xa2, 0xd3, + 0xff, 0x5b, 0x08, 0x7d, 0x2b, 0x65, 0xe4, 0xc3, 0x09, 0x68, 0x72, 0x21, 0xc4, 0xd8, 0x0a, 0x21, 0x9e, + 0x1f, 0xdf, 0xb2, 0xaa, 0x2b, 0x42, 0x68, 0xe7, 0xeb, 0x52, 0xf8, 0x9e, 0xfc, 0x7f, 0x0f, 0x55, 0x26, + 0x7d, 0x44, 0xfb, 0x35, 0xe5, 0xc2, 0x2c, 0xb6, 0x8d, 0x06, 0xc5, 0xdc, 0xbf, 0x66, 0xf6, 0xb2, 0xf2, + 0x9b, 0xe2, 0x49, 0xaf, 0xfd, 0x4c, 0x69, 0x46, 0x72, 0xe0, 0x2f, 0x31, 0x77, 0x86, 0x7b, 0x5b, 0x6d, + 0x49, 0xe6, 0xc7, 0x84, 0xd1, 0xdd, 0x56, 0x89, 0x8d, 0xbd, 0x07, 0x18, 0x01, 0x43, 0x70, 0x9b, 0x00, + 0x71, 0x16, 0x89, 0x66, 0x2e, 0xb6, 0x5f, 0x62, 0xeb, 0x96, 0xed, 0xf2, 0xdb, 0xdb, 0xcf, 0xdd, 0xa8, + 0xab, 0xde, 0x93, 0xb3, 0xdb, 0x54, 0xf0, 0x34, 0x4a, 0x28, 0xc3, 0x11, 0xf6, 0xb9, 0xd6, 0x45, 0x3f, + 0x07, 0xc0, 0x8e, 0x10, 0x7a, 0x2b, 0x56, 0x15, 0xbb, 0x00, 0x9d, 0x82, 0x27, 0xf2, 0x11, 0xa3, 0xda, + 0x03, 0xaa, 0x51, 0xc0, 0xfd, 0x90, 0xc8, 0x73, 0x81, 0xce, 0x97, 0x30, 0xa2, 0x54, 0x63, 0x6f, 0xfc, + 0x7f, 0x5b, 0x71, 0xec, 0x11, 0xb0, 0xa0, 0xc8, 0x74, 0x3a, 0xcc, 0x1b, 0x5e, 0xcd, 0x91, 0xa8, 0x18, + 0x92, 0xeb, 0x33, 0xc4, 0x6d, 0xb8, 0x16, 0x67, 0xe1, 0xc5, 0xa6, 0x26, 0x35, 0x48, 0xc4, 0xe7, 0x94, + 0xeb, 0xbb, 0xb8, 0xde, 0xd3, 0xe1, 0xc0, 0xcb, 0x00, 0x20, 0xf6, 0xbc, 0xa9, 0xc5, 0x70, 0xc4, 0xda, + 0x1b, 0x61, 0x0b, 0x9f, 0x0b, 0x19, 0x93, 0xaf, 0x8f, 0x40, 0xbb, 0x26, 0x79, 0x02, 0x03, 0x01, 0x00, + 0x01, 0xa3, 0x82, 0x01, 0x1d, 0x30, 0x82, 0x01, 0x19, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, + 0x16, 0x04, 0x14, 0xa3, 0xda, 0xe5, 0xef, 0xc3, 0x1c, 0x7a, 0xcf, 0x34, 0x2b, 0xa2, 0x42, 0x2b, 0x77, + 0xcb, 0x62, 0xfb, 0x4c, 0x28, 0x51, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, + 0x80, 0x14, 0x9c, 0xe1, 0xad, 0x8f, 0xd4, 0x86, 0xd2, 0x1c, 0x7e, 0x48, 0x32, 0xf2, 0x28, 0xfe, 0x87, + 0x90, 0xe3, 0xb1, 0xc5, 0x8e, 0x30, 0x4a, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x43, 0x30, 0x41, 0x30, + 0x3f, 0xa0, 0x3d, 0xa0, 0x3b, 0x86, 0x39, 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x2f, 0x2f, 0x2f, 0x2f, 0x52, + 0x44, 0x32, 0x38, 0x31, 0x38, 0x37, 0x38, 0x30, 0x45, 0x33, 0x45, 0x45, 0x43, 0x2f, 0x43, 0x65, 0x72, + 0x74, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x50, 0x72, 0x6f, 0x64, 0x32, 0x4c, 0x53, 0x52, 0x41, + 0x73, 0x68, 0x61, 0x32, 0x52, 0x44, 0x53, 0x4c, 0x4d, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x64, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x58, 0x30, 0x56, 0x30, 0x54, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x48, 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x2f, 0x2f, 0x2f, + 0x2f, 0x52, 0x44, 0x32, 0x38, 0x31, 0x38, 0x37, 0x38, 0x30, 0x45, 0x33, 0x45, 0x45, 0x43, 0x2f, 0x43, + 0x65, 0x72, 0x74, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x52, 0x44, 0x32, 0x38, 0x31, 0x38, 0x37, + 0x38, 0x30, 0x45, 0x33, 0x45, 0x45, 0x43, 0x5f, 0x50, 0x72, 0x6f, 0x64, 0x32, 0x4c, 0x53, 0x52, 0x41, + 0x73, 0x68, 0x61, 0x32, 0x52, 0x44, 0x53, 0x4c, 0x4d, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x0c, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x17, 0x06, 0x08, 0x2b, 0x06, 0x01, + 0x04, 0x01, 0x82, 0x37, 0x12, 0x04, 0x0b, 0x16, 0x09, 0x54, 0x4c, 0x53, 0x7e, 0x42, 0x41, 0x53, 0x49, + 0x43, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x01, 0x00, 0x55, 0xd5, 0x94, 0x3b, 0x06, 0xef, 0xf2, 0xb0, 0xf9, 0xd7, 0x36, 0x2a, 0x36, + 0xe0, 0xf1, 0xd9, 0x18, 0xc1, 0x89, 0x7e, 0xa2, 0xcf, 0x01, 0x6f, 0x22, 0x7b, 0x34, 0x81, 0xf0, 0x7a, + 0x45, 0x11, 0x6e, 0x75, 0x4b, 0x0b, 0xa8, 0xcd, 0x92, 0x57, 0x19, 0x80, 0xb7, 0x6e, 0x1a, 0x4d, 0x12, + 0x65, 0x91, 0x56, 0x38, 0x17, 0x22, 0xa2, 0x75, 0xae, 0xf9, 0x12, 0x75, 0x38, 0xf3, 0x19, 0x74, 0xea, + 0x87, 0x46, 0x1f, 0x98, 0x2c, 0x2f, 0xf9, 0xfc, 0xb4, 0xdc, 0x25, 0xa0, 0xd3, 0x34, 0x1b, 0xbc, 0x21, + 0xbb, 0x3d, 0x82, 0xad, 0x15, 0xc6, 0x3d, 0x02, 0x75, 0x33, 0x70, 0x25, 0x0a, 0x1a, 0xf7, 0x4c, 0xcb, + 0x84, 0xa3, 0xc1, 0x78, 0xe6, 0xf5, 0xa1, 0x44, 0x54, 0xc8, 0x34, 0xfd, 0xef, 0xbf, 0x86, 0x81, 0x9d, + 0x9a, 0x7e, 0xb6, 0xad, 0x71, 0x7e, 0xe4, 0xd9, 0x71, 0x6c, 0xb9, 0xe7, 0xf2, 0xd6, 0xd7, 0xbb, 0x66, + 0x5a, 0x30, 0xf5, 0x29, 0xae, 0x02, 0x39, 0x3d, 0xea, 0x7a, 0x79, 0x1b, 0x53, 0xc5, 0xbe, 0x8d, 0xfb, + 0xe2, 0xe4, 0x8e, 0xc2, 0x04, 0xb3, 0x0a, 0x94, 0x75, 0xa3, 0xbf, 0xd4, 0x87, 0xd2, 0x74, 0x15, 0x05, + 0x5e, 0xd5, 0x8f, 0x94, 0x23, 0x41, 0x13, 0x3f, 0xbd, 0xed, 0x21, 0x55, 0x96, 0xe9, 0xc4, 0x93, 0x34, + 0x7f, 0xaa, 0xea, 0xe7, 0xb1, 0x9a, 0xca, 0x25, 0x91, 0x18, 0xdf, 0x28, 0x05, 0x8e, 0x53, 0xb3, 0x8c, + 0x8d, 0xcc, 0xf3, 0xf4, 0x78, 0x76, 0x76, 0x7b, 0x82, 0xd6, 0x75, 0x7a, 0x7d, 0xb3, 0x23, 0x2c, 0xc7, + 0xbe, 0xa6, 0xb0, 0x50, 0x4d, 0x6c, 0xe2, 0x90, 0x85, 0x97, 0x77, 0x0d, 0x2f, 0xf5, 0x7b, 0xb0, 0xc6, + 0xad, 0xfa, 0x9a, 0x2c, 0xdf, 0xeb, 0x0d, 0x60, 0xd3, 0x0e, 0xa8, 0x5c, 0x43, 0xab, 0x09, 0x85, 0xa3, + 0xa9, 0x31, 0x66, 0xbd, 0xe4], + vec![0x30, 0x82, 0x04, 0x59, 0x30, 0x82, 0x03, 0x45, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x05, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x11, + 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x06, 0x42, 0x65, 0x63, 0x6b, 0x65, 0x72, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x30, 0x32, 0x36, 0x32, 0x33, 0x32, 0x36, 0x34, 0x35, 0x5a, + 0x17, 0x0d, 0x33, 0x38, 0x30, 0x31, 0x31, 0x39, 0x30, 0x33, 0x31, 0x34, 0x30, 0x37, 0x5a, 0x30, 0x81, + 0xa6, 0x31, 0x81, 0xa3, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x1e, 0x20, 0x00, 0x6e, 0x00, 0x63, + 0x00, 0x61, 0x00, 0x63, 0x00, 0x6e, 0x00, 0x5f, 0x00, 0x69, 0x00, 0x70, 0x00, 0x5f, 0x00, 0x74, 0x00, + 0x63, 0x00, 0x70, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x32, 0x00, 0x37, 0x30, 0x33, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x1e, 0x2c, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6e, 0x00, 0x5f, 0x00, 0x69, + 0x00, 0x70, 0x00, 0x5f, 0x00, 0x74, 0x00, 0x63, 0x00, 0x70, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x32, 0x00, + 0x37, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x31, 0x30, 0x43, 0x06, 0x03, + 0x55, 0x04, 0x05, 0x1e, 0x3c, 0x00, 0x31, 0x00, 0x42, 0x00, 0x63, 0x00, 0x4b, 0x00, 0x65, 0x00, 0x56, + 0x00, 0x33, 0x00, 0x4d, 0x00, 0x67, 0x00, 0x74, 0x00, 0x6a, 0x00, 0x55, 0x00, 0x74, 0x00, 0x6f, 0x00, + 0x32, 0x00, 0x50, 0x00, 0x49, 0x00, 0x68, 0x00, 0x35, 0x00, 0x52, 0x00, 0x57, 0x00, 0x56, 0x00, 0x36, + 0x00, 0x42, 0x00, 0x58, 0x00, 0x48, 0x00, 0x77, 0x00, 0x3d, 0x00, 0x0d, 0x00, 0x0a, 0x30, 0x58, 0x30, + 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x0f, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, + 0x00, 0xab, 0xac, 0x87, 0x11, 0x83, 0xbf, 0xe9, 0x48, 0x25, 0x00, 0x2c, 0x33, 0x31, 0x5e, 0x3d, 0x78, + 0xc8, 0x5f, 0x82, 0xcb, 0x36, 0x41, 0xf5, 0xb4, 0x65, 0x15, 0xee, 0x04, 0x31, 0xae, 0xe2, 0x48, 0x58, + 0x99, 0x7f, 0x4f, 0x90, 0x1d, 0xf7, 0x7c, 0xd7, 0xf8, 0x47, 0x93, 0xa0, 0xca, 0x9c, 0xdf, 0x91, 0xb0, + 0x41, 0xe8, 0x05, 0x4b, 0xdc, 0x24, 0x5b, 0x72, 0xf7, 0x68, 0x91, 0x84, 0xfb, 0x19, 0x02, 0x03, 0x01, + 0x00, 0x01, 0xa3, 0x82, 0x01, 0xf4, 0x30, 0x82, 0x01, 0xf0, 0x30, 0x14, 0x06, 0x09, 0x2b, 0x06, 0x01, + 0x04, 0x01, 0x82, 0x37, 0x12, 0x04, 0x01, 0x01, 0xff, 0x04, 0x04, 0x01, 0x00, 0x05, 0x00, 0x30, 0x3c, + 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x12, 0x02, 0x01, 0x01, 0xff, 0x04, 0x2c, 0x4d, + 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, + 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, + 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x30, 0x81, 0xdd, 0x06, 0x09, 0x2b, 0x06, 0x01, + 0x04, 0x01, 0x82, 0x37, 0x12, 0x05, 0x01, 0x01, 0xff, 0x04, 0x81, 0xcc, 0x00, 0x30, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x22, 0x04, 0x00, 0x00, 0x1c, 0x00, 0x4a, 0x00, 0x66, 0x00, + 0x4a, 0x00, 0xb0, 0x00, 0x03, 0x00, 0x33, 0x00, 0x64, 0x00, 0x32, 0x00, 0x36, 0x00, 0x37, 0x00, 0x39, + 0x00, 0x35, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x65, 0x00, 0x65, 0x00, 0x62, 0x00, 0x37, 0x00, 0x2d, 0x00, + 0x31, 0x00, 0x31, 0x00, 0x64, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x39, 0x00, 0x34, 0x00, 0x65, + 0x00, 0x2d, 0x00, 0x30, 0x00, 0x30, 0x00, 0x63, 0x00, 0x30, 0x00, 0x34, 0x00, 0x66, 0x00, 0x61, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x38, 0x00, 0x30, 0x00, 0x64, 0x00, 0x00, 0x00, 0x33, 0x00, 0x64, 0x00, 0x32, + 0x00, 0x36, 0x00, 0x37, 0x00, 0x39, 0x00, 0x35, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x65, 0x00, 0x65, 0x00, + 0x62, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x31, 0x00, 0x64, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x62, + 0x00, 0x39, 0x00, 0x34, 0x00, 0x65, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x30, 0x00, 0x63, 0x00, 0x30, 0x00, + 0x34, 0x00, 0x66, 0x00, 0x61, 0x00, 0x33, 0x00, 0x30, 0x00, 0x38, 0x00, 0x30, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x81, 0x80, 0x06, 0x09, + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x12, 0x06, 0x01, 0x01, 0xff, 0x04, 0x70, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x50, 0x00, 0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x2d, 0x00, 0x34, 0x00, + 0x4c, 0x00, 0x34, 0x00, 0x4c, 0x00, 0x36, 0x00, 0x41, 0x00, 0x4d, 0x00, 0x42, 0x00, 0x43, 0x00, 0x53, + 0x00, 0x51, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x34, 0x00, 0x32, 0x00, 0x39, 0x00, 0x2d, 0x00, + 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x2d, 0x00, 0x33, 0x00, 0x34, 0x00, 0x39, + 0x00, 0x37, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x41, 0x00, 0x54, 0x00, 0x33, 0x00, 0x35, 0x00, 0x33, 0x00, + 0x00, 0x00, 0x57, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x4b, 0x00, 0x47, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x55, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x01, 0x01, 0xff, + 0x04, 0x2d, 0x30, 0x2b, 0xa1, 0x22, 0xa4, 0x20, 0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x2d, 0x00, 0x34, + 0x00, 0x4c, 0x00, 0x34, 0x00, 0x4c, 0x00, 0x36, 0x00, 0x41, 0x00, 0x4d, 0x00, 0x42, 0x00, 0x43, 0x00, + 0x53, 0x00, 0x51, 0x00, 0x00, 0x00, 0x82, 0x05, 0x01, 0x00, 0x00, 0x00, 0x02, 0x30, 0x09, 0x06, 0x05, + 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x3e, 0xd3, 0xd5, 0x61, 0x8a, + 0x87, 0x7b, 0x98, 0x2c, 0x6d, 0x20, 0x38, 0x12, 0x08, 0xd8, 0xf7, 0x83, 0x08, 0xf8, 0xe6, 0xb2, 0xe1, + 0x21, 0xe1, 0x30, 0x61, 0x12, 0x19, 0xe8, 0xc1, 0x41, 0xaf, 0x59, 0x7c, 0x1e, 0x3e, 0xc8, 0x40, 0x9e, + 0x24, 0xe8, 0x8d, 0x0c, 0x41, 0xfd, 0xf8, 0x3e, 0xa1, 0xb3, 0xac, 0x56, 0xac, 0x52, 0x91, 0x5a, 0xf8, + 0xd0, 0x40, 0x8e, 0x13, 0x47, 0xa9, 0x8a, 0x0a, 0x62, 0x6d, 0x11, 0x89, 0x20, 0x56, 0xe7, 0xd6, 0x5f, + 0x12, 0x44, 0x94, 0xbf, 0x63, 0x99, 0xa3, 0x42, 0x40, 0xd5, 0xc6, 0x8c, 0x1f, 0x4b, 0xf8, 0xaf, 0x83, + 0x8e, 0xf6, 0x74, 0xb2, 0x0b, 0x55, 0x13, 0x4a, 0x76, 0xed, 0x37, 0xd8, 0x3d, 0x13, 0xe7, 0xae, 0x43, + 0x4c, 0x9a, 0x61, 0x6c, 0x7b, 0x1b, 0xd1, 0xaa, 0x00, 0x97, 0xdf, 0x5b, 0x85, 0x9f, 0xc8, 0xee, 0x6c, + 0xe5, 0xa2, 0x63, 0x76, 0xe4, 0x06, 0xd3, 0x2a, 0xe0, 0x55, 0xe1, 0x92, 0x78, 0xed, 0x03, 0x7b, 0x7d, + 0x1a, 0x6e, 0xc2, 0x56, 0xdc, 0xad, 0x6e, 0xd7, 0xa9, 0xfe, 0xa7, 0xfd, 0x09, 0x0a, 0xa6, 0xd5, 0x8a, + 0x99, 0xa4, 0x75, 0x89, 0xad, 0x84, 0xc7, 0x09, 0xf7, 0x4c, 0x6e, 0xd0, 0xe2, 0x80, 0x17, 0x62, 0xfa, + 0x86, 0xfe, 0x43, 0x51, 0xf2, 0xb4, 0xf6, 0xef, 0x3b, 0xb3, 0x3d, 0x1f, 0xef, 0xa3, 0xcb, 0xa2, 0x57, + 0x25, 0x7c, 0x02, 0xf2, 0x27, 0x1c, 0x87, 0x70, 0x8e, 0x84, 0x20, 0xfe, 0x1d, 0x4a, 0xc4, 0x87, 0x24, + 0x3b, 0xba, 0xff, 0x34, 0x1a, 0xe2, 0xff, 0xa2, 0x43, 0x39, 0xd8, 0x19, 0x97, 0xf8, 0xf0, 0xf9, 0x73, + 0xa6, 0xb6, 0x55, 0x64, 0xa6, 0xca, 0xa3, 0x48, 0x22, 0xb7, 0x1a, 0x9b, 0x98, 0x1a, 0x8e, 0x2f, 0xaa, + 0xec, 0xc1, 0xfe, 0x25, 0x36, 0x2b, 0x70, 0x97, 0x8c, 0x5b, 0x62, 0x21, 0xc3], + ], + }), }), - }), - scope_list: vec![Scope(String::from("microsoft.com"))], + scope_list: vec![Scope(String::from("microsoft.com"))], + }; + req.license_header.preamble_message_size = req.size() as u16; + req.into() }; } @@ -281,17 +294,25 @@ fn buffer_length_is_correct_for_client_new_license_request() { #[test] fn client_new_license_request_creates_correctly() { - let (client_new_license_request, encryption_data) = ClientNewLicenseRequest::from_server_license_request( - &SERVER_LICENSE_REQUEST, - CLIENT_RANDOM_BUFFER.as_ref(), - PREMASTER_SECRET_BUFFER.as_ref(), - CLIENT_USERNAME, - CLIENT_MACHINE_NAME, - ) - .unwrap(); + match &*SERVER_LICENSE_REQUEST { + LicensePdu::ServerLicenseRequest(license_request) => { + let (client_new_license_request, encryption_data) = ClientNewLicenseRequest::from_server_license_request( + license_request, + CLIENT_RANDOM_BUFFER.as_ref(), + PREMASTER_SECRET_BUFFER.as_ref(), + CLIENT_USERNAME, + CLIENT_MACHINE_NAME, + ) + .unwrap(); - assert_eq!(encryption_data.license_key, LICENSE_KEY_BUFFER.as_ref()); - assert_eq!(client_new_license_request, *CLIENT_NEW_LICENSE_REQUEST); + assert_eq!(encryption_data.license_key, LICENSE_KEY_BUFFER.as_ref()); + assert_eq!( + Into::::into(client_new_license_request), + *CLIENT_NEW_LICENSE_REQUEST + ); + } + _ => panic!("Invalid license pdu"), + } } #[test] diff --git a/crates/ironrdp-pdu/src/rdp/server_license/client_platform_challenge_response.rs b/crates/ironrdp-pdu/src/rdp/server_license/client_platform_challenge_response.rs index 4c22c14ef..8280bf01c 100644 --- a/crates/ironrdp-pdu/src/rdp/server_license/client_platform_challenge_response.rs +++ b/crates/ironrdp-pdu/src/rdp/server_license/client_platform_challenge_response.rs @@ -100,16 +100,16 @@ impl ClientPlatformChallengeResponse { } } -impl PduEncode for ClientPlatformChallengeResponse { - fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> { +impl ClientPlatformChallengeResponse { + pub fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> { ensure_size!(in: dst, size: self.size()); self.license_header.encode(dst)?; - BlobHeader::new(BlobType::EncryptedData, self.encrypted_challenge_response_data.len()).encode(dst)?; + BlobHeader::new(BlobType::ENCRYPTED_DATA, self.encrypted_challenge_response_data.len()).encode(dst)?; dst.write_slice(&self.encrypted_challenge_response_data); - BlobHeader::new(BlobType::EncryptedData, self.encrypted_hwid.len()).encode(dst)?; + BlobHeader::new(BlobType::ENCRYPTED_DATA, self.encrypted_hwid.len()).encode(dst)?; dst.write_slice(&self.encrypted_hwid); dst.write_slice(&self.mac_data); @@ -117,20 +117,19 @@ impl PduEncode for ClientPlatformChallengeResponse { Ok(()) } - fn name(&self) -> &'static str { + pub fn name(&self) -> &'static str { Self::NAME } - fn size(&self) -> usize { + pub fn size(&self) -> usize { self.license_header.size() + (BLOB_TYPE_SIZE + BLOB_LENGTH_SIZE) * 2 // 2 blobs in this structure + MAC_SIZE + self.encrypted_challenge_response_data.len() + self.encrypted_hwid.len() } } -impl<'de> PduDecode<'de> for ClientPlatformChallengeResponse { - fn decode(src: &mut ReadCursor<'de>) -> PduResult { - let license_header = LicenseHeader::decode(src)?; +impl ClientPlatformChallengeResponse { + pub fn decode(license_header: LicenseHeader, src: &mut ReadCursor<'_>) -> PduResult { if license_header.preamble_message_type != PreambleType::PlatformChallengeResponse { return Err(invalid_message_err!( "preambleMessageType", @@ -139,14 +138,14 @@ impl<'de> PduDecode<'de> for ClientPlatformChallengeResponse { } let encrypted_challenge_blob = BlobHeader::decode(src)?; - if encrypted_challenge_blob.blob_type != BlobType::EncryptedData { + if encrypted_challenge_blob.blob_type != BlobType::ENCRYPTED_DATA { return Err(invalid_message_err!("blobType", "unexpected blob type")); } ensure_size!(in: src, size: encrypted_challenge_blob.length); let encrypted_challenge_response_data = src.read_slice(encrypted_challenge_blob.length).into(); let encrypted_hwid_blob = BlobHeader::decode(src)?; - if encrypted_hwid_blob.blob_type != BlobType::EncryptedData { + if encrypted_hwid_blob.blob_type != BlobType::ENCRYPTED_DATA { return Err(invalid_message_err!("blobType", "unexpected blob type")); } ensure_size!(in: src, size: encrypted_hwid_blob.length); diff --git a/crates/ironrdp-pdu/src/rdp/server_license/client_platform_challenge_response/test.rs b/crates/ironrdp-pdu/src/rdp/server_license/client_platform_challenge_response/test.rs index 65b3f05f8..c01b219eb 100644 --- a/crates/ironrdp-pdu/src/rdp/server_license/client_platform_challenge_response/test.rs +++ b/crates/ironrdp-pdu/src/rdp/server_license/client_platform_challenge_response/test.rs @@ -2,8 +2,8 @@ use lazy_static::lazy_static; use super::*; use crate::rdp::server_license::{ - BasicSecurityHeader, BasicSecurityHeaderFlags, LicenseHeader, PreambleFlags, PreambleType, PreambleVersion, - BASIC_SECURITY_HEADER_SIZE, PREAMBLE_SIZE, + BasicSecurityHeader, BasicSecurityHeaderFlags, LicenseHeader, LicensePdu, PreambleFlags, PreambleType, + PreambleVersion, BASIC_SECURITY_HEADER_SIZE, PREAMBLE_SIZE, }; use crate::{decode, encode_vec}; @@ -57,8 +57,8 @@ lazy_static! { platform_id: HARDWARE_ID, data: Vec::from(DATA_BUFFER.as_ref()), }; - pub(crate) static ref CLIENT_PLATFORM_CHALLENGE_RESPONSE: ClientPlatformChallengeResponse = - ClientPlatformChallengeResponse { + pub(crate) static ref CLIENT_PLATFORM_CHALLENGE_RESPONSE: LicensePdu = + LicensePdu::ClientPlatformChallengeResponse(ClientPlatformChallengeResponse { license_header: LicenseHeader { security_header: BasicSecurityHeader { flags: BasicSecurityHeaderFlags::LICENSE_PKT, @@ -74,7 +74,7 @@ lazy_static! { mac_data: Vec::from( &CLIENT_PLATFORM_CHALLENGE_RESPONSE_BUFFER[CLIENT_PLATFORM_CHALLENGE_RESPONSE_BUFFER.len() - 16..] ), - }; + }); } #[test] diff --git a/crates/ironrdp-pdu/src/rdp/server_license/licensing_error_message.rs b/crates/ironrdp-pdu/src/rdp/server_license/licensing_error_message.rs index 1b9d7706c..2648af0ba 100644 --- a/crates/ironrdp-pdu/src/rdp/server_license/licensing_error_message.rs +++ b/crates/ironrdp-pdu/src/rdp/server_license/licensing_error_message.rs @@ -4,9 +4,13 @@ mod test; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; -use super::{BlobHeader, BlobType, BLOB_LENGTH_SIZE, BLOB_TYPE_SIZE}; +use super::{BlobHeader, BlobType, LicenseHeader, PreambleFlags, PreambleVersion, BLOB_LENGTH_SIZE, BLOB_TYPE_SIZE}; use crate::{ cursor::{ReadCursor, WriteCursor}, + rdp::{ + headers::{BasicSecurityHeader, BasicSecurityHeaderFlags}, + server_license::PreambleType, + }, PduDecode, PduEncode, PduResult, }; @@ -18,6 +22,7 @@ const STATE_TRANSITION_SIZE: usize = 4; /// [2.2.1.12.1.3]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/f18b6c9f-f3d8-4a0e-8398-f9b153233dca #[derive(Debug, PartialEq, Eq)] pub struct LicensingErrorMessage { + pub license_header: LicenseHeader, pub error_code: LicenseErrorCode, pub state_transition: LicensingStateTransition, pub error_info: Vec, @@ -27,46 +32,73 @@ impl LicensingErrorMessage { const NAME: &'static str = "LicensingErrorMessage"; const FIXED_PART_SIZE: usize = ERROR_CODE_SIZE + STATE_TRANSITION_SIZE; + + pub fn new_valid_client() -> PduResult { + let mut this = Self { + license_header: LicenseHeader { + security_header: BasicSecurityHeader { + flags: BasicSecurityHeaderFlags::LICENSE_PKT, + }, + preamble_message_type: PreambleType::ErrorAlert, + preamble_flags: PreambleFlags::empty(), + preamble_version: PreambleVersion::V3, + preamble_message_size: 0, + }, + error_code: LicenseErrorCode::StatusValidClient, + state_transition: LicensingStateTransition::NoTransition, + error_info: Vec::new(), + }; + this.license_header.preamble_message_size = + cast_length!("LicensingErrorMessage", "preamble_message_size", this.size())?; + Ok(this) + } } -impl PduEncode for LicensingErrorMessage { - fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> { +impl LicensingErrorMessage { + pub fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> { ensure_size!(in: dst, size: self.size()); + self.license_header.encode(dst)?; + dst.write_u32(self.error_code.to_u32().unwrap()); dst.write_u32(self.state_transition.to_u32().unwrap()); - BlobHeader::new(BlobType::Error, self.error_info.len()).encode(dst)?; + BlobHeader::new(BlobType::ERROR, self.error_info.len()).encode(dst)?; dst.write_slice(&self.error_info); Ok(()) } - fn name(&self) -> &'static str { + pub fn name(&self) -> &'static str { Self::NAME } - fn size(&self) -> usize { - Self::FIXED_PART_SIZE + self.error_info.len() + BLOB_LENGTH_SIZE + BLOB_TYPE_SIZE + pub fn size(&self) -> usize { + self.license_header.size() + Self::FIXED_PART_SIZE + self.error_info.len() + BLOB_LENGTH_SIZE + BLOB_TYPE_SIZE } } -impl<'de> PduDecode<'de> for LicensingErrorMessage { - fn decode(src: &mut ReadCursor<'de>) -> PduResult { - ensure_fixed_part_size!(in: src); +impl LicensingErrorMessage { + pub fn decode(license_header: LicenseHeader, src: &mut ReadCursor<'_>) -> PduResult { + if license_header.preamble_message_type != PreambleType::ErrorAlert { + return Err(invalid_message_err!("preambleMessageType", "unexpected preamble type")); + } + ensure_fixed_part_size!(in: src); let error_code = LicenseErrorCode::from_u32(src.read_u32()) .ok_or_else(|| invalid_message_err!("errorCode", "invalid error code"))?; let state_transition = LicensingStateTransition::from_u32(src.read_u32()) .ok_or_else(|| invalid_message_err!("stateTransition", "invalid state transition"))?; let error_info_blob = BlobHeader::decode(src)?; - if error_info_blob.blob_type != BlobType::Error { + if error_info_blob.length != 0 && error_info_blob.blob_type != BlobType::ERROR { return Err(invalid_message_err!("blobType", "invalid blob type")); } + let error_info = vec![0u8; error_info_blob.length]; Ok(Self { + license_header, error_code, state_transition, error_info, diff --git a/crates/ironrdp-pdu/src/rdp/server_license/licensing_error_message/test.rs b/crates/ironrdp-pdu/src/rdp/server_license/licensing_error_message/test.rs index 73626bf5e..c6857555f 100644 --- a/crates/ironrdp-pdu/src/rdp/server_license/licensing_error_message/test.rs +++ b/crates/ironrdp-pdu/src/rdp/server_license/licensing_error_message/test.rs @@ -1,33 +1,63 @@ use lazy_static::lazy_static; use super::*; -use crate::{decode, encode_vec}; +use crate::{ + decode, encode_vec, + rdp::{ + headers::{BasicSecurityHeader, BasicSecurityHeaderFlags}, + server_license::{LicensePdu, PreambleFlags, PreambleVersion}, + }, +}; -pub const LICENSE_MESSAGE_BUFFER: [u8; 12] = [ +const HEADER_MESSAGE_BUFFER: [u8; 8] = [0x80, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x14, 0x00]; + +const LICENSE_MESSAGE_BUFFER: [u8; 12] = [ 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, // message ]; lazy_static! { - pub static ref LICENSING_ERROR_MESSAGE: LicensingErrorMessage = LicensingErrorMessage { - error_code: LicenseErrorCode::StatusValidClient, - state_transition: LicensingStateTransition::NoTransition, - error_info: Vec::new(), + pub static ref LICENSING_ERROR_MESSAGE: LicensePdu = { + let mut pdu = LicensingErrorMessage { + license_header: LicenseHeader { + security_header: BasicSecurityHeader { + flags: BasicSecurityHeaderFlags::LICENSE_PKT, + }, + preamble_message_type: PreambleType::ErrorAlert, + preamble_flags: PreambleFlags::empty(), + preamble_version: PreambleVersion::V3, + preamble_message_size: 0, + }, + error_code: LicenseErrorCode::StatusValidClient, + state_transition: LicensingStateTransition::NoTransition, + error_info: Vec::new(), + }; + pdu.license_header.preamble_message_size = pdu.size() as u16; + pdu.into() }; } #[test] fn from_buffer_correctly_parses_licensing_error_message() { - assert_eq!(*LICENSING_ERROR_MESSAGE, decode(&LICENSE_MESSAGE_BUFFER).unwrap(),); + assert_eq!( + *LICENSING_ERROR_MESSAGE, + decode(&[&HEADER_MESSAGE_BUFFER[..], &LICENSE_MESSAGE_BUFFER[..]].concat()).unwrap(), + ); } #[test] fn to_buffer_correctly_serializes_licensing_error_message() { let buffer = encode_vec(&*LICENSING_ERROR_MESSAGE).unwrap(); - assert_eq!(LICENSE_MESSAGE_BUFFER.as_ref(), buffer.as_slice()); + assert_eq!( + [&HEADER_MESSAGE_BUFFER[..], &LICENSE_MESSAGE_BUFFER[..]].concat(), + buffer + ); } #[test] fn buffer_length_is_correct_for_licensing_error_message() { - assert_eq!(LICENSE_MESSAGE_BUFFER.len(), LICENSING_ERROR_MESSAGE.size()); + assert_eq!( + HEADER_MESSAGE_BUFFER.len() + LICENSE_MESSAGE_BUFFER.len(), + LICENSING_ERROR_MESSAGE.size() + ); } diff --git a/crates/ironrdp-pdu/src/rdp/server_license/server_license_request.rs b/crates/ironrdp-pdu/src/rdp/server_license/server_license_request.rs index 69a2a65d0..8f4cf5cab 100644 --- a/crates/ironrdp-pdu/src/rdp/server_license/server_license_request.rs +++ b/crates/ironrdp-pdu/src/rdp/server_license/server_license_request.rs @@ -6,10 +6,8 @@ mod tests; use cert::{CertificateType, ProprietaryCertificate, X509CertificateChain}; use super::{ - BasicSecurityHeader, BasicSecurityHeaderFlags, BlobHeader, BlobType, LicenseErrorCode, LicenseHeader, - LicensingErrorMessage, LicensingStateTransition, PreambleFlags, PreambleType, PreambleVersion, ServerLicenseError, - BLOB_LENGTH_SIZE, BLOB_TYPE_SIZE, KEY_EXCHANGE_ALGORITHM_RSA, PREAMBLE_SIZE, RANDOM_NUMBER_SIZE, - UTF16_NULL_TERMINATOR_SIZE, UTF8_NULL_TERMINATOR_SIZE, + BlobHeader, BlobType, LicenseHeader, PreambleType, ServerLicenseError, BLOB_LENGTH_SIZE, BLOB_TYPE_SIZE, + KEY_EXCHANGE_ALGORITHM_RSA, RANDOM_NUMBER_SIZE, UTF16_NULL_TERMINATOR_SIZE, UTF8_NULL_TERMINATOR_SIZE, }; use crate::{ cursor::{ReadCursor, WriteCursor}, @@ -28,118 +26,12 @@ const MAX_PRODUCT_ID_LEN: usize = 1024; const RSA_EXCHANGE_ALGORITHM: u32 = 1; -#[derive(Debug, PartialEq, Eq)] -pub enum InitialMessageType { - LicenseRequest(ServerLicenseRequest), - StatusValidClient(LicensingErrorMessage), -} - -// FIXME(#269): this is a helper structure which tries to detect if a -// SERVER_LICENSE_REQUEST PDU is received from the server, or if a -// STATUS_VALID_CLIENT error code is received instead (no need to negotiate -// a license). I think this could be refactored into a more generic struct / enum, -// without trying to be too smart by, e.g., returning errors when a LICENSE_ERROR_MESSAGE -// is received depending on the error code. Parsing code should lend the data received -// from the network without making too much decisions. - -/// Either a SERVER_LICENSE_REQUEST or a LICENSE_ERROR_MESSAGE with the STATUS_VALID_CLIENT code -#[derive(Debug, PartialEq, Eq)] -pub struct InitialServerLicenseMessage { - pub license_header: LicenseHeader, - pub message_type: InitialMessageType, -} - -impl InitialServerLicenseMessage { - const NAME: &'static str = "InitialServerLicenseMessage"; - - pub fn new_status_valid_client_message() -> Self { - let valid_client_message = LicensingErrorMessage { - error_code: LicenseErrorCode::StatusValidClient, - state_transition: LicensingStateTransition::NoTransition, - error_info: Vec::new(), - }; - - Self { - license_header: LicenseHeader { - security_header: BasicSecurityHeader { - flags: BasicSecurityHeaderFlags::LICENSE_PKT, - }, - preamble_message_type: PreambleType::ErrorAlert, - preamble_flags: PreambleFlags::empty(), - preamble_version: PreambleVersion::V3, - preamble_message_size: (PREAMBLE_SIZE + valid_client_message.size()) as u16, - }, - message_type: InitialMessageType::StatusValidClient(valid_client_message), - } - } -} - -impl PduEncode for InitialServerLicenseMessage { - fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> { - self.license_header.encode(dst)?; - - match &self.message_type { - InitialMessageType::LicenseRequest(license_request) => { - license_request.encode(dst)?; - } - InitialMessageType::StatusValidClient(valid_client) => { - valid_client.encode(dst)?; - } - } - - Ok(()) - } - - fn name(&self) -> &'static str { - Self::NAME - } - - fn size(&self) -> usize { - self.license_header.size() - + match &self.message_type { - InitialMessageType::LicenseRequest(license_request) => license_request.size(), - InitialMessageType::StatusValidClient(valid_client) => valid_client.size(), - } - } -} - -impl<'de> PduDecode<'de> for InitialServerLicenseMessage { - fn decode(src: &mut ReadCursor<'de>) -> PduResult { - let license_header = LicenseHeader::decode(src)?; - - match license_header.preamble_message_type { - PreambleType::LicenseRequest => { - let license_request = ServerLicenseRequest::decode(src)?; - - Ok(Self { - license_header, - message_type: InitialMessageType::LicenseRequest(license_request), - }) - } - PreambleType::ErrorAlert => { - let license_error = LicensingErrorMessage::decode(src)?; - - if license_error.error_code == LicenseErrorCode::StatusValidClient - && license_error.state_transition == LicensingStateTransition::NoTransition - { - Ok(Self { - license_header, - message_type: InitialMessageType::StatusValidClient(license_error), - }) - } else { - Err(invalid_message_err!("errorCode", "unexpected error")) - } - } - _ => Err(invalid_message_err!("preambleMessageType", "invalid preamble")), - } - } -} - /// [2.2.2.1] Server License Request (SERVER_LICENSE_REQUEST) /// /// [2.2.2.1]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/e17772e9-9642-4bb6-a2bc-82875dd6da7c #[derive(Debug, PartialEq, Eq)] pub struct ServerLicenseRequest { + pub license_header: LicenseHeader, pub server_random: Vec, pub product_info: ProductInfo, pub server_certificate: Option, @@ -154,18 +46,20 @@ impl ServerLicenseRequest { } } -impl PduEncode for ServerLicenseRequest { - fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> { +impl ServerLicenseRequest { + pub fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> { ensure_size!(in: dst, size: self.size()); + self.license_header.encode(dst)?; + dst.write_slice(&self.server_random); self.product_info.encode(dst)?; - BlobHeader::new(BlobType::KeyExchangeAlgorithm, KEY_EXCHANGE_FIELD_SIZE).encode(dst)?; + BlobHeader::new(BlobType::KEY_EXCHANGE_ALGORITHM, KEY_EXCHANGE_FIELD_SIZE).encode(dst)?; dst.write_u32(KEY_EXCHANGE_ALGORITHM_RSA); let cert_size = self.server_certificate.as_ref().map(|v| v.size()).unwrap_or(0); - BlobHeader::new(BlobType::Certificate, cert_size).encode(dst)?; + BlobHeader::new(BlobType::CERTIFICATE, cert_size).encode(dst)?; if let Some(cert) = &self.server_certificate { cert.encode(dst)?; @@ -180,12 +74,13 @@ impl PduEncode for ServerLicenseRequest { Ok(()) } - fn name(&self) -> &'static str { + pub fn name(&self) -> &'static str { Self::NAME } - fn size(&self) -> usize { - RANDOM_NUMBER_SIZE + pub fn size(&self) -> usize { + self.license_header.size() + + RANDOM_NUMBER_SIZE + self.product_info.size() + BLOB_LENGTH_SIZE * 2 // KeyExchangeBlob + CertificateBlob + BLOB_TYPE_SIZE * 2 // KeyExchangeBlob + CertificateBlob @@ -196,15 +91,19 @@ impl PduEncode for ServerLicenseRequest { } } -impl<'de> PduDecode<'de> for ServerLicenseRequest { - fn decode(src: &mut ReadCursor<'de>) -> PduResult { +impl ServerLicenseRequest { + pub fn decode(license_header: LicenseHeader, src: &mut ReadCursor<'_>) -> PduResult { + if license_header.preamble_message_type != PreambleType::LicenseRequest { + return Err(invalid_message_err!("preambleMessageType", "unexpected preamble type")); + } + ensure_size!(in: src, size: RANDOM_NUMBER_SIZE); let server_random = src.read_slice(RANDOM_NUMBER_SIZE).into(); let product_info = ProductInfo::decode(src)?; let key_exchange_algorithm_blob = BlobHeader::decode(src)?; - if key_exchange_algorithm_blob.blob_type != BlobType::KeyExchangeAlgorithm { + if key_exchange_algorithm_blob.blob_type != BlobType::KEY_EXCHANGE_ALGORITHM { return Err(invalid_message_err!("blobType", "invalid blob type")); } @@ -215,7 +114,7 @@ impl<'de> PduDecode<'de> for ServerLicenseRequest { } let cert_blob = BlobHeader::decode(src)?; - if cert_blob.blob_type != BlobType::Certificate { + if cert_blob.blob_type != BlobType::CERTIFICATE { return Err(invalid_message_err!("blobType", "invalid blob type")); } @@ -239,6 +138,7 @@ impl<'de> PduDecode<'de> for ServerLicenseRequest { } Ok(Self { + license_header, server_random, product_info, server_certificate, @@ -261,7 +161,7 @@ impl PduEncode for Scope { ensure_size!(in: dst, size: self.size()); let data_size = self.0.len() + UTF8_NULL_TERMINATOR_SIZE; - BlobHeader::new(BlobType::Scope, data_size).encode(dst)?; + BlobHeader::new(BlobType::SCOPE, data_size).encode(dst)?; dst.write_slice(self.0.as_bytes()); dst.write_u8(0); // null terminator @@ -280,7 +180,7 @@ impl PduEncode for Scope { impl<'de> PduDecode<'de> for Scope { fn decode(src: &mut ReadCursor<'de>) -> PduResult { let blob_header = BlobHeader::decode(src)?; - if blob_header.blob_type != BlobType::Scope { + if blob_header.blob_type != BlobType::SCOPE { return Err(invalid_message_err!("blobType", "invalid blob type")); } if blob_header.length < UTF8_NULL_TERMINATOR_SIZE { diff --git a/crates/ironrdp-pdu/src/rdp/server_license/server_license_request/cert.rs b/crates/ironrdp-pdu/src/rdp/server_license/server_license_request/cert.rs index 3f4efc56b..b2050ee20 100644 --- a/crates/ironrdp-pdu/src/rdp/server_license/server_license_request/cert.rs +++ b/crates/ironrdp-pdu/src/rdp/server_license/server_license_request/cert.rs @@ -120,10 +120,10 @@ impl PduEncode for ProprietaryCertificate { dst.write_u32(SIGNATURE_ALGORITHM_RSA); dst.write_u32(KEY_EXCHANGE_ALGORITHM_RSA); - BlobHeader::new(BlobType::RsaKey, self.public_key.size()).encode(dst)?; + BlobHeader::new(BlobType::RSA_KEY, self.public_key.size()).encode(dst)?; self.public_key.encode(dst)?; - BlobHeader::new(BlobType::RsaSignature, self.signature.len()).encode(dst)?; + BlobHeader::new(BlobType::RSA_SIGNATURE, self.signature.len()).encode(dst)?; dst.write_slice(&self.signature); Ok(()) @@ -153,13 +153,13 @@ impl<'de> PduDecode<'de> for ProprietaryCertificate { } let key_blob_header = BlobHeader::decode(src)?; - if key_blob_header.blob_type != BlobType::RsaKey { + if key_blob_header.blob_type != BlobType::RSA_KEY { return Err(invalid_message_err!("blobType", "invalid blob type")); } let public_key = RsaPublicKey::decode(src)?; let sig_blob_header = BlobHeader::decode(src)?; - if sig_blob_header.blob_type != BlobType::RsaSignature { + if sig_blob_header.blob_type != BlobType::RSA_SIGNATURE { return Err(invalid_message_err!("blobType", "invalid blob type")); } ensure_size!(in: src, size: sig_blob_header.length); diff --git a/crates/ironrdp-pdu/src/rdp/server_license/server_license_request/tests.rs b/crates/ironrdp-pdu/src/rdp/server_license/server_license_request/tests.rs index 574fa539a..201907c3a 100644 --- a/crates/ironrdp-pdu/src/rdp/server_license/server_license_request/tests.rs +++ b/crates/ironrdp-pdu/src/rdp/server_license/server_license_request/tests.rs @@ -2,8 +2,13 @@ use lazy_static::lazy_static; use super::cert::{RsaPublicKey, PROP_CERT_BLOBS_HEADERS_SIZE, PROP_CERT_NO_BLOBS_SIZE, RSA_KEY_SIZE_WITHOUT_MODULUS}; use super::*; +use crate::rdp::headers::{BasicSecurityHeader, BasicSecurityHeaderFlags}; +use crate::rdp::server_license::{LicensePdu, PreambleFlags, PreambleVersion}; use crate::{decode, encode_vec, PduEncode}; +const LICENSE_HEADER_BUFFER_WITH_CERT: [u8; 8] = [0x80, 0x00, 0x00, 0x00, 0x01, 0x03, 0x9C, 0x08]; +const LICENSE_HEADER_BUFFER_NO_CERT: [u8; 8] = [0x80, 0x00, 0x00, 0x00, 0x01, 0x03, 0x8A, 0x00]; + const SERVER_RANDOM_BUFFER: [u8; 32] = [ 0x84, 0xef, 0xae, 0x20, 0xb1, 0xd5, 0x9e, 0x36, 0x49, 0x1a, 0xe8, 0x2e, 0x0a, 0x99, 0x89, 0xac, 0x49, 0xa6, 0x47, 0x4f, 0x33, 0x9b, 0x5a, 0xb9, 0x95, 0x03, 0xa6, 0xc6, 0xc2, 0x3c, 0x3f, 0x61, @@ -222,20 +227,33 @@ lazy_static! { public_exponent: 0x0001_0001, modulus: Vec::from(MODULUS.as_ref()), }; - pub static ref SERVER_LICENSE_REQUEST: ServerLicenseRequest = ServerLicenseRequest { - server_random: Vec::from(SERVER_RANDOM_BUFFER.as_ref()), - product_info: ProductInfo { - version: 0x60000, - company_name: "Microsoft Corporation".to_string(), - product_id: "A02".to_string(), - }, - server_certificate: Some(ServerCertificate { - issued_permanently: true, - certificate: CertificateType::X509(X509CertificateChain { - certificate_array: vec![Vec::from(CERT_1_BUFFER.as_ref()), Vec::from(CERT_2_BUFFER.as_ref()),], + pub static ref SERVER_LICENSE_REQUEST: LicensePdu = { + let mut req = ServerLicenseRequest { + license_header: LicenseHeader { + security_header: BasicSecurityHeader { + flags: BasicSecurityHeaderFlags::LICENSE_PKT, + }, + preamble_message_type: PreambleType::LicenseRequest, + preamble_flags: PreambleFlags::empty(), + preamble_version: PreambleVersion::V3, + preamble_message_size: 0, + }, + server_random: Vec::from(SERVER_RANDOM_BUFFER.as_ref()), + product_info: ProductInfo { + version: 0x60000, + company_name: "Microsoft Corporation".to_string(), + product_id: "A02".to_string(), + }, + server_certificate: Some(ServerCertificate { + issued_permanently: true, + certificate: CertificateType::X509(X509CertificateChain { + certificate_array: vec![Vec::from(CERT_1_BUFFER.as_ref()), Vec::from(CERT_2_BUFFER.as_ref())], + }), }), - }), - scope_list: vec![Scope(String::from("microsoft.com"))], + scope_list: vec![Scope(String::from("microsoft.com"))], + }; + req.license_header.preamble_message_size = req.size() as u16; + req.into() }; pub static ref X509_CERTIFICATE: ServerCertificate = ServerCertificate { issued_permanently: true, @@ -252,6 +270,7 @@ lazy_static! { #[test] fn from_buffer_correctly_parses_server_license_request() { let request_buffer = [ + &LICENSE_HEADER_BUFFER_WITH_CERT[..], &SERVER_RANDOM_BUFFER[..], &PRODUCT_INFO_BUFFER[..], &KEY_EXCHANGE_LIST_BUFFER[..], @@ -276,6 +295,7 @@ fn from_buffer_correctly_parses_server_license_request_no_certificate() { ]; let request_buffer = [ + &LICENSE_HEADER_BUFFER_NO_CERT[..], &SERVER_RANDOM_BUFFER[..], &PRODUCT_INFO_BUFFER[..], &KEY_EXCHANGE_LIST_BUFFER[..], @@ -284,7 +304,16 @@ fn from_buffer_correctly_parses_server_license_request_no_certificate() { ] .concat(); - let request = ServerLicenseRequest { + let mut request = ServerLicenseRequest { + license_header: LicenseHeader { + security_header: BasicSecurityHeader { + flags: BasicSecurityHeaderFlags::LICENSE_PKT, + }, + preamble_message_type: PreambleType::LicenseRequest, + preamble_flags: PreambleFlags::empty(), + preamble_version: PreambleVersion::V3, + preamble_message_size: 0, + }, server_random: Vec::from(SERVER_RANDOM_BUFFER.as_ref()), product_info: ProductInfo { version: 0x60000, @@ -294,6 +323,8 @@ fn from_buffer_correctly_parses_server_license_request_no_certificate() { server_certificate: None, scope_list: vec![Scope(String::from("microsoft.com"))], }; + request.license_header.preamble_message_size = request.size() as u16; + let request: LicensePdu = request.into(); assert_eq!(request, decode(&request_buffer).unwrap()); } @@ -301,6 +332,7 @@ fn from_buffer_correctly_parses_server_license_request_no_certificate() { #[test] fn to_buffer_correctly_serializes_server_license_request() { let request_buffer = [ + &LICENSE_HEADER_BUFFER_WITH_CERT[..], &SERVER_RANDOM_BUFFER[..], &PRODUCT_INFO_BUFFER[..], &KEY_EXCHANGE_LIST_BUFFER[..], @@ -314,7 +346,16 @@ fn to_buffer_correctly_serializes_server_license_request() { ] .concat(); - let request = ServerLicenseRequest { + let mut request = ServerLicenseRequest { + license_header: LicenseHeader { + security_header: BasicSecurityHeader { + flags: BasicSecurityHeaderFlags::LICENSE_PKT, + }, + preamble_message_type: PreambleType::LicenseRequest, + preamble_flags: PreambleFlags::empty(), + preamble_version: PreambleVersion::V3, + preamble_message_size: 0, + }, server_random: Vec::from(SERVER_RANDOM_BUFFER.as_ref()), product_info: ProductInfo { version: 0x60000, @@ -329,6 +370,8 @@ fn to_buffer_correctly_serializes_server_license_request() { }), scope_list: vec![Scope(String::from("microsoft.com"))], }; + request.license_header.preamble_message_size = request.size() as u16; + let request: LicensePdu = request.into(); let serialized_request = encode_vec(&request).unwrap(); @@ -338,6 +381,7 @@ fn to_buffer_correctly_serializes_server_license_request() { #[test] fn buffer_length_is_correct_for_server_license_request() { let request_buffer = [ + &LICENSE_HEADER_BUFFER_WITH_CERT[..], &SERVER_RANDOM_BUFFER[..], &PRODUCT_INFO_BUFFER[..], &KEY_EXCHANGE_LIST_BUFFER[..], diff --git a/crates/ironrdp-pdu/src/rdp/server_license/server_platform_challenge.rs b/crates/ironrdp-pdu/src/rdp/server_license/server_platform_challenge.rs index 246dd7cae..664c5fd26 100644 --- a/crates/ironrdp-pdu/src/rdp/server_license/server_platform_challenge.rs +++ b/crates/ironrdp-pdu/src/rdp/server_license/server_platform_challenge.rs @@ -1,9 +1,7 @@ #[cfg(test)] mod test; -use super::{ - read_license_header, BlobHeader, BlobType, LicenseHeader, PreambleType, BLOB_LENGTH_SIZE, BLOB_TYPE_SIZE, MAC_SIZE, -}; +use super::{BlobHeader, BlobType, LicenseHeader, PreambleType, BLOB_LENGTH_SIZE, BLOB_TYPE_SIZE, MAC_SIZE}; use crate::{ cursor::{ReadCursor, WriteCursor}, PduDecode, PduEncode, PduResult, @@ -27,31 +25,33 @@ impl ServerPlatformChallenge { const FIXED_PART_SIZE: usize = CONNECT_FLAGS_FIELD_SIZE + MAC_SIZE + BLOB_LENGTH_SIZE + BLOB_TYPE_SIZE; } -impl PduEncode for ServerPlatformChallenge { - fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> { +impl ServerPlatformChallenge { + pub fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> { ensure_size!(in: dst, size: self.size()); self.license_header.encode(dst)?; dst.write_u32(0); // connect_flags, ignored - BlobHeader::new(BlobType::Any, self.encrypted_platform_challenge.len()).encode(dst)?; + BlobHeader::new(BlobType::ANY, self.encrypted_platform_challenge.len()).encode(dst)?; dst.write_slice(&self.encrypted_platform_challenge); dst.write_slice(&self.mac_data); Ok(()) } - fn name(&self) -> &'static str { + pub fn name(&self) -> &'static str { Self::NAME } - fn size(&self) -> usize { + pub fn size(&self) -> usize { Self::FIXED_PART_SIZE + self.license_header.size() + self.encrypted_platform_challenge.len() } } -impl<'de> PduDecode<'de> for ServerPlatformChallenge { - fn decode(src: &mut ReadCursor<'de>) -> PduResult { - let license_header = read_license_header(PreambleType::PlatformChallenge, src)?; +impl ServerPlatformChallenge { + pub fn decode(license_header: LicenseHeader, src: &mut ReadCursor<'_>) -> PduResult { + if license_header.preamble_message_type != PreambleType::PlatformChallenge { + return Err(invalid_message_err!("preambleMessageType", "unexpected preamble type")); + } ensure_size!(in: src, size: 4); let _connect_flags = src.read_u32(); diff --git a/crates/ironrdp-pdu/src/rdp/server_license/server_platform_challenge/test.rs b/crates/ironrdp-pdu/src/rdp/server_license/server_platform_challenge/test.rs index b28273711..03328ec45 100644 --- a/crates/ironrdp-pdu/src/rdp/server_license/server_platform_challenge/test.rs +++ b/crates/ironrdp-pdu/src/rdp/server_license/server_platform_challenge/test.rs @@ -2,7 +2,8 @@ use lazy_static::lazy_static; use super::*; use crate::rdp::server_license::{ - BasicSecurityHeader, BasicSecurityHeaderFlags, PreambleFlags, PreambleVersion, BASIC_SECURITY_HEADER_SIZE, + BasicSecurityHeader, BasicSecurityHeaderFlags, LicensePdu, PreambleFlags, PreambleVersion, + BASIC_SECURITY_HEADER_SIZE, }; use crate::{decode, encode_vec}; @@ -10,8 +11,8 @@ const PLATFORM_CHALLENGE_BUFFER: [u8; 42] = [ 0x80, 0x00, // flags 0x00, 0x00, // flagsHi 0x02, 0x03, 0x26, 0x00, // preamble - 0x00, 0x00, 0x00, 0x00, // connect flags - 0x00, 0x00, // ignored + 0x00, 0x00, 0x00, 0x00, // connect_flags (ignored) + 0x00, 0x00, // blob_type, ignored; 0x0a, 0x00, // blob len 0x46, 0x37, 0x85, 0x54, 0x8e, 0xc5, 0x91, 0x34, 0x97, 0x5d, // challenge 0x38, 0x23, 0x62, 0x5d, 0x10, 0x8b, 0x93, 0xc3, 0xf1, 0xe4, 0x67, 0x1f, 0x4a, 0xb6, 0x00, 0x0a, // mac data @@ -26,7 +27,7 @@ const MAC_DATA_BUFFER: [u8; MAC_SIZE] = [ ]; lazy_static! { - pub static ref PLATFORM_CHALLENGE: ServerPlatformChallenge = ServerPlatformChallenge { + pub static ref PLATFORM_CHALLENGE: LicensePdu = ServerPlatformChallenge { license_header: LicenseHeader { security_header: BasicSecurityHeader { flags: BasicSecurityHeaderFlags::LICENSE_PKT, @@ -38,7 +39,8 @@ lazy_static! { }, encrypted_platform_challenge: Vec::from(CHALLENGE_BUFFER.as_ref()), mac_data: Vec::from(MAC_DATA_BUFFER.as_ref()), - }; + } + .into(); } #[test] @@ -46,6 +48,15 @@ fn from_buffer_correctly_parses_server_platform_challenge() { assert_eq!(*PLATFORM_CHALLENGE, decode(PLATFORM_CHALLENGE_BUFFER.as_ref()).unwrap()); } +#[test] +fn from_buffer_correctly_parses_server_platform_challenge_resiliently() { + let mut buffer = PLATFORM_CHALLENGE_BUFFER; + // Change blob type to junk value 0xbeef + buffer[12] = 0xbe; + buffer[13] = 0xef; + assert_eq!(*PLATFORM_CHALLENGE, decode(buffer.as_ref()).unwrap()); +} + #[test] fn to_buffer_correctly_serializes_server_platform_challenge() { let serialized_platform_challenge = encode_vec(&*PLATFORM_CHALLENGE).unwrap(); diff --git a/crates/ironrdp-pdu/src/rdp/server_license/server_upgrade_license.rs b/crates/ironrdp-pdu/src/rdp/server_license/server_upgrade_license.rs index e26c6b018..0b2192c43 100644 --- a/crates/ironrdp-pdu/src/rdp/server_license/server_upgrade_license.rs +++ b/crates/ironrdp-pdu/src/rdp/server_license/server_upgrade_license.rs @@ -2,8 +2,8 @@ mod tests; use super::{ - read_license_header, BlobHeader, BlobType, LicenseEncryptionData, LicenseHeader, PreambleType, ServerLicenseError, - BLOB_LENGTH_SIZE, BLOB_TYPE_SIZE, MAC_SIZE, UTF16_NULL_TERMINATOR_SIZE, UTF8_NULL_TERMINATOR_SIZE, + BlobHeader, BlobType, LicenseEncryptionData, LicenseHeader, PreambleType, ServerLicenseError, BLOB_LENGTH_SIZE, + BLOB_TYPE_SIZE, MAC_SIZE, UTF16_NULL_TERMINATOR_SIZE, UTF8_NULL_TERMINATOR_SIZE, }; use crate::crypto::rc4::Rc4; use crate::cursor::{ReadCursor, WriteCursor}; @@ -41,31 +41,29 @@ impl ServerUpgradeLicense { const NAME: &'static str = "ServerUpgradeLicense"; } -impl PduEncode for ServerUpgradeLicense { - fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> { +impl ServerUpgradeLicense { + pub fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> { ensure_size!(in: dst, size: self.size()); self.license_header.encode(dst)?; - BlobHeader::new(BlobType::EncryptedData, self.encrypted_license_info.len()).encode(dst)?; + BlobHeader::new(BlobType::ENCRYPTED_DATA, self.encrypted_license_info.len()).encode(dst)?; dst.write_slice(&self.encrypted_license_info); dst.write_slice(&self.mac_data); Ok(()) } - fn name(&self) -> &'static str { + pub fn name(&self) -> &'static str { Self::NAME } - fn size(&self) -> usize { + pub fn size(&self) -> usize { self.license_header.size() + BLOB_LENGTH_SIZE + BLOB_TYPE_SIZE + self.encrypted_license_info.len() + MAC_SIZE } } -impl<'de> PduDecode<'de> for ServerUpgradeLicense { - fn decode(src: &mut ReadCursor<'de>) -> PduResult { - let license_header = read_license_header(PreambleType::NewLicense, src)?; - +impl ServerUpgradeLicense { + pub fn decode(license_header: LicenseHeader, src: &mut ReadCursor<'_>) -> PduResult { if license_header.preamble_message_type != PreambleType::UpgradeLicense && license_header.preamble_message_type != PreambleType::NewLicense { @@ -76,7 +74,7 @@ impl<'de> PduDecode<'de> for ServerUpgradeLicense { } let encrypted_license_info_blob = BlobHeader::decode(src)?; - if encrypted_license_info_blob.blob_type != BlobType::EncryptedData { + if encrypted_license_info_blob.blob_type != BlobType::ENCRYPTED_DATA { return Err(invalid_message_err!("blobType", "unexpected blob type")); } diff --git a/crates/ironrdp-pdu/src/rdp/server_license/server_upgrade_license/tests.rs b/crates/ironrdp-pdu/src/rdp/server_license/server_upgrade_license/tests.rs index 959599d3b..85d78a27a 100644 --- a/crates/ironrdp-pdu/src/rdp/server_license/server_upgrade_license/tests.rs +++ b/crates/ironrdp-pdu/src/rdp/server_license/server_upgrade_license/tests.rs @@ -2,8 +2,8 @@ use lazy_static::lazy_static; use super::*; use crate::rdp::server_license::{ - BasicSecurityHeader, BasicSecurityHeaderFlags, PreambleFlags, PreambleVersion, BASIC_SECURITY_HEADER_SIZE, - PREAMBLE_SIZE, + BasicSecurityHeader, BasicSecurityHeaderFlags, LicensePdu, PreambleFlags, PreambleVersion, + BASIC_SECURITY_HEADER_SIZE, PREAMBLE_SIZE, }; use crate::{decode, encode_vec}; @@ -252,7 +252,7 @@ lazy_static! { product_id: "A02".to_string(), license_info: Vec::from(&NEW_LICENSE_INFORMATION_BUFFER[NEW_LICENSE_INFORMATION_BUFFER.len() - 0x0799..]), }; - pub static ref SERVER_UPGRADE_LICENSE: ServerUpgradeLicense = ServerUpgradeLicense { + pub static ref SERVER_UPGRADE_LICENSE: LicensePdu = ServerUpgradeLicense { license_header: LicenseHeader { security_header: BasicSecurityHeader { flags: BasicSecurityHeaderFlags::LICENSE_PKT, @@ -266,7 +266,8 @@ lazy_static! { &SERVER_UPGRADE_LICENSE_BUFFER[12..SERVER_UPGRADE_LICENSE_BUFFER.len() - MAC_SIZE] ), mac_data: Vec::from(MAC_DATA.as_ref()), - }; + } + .into(); } #[test] diff --git a/crates/ironrdp-pdu/src/rdp/server_license/tests.rs b/crates/ironrdp-pdu/src/rdp/server_license/tests.rs index 343a504ef..26383cd64 100644 --- a/crates/ironrdp-pdu/src/rdp/server_license/tests.rs +++ b/crates/ironrdp-pdu/src/rdp/server_license/tests.rs @@ -1,7 +1,7 @@ use lazy_static::lazy_static; use super::*; -use crate::{decode, encode_vec, PduErrorKind}; +use crate::{decode, encode_vec}; const LICENSE_HEADER_BUFFER: [u8; 8] = [ 0x80, 0x00, // flags @@ -35,12 +35,6 @@ pub const STATUS_VALID_CLIENT_BUFFER: [u8; 20] = [ 0xff, 0x03, 0x10, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, ]; -pub const UNEXPECTED_ERROR_BUFFER: [u8; 20] = [ - 0x80, 0x00, // flags - 0x00, 0x00, // flagsHi - 0xff, 0x03, 0x10, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, -]; - lazy_static! { pub static ref LICENSE_HEADER: LicenseHeader = LicenseHeader { security_header: BasicSecurityHeader { @@ -56,7 +50,7 @@ lazy_static! { #[test] fn read_blob_header_handles_wrong_type_correctly() { let h = decode::(&BLOB_BUFFER).unwrap(); - assert_ne!(h.blob_type, BlobType::Certificate); + assert_ne!(h.blob_type, BlobType::CERTIFICATE); } #[test] @@ -71,16 +65,20 @@ fn read_blob_header_handles_invalid_type_correctly() { 0x00, // blob data ]; - match decode::(&invalid_blob_buffer) { - Err(e) if matches!(e.kind(), PduErrorKind::InvalidMessage { .. }) => (), - _ => panic!("expected invalid message error"), - } + let header = decode::(&invalid_blob_buffer).unwrap(); + assert_eq!( + header, + BlobHeader { + blob_type: BlobType(0x99), + length: 0x48 + } + ) } #[test] fn read_blob_header_reads_blob_correctly() { let blob = decode::(&BLOB_BUFFER).unwrap(); - assert_eq!(blob.blob_type, BlobType::RsaSignature); + assert_eq!(blob.blob_type, BlobType::RSA_SIGNATURE); assert_eq!(blob.length, BLOB_BUFFER.len() - 4); } @@ -89,7 +87,7 @@ fn write_blob_header_writes_blob_header_correctly() { let correct_blob_header = &BLOB_BUFFER[..4]; let blob_data = &BLOB_BUFFER[4..]; - let blob = BlobHeader::new(BlobType::RsaSignature, blob_data.len()); + let blob = BlobHeader::new(BlobType::RSA_SIGNATURE, blob_data.len()); let buffer = encode_vec(&blob).unwrap(); assert_eq!(correct_blob_header, buffer.as_slice()); @@ -135,21 +133,28 @@ fn buffer_length_is_correct_for_license_header() { #[test] fn read_license_header_reads_correctly() { - decode::(&PLATFORM_CHALLENGE_BUFFER).unwrap(); + decode::(&PLATFORM_CHALLENGE_BUFFER).unwrap(); } #[test] fn read_license_header_handles_valid_client_correctly() { - match decode::(&STATUS_VALID_CLIENT_BUFFER) { - Err(e) if matches!(e.kind(), PduErrorKind::InvalidMessage { .. }) => (), - e => panic!("The function has return an invalid error: {:?}", e), - } -} - -#[test] -fn read_license_header_handles_unexpected_error_correctly() { - match decode::(&UNEXPECTED_ERROR_BUFFER) { - Err(e) if matches!(e.kind(), PduErrorKind::InvalidMessage { .. }) => (), - e => panic!("The function has return an invalid error: {:?}", e), - } + let pdu = decode::(&STATUS_VALID_CLIENT_BUFFER).unwrap(); + assert_eq!( + pdu, + LicensingErrorMessage { + license_header: LicenseHeader { + security_header: BasicSecurityHeader { + flags: BasicSecurityHeaderFlags::LICENSE_PKT, + }, + preamble_message_type: PreambleType::ErrorAlert, + preamble_flags: PreambleFlags::empty(), + preamble_version: PreambleVersion::V3, + preamble_message_size: 0x10, + }, + error_code: LicenseErrorCode::StatusValidClient, + state_transition: LicensingStateTransition::NoTransition, + error_info: Vec::new() + } + .into() + ); } diff --git a/crates/ironrdp-session/src/x224/mod.rs b/crates/ironrdp-session/src/x224/mod.rs index 752ab90b2..9885e521c 100644 --- a/crates/ironrdp-session/src/x224/mod.rs +++ b/crates/ironrdp-session/src/x224/mod.rs @@ -149,7 +149,7 @@ impl Processor { } _ => Err(reason_err!( "IO channel", - "unexpected PDU: expected Session Save Info PDU, got: {:?}", + "unhandled PDU: {:?}", ctx.pdu.as_short_name() )), } diff --git a/crates/ironrdp-testsuite-core/src/rdp.rs b/crates/ironrdp-testsuite-core/src/rdp.rs index 4af6b2a7c..c86c2db25 100644 --- a/crates/ironrdp-testsuite-core/src/rdp.rs +++ b/crates/ironrdp-testsuite-core/src/rdp.rs @@ -142,7 +142,10 @@ pub const SERVER_FONT_MAP_BUFFER: [u8; 26] = [ pub const SERVER_LICENSE_BUFFER: [u8; 20] = [ 0x80, 0x00, // flags 0x00, 0x00, // flagsHi - 0xff, 0x03, 0x10, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xff, // preamble_message_type + 0x03, // preamble_flags | preamble_version + 0x14, // preamble_message_size + 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, ]; lazy_static! { @@ -152,21 +155,23 @@ lazy_static! { }, client_info: CLIENT_INFO_UNICODE.clone(), }; - pub static ref SERVER_LICENSE_PDU: InitialServerLicenseMessage = InitialServerLicenseMessage { - license_header: LicenseHeader { - security_header: BasicSecurityHeader { - flags: BasicSecurityHeaderFlags::LICENSE_PKT, + pub static ref SERVER_LICENSE_PDU: LicensePdu = { + let mut pdu = LicensingErrorMessage { + license_header: LicenseHeader { + security_header: BasicSecurityHeader { + flags: BasicSecurityHeaderFlags::LICENSE_PKT, + }, + preamble_message_type: PreambleType::ErrorAlert, + preamble_flags: PreambleFlags::empty(), + preamble_version: PreambleVersion::V3, + preamble_message_size: 0, }, - preamble_message_type: PreambleType::ErrorAlert, - preamble_flags: PreambleFlags::empty(), - preamble_version: PreambleVersion::V3, - preamble_message_size: (SERVER_LICENSE_BUFFER.len() - BASIC_SECURITY_HEADER_SIZE) as u16 - }, - message_type: InitialMessageType::StatusValidClient(LicensingErrorMessage { error_code: LicenseErrorCode::StatusValidClient, state_transition: LicensingStateTransition::NoTransition, error_info: Vec::new(), - }) + }; + pdu.license_header.preamble_message_size = pdu.size() as u16; + pdu.into() }; pub static ref SERVER_DEMAND_ACTIVE_PDU: ShareControlHeader = ShareControlHeader { share_control_pdu: ShareControlPdu::ServerDemandActive(SERVER_DEMAND_ACTIVE.clone()),