fix: make license parsing and protocol more resilient (#436)

* Converts `BlobType` to a resilient parsing style
* Makes the licensing parsing and handling more resilient to make it compatible with xrdp
This commit is contained in:
Isaiah Becker-Mayer 2024-04-25 00:23:20 -05:00 committed by GitHub
parent a232b4ee0f
commit 5c42ade597
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 776 additions and 580 deletions

6
Cargo.lock generated
View file

@ -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",
]

View file

@ -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");

View file

@ -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;

View file

@ -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
);
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);
}
if control_pdu.grant_id == self.user_channel_id
&& control_pdu.control_id == u32::from(SERVER_CHANNEL_ID)
{
debug!("Server Control (Granted Control)");
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(

View file

@ -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::<server_license::InitialServerLicenseMessage>()
.with_context("decode initial server license PDU")?;
let license_pdu = send_data_indication_ctx
.decode_user_data::<LicensePdu>()
.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::<LicensePdu>(
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::<server_license::ServerPlatformChallenge>()
.with_context("decode SERVER_PLATFORM_CHALLENGE")
{
Ok(challenge) => {
let license_pdu = send_data_indication_ctx
.decode_user_data::<LicensePdu>()
.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::<LicensePdu>(
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.
// Its expected that fixing #263 will also lead to a better alternative here.
let license_pdu = send_data_indication_ctx
.decode_user_data::<LicensePdu>()
.with_context("decode during SERVER_NEW_LICENSE/LicenseExchangeState::UpgradeLicense")?;
match send_data_indication_ctx
.decode_user_data::<server_license::ServerUpgradeLicense>()
.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<T, Fn>(error: ConnectorError, op: Fn) -> ConnectorResult<T>
where
Fn: FnOnce(&server_license::LicensingErrorMessage) -> T,
{
match std::error::Error::source(&error)
.and_then(|source| source.downcast_ref::<server_license::ServerLicenseError>())
{
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),
}
}

View file

@ -35,11 +35,7 @@ pub fn pdu_decode(data: &[u8]) {
let _ = decode::<gcc::ConferenceCreateRequest>(data);
let _ = decode::<gcc::ConferenceCreateResponse>(data);
let _ = decode::<server_license::ClientNewLicenseRequest>(data);
let _ = decode::<server_license::ClientPlatformChallengeResponse>(data);
let _ = decode::<server_license::InitialServerLicenseMessage>(data);
let _ = decode::<server_license::ServerLicenseRequest>(data);
let _ = decode::<server_license::ServerPlatformChallenge>(data);
let _ = decode::<server_license::LicensePdu>(data);
let _ = decode::<vc::ChannelPduHeader>(data);

View file

@ -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<u8>),
DrawNineGridCache(Vec<u8>),
DrawGdiPlus(Vec<u8>),
Rail(Vec<u8>),
WindowList(Vec<u8>),
FrameAcknowledge(FrameAcknowledge),
BitmapCacheV3(Vec<u8>),
}
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<Self> {
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,

View file

@ -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);

View file

@ -322,6 +322,18 @@ pub enum ShareDataPdu {
ShutdownDenied,
SuppressOutput(SuppressOutputPdu),
RefreshRectangle(RefreshRectanglePdu),
Update(Vec<u8>),
Pointer(Vec<u8>),
PlaySound(Vec<u8>),
SetKeyboardIndicators(Vec<u8>),
BitmapCachePersistentList(Vec<u8>),
BitmapCacheErrorPdu(Vec<u8>),
SetKeyboardImeStatus(Vec<u8>),
OffscreenCacheErrorPdu(Vec<u8>),
DrawNineGridErrorPdu(Vec<u8>),
DrawGdiPusErrorPdu(Vec<u8>),
ArcStatusPdu(Vec<u8>),
StatusInfoPdu(Vec<u8>),
}
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(),
}
}
}

View file

@ -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<PduError> for ServerLicenseError {
}
}
impl From<LicensingErrorMessage> 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<Self> {
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<u8> {
md5.finalize().to_vec()
}
fn read_license_header(
required_preamble_message_type: PreambleType,
src: &mut ReadCursor<'_>,
) -> Result<LicenseHeader, PduError> {
let license_header = LicenseHeader::decode(src)?;
#[derive(Debug, PartialEq)]
pub enum LicensePdu {
ClientNewLicenseRequest(ClientNewLicenseRequest),
ClientPlatformChallengeResponse(ClientPlatformChallengeResponse),
ServerLicenseRequest(ServerLicenseRequest),
ServerPlatformChallenge(ServerPlatformChallenge),
ServerUpgradeLicense(ServerUpgradeLicense),
LicensingErrorMessage(LicensingErrorMessage),
}
// 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.
impl<'de> PduDecode<'de> for LicensePdu {
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
let license_header = LicenseHeader::decode(src)?;
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"));
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())
}
} else {
return Err(invalid_message_err!("preambleType", "got unexptected preamble type"));
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())
}
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),
}
}
Ok(license_header)
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<ClientNewLicenseRequest> for LicensePdu {
fn from(pdu: ClientNewLicenseRequest) -> Self {
Self::ClientNewLicenseRequest(pdu)
}
}
impl From<ClientPlatformChallengeResponse> for LicensePdu {
fn from(pdu: ClientPlatformChallengeResponse) -> Self {
Self::ClientPlatformChallengeResponse(pdu)
}
}
impl From<ServerLicenseRequest> for LicensePdu {
fn from(pdu: ServerLicenseRequest) -> Self {
Self::ServerLicenseRequest(pdu)
}
}
impl From<ServerPlatformChallenge> for LicensePdu {
fn from(pdu: ServerPlatformChallenge) -> Self {
Self::ServerPlatformChallenge(pdu)
}
}
impl From<ServerUpgradeLicense> for LicensePdu {
fn from(pdu: ServerUpgradeLicense) -> Self {
Self::ServerUpgradeLicense(pdu)
}
}
impl From<LicensingErrorMessage> for LicensePdu {
fn from(pdu: LicensingErrorMessage) -> Self {
Self::LicensingErrorMessage(pdu)
}
}

View file

@ -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<Self> {
let license_header = LicenseHeader::decode(src)?;
impl ClientNewLicenseRequest {
pub fn decode(license_header: LicenseHeader, src: &mut ReadCursor<'_>) -> PduResult<Self> {
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);

View file

@ -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<u8> = {
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::<LicensePdu>::into(client_new_license_request),
*CLIENT_NEW_LICENSE_REQUEST
);
}
_ => panic!("Invalid license pdu"),
}
}
#[test]

View file

@ -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<Self> {
let license_header = LicenseHeader::decode(src)?;
impl ClientPlatformChallengeResponse {
pub fn decode(license_header: LicenseHeader, src: &mut ReadCursor<'_>) -> PduResult<Self> {
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);

View file

@ -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]

View file

@ -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<u8>,
@ -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<Self> {
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<Self> {
ensure_fixed_part_size!(in: src);
impl LicensingErrorMessage {
pub fn decode(license_header: LicenseHeader, src: &mut ReadCursor<'_>) -> PduResult<Self> {
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,

View file

@ -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()
);
}

View file

@ -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<Self> {
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<u8>,
pub product_info: ProductInfo,
pub server_certificate: Option<ServerCertificate>,
@ -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<Self> {
impl ServerLicenseRequest {
pub fn decode(license_header: LicenseHeader, src: &mut ReadCursor<'_>) -> PduResult<Self> {
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<Self> {
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 {

View file

@ -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);

View file

@ -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[..],

View file

@ -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<Self> {
let license_header = read_license_header(PreambleType::PlatformChallenge, src)?;
impl ServerPlatformChallenge {
pub fn decode(license_header: LicenseHeader, src: &mut ReadCursor<'_>) -> PduResult<Self> {
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();

View file

@ -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();

View file

@ -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<Self> {
let license_header = read_license_header(PreambleType::NewLicense, src)?;
impl ServerUpgradeLicense {
pub fn decode(license_header: LicenseHeader, src: &mut ReadCursor<'_>) -> PduResult<Self> {
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"));
}

View file

@ -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]

View file

@ -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::<BlobHeader>(&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::<BlobHeader>(&invalid_blob_buffer) {
Err(e) if matches!(e.kind(), PduErrorKind::InvalidMessage { .. }) => (),
_ => panic!("expected invalid message error"),
}
let header = decode::<BlobHeader>(&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::<BlobHeader>(&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::<ServerPlatformChallenge>(&PLATFORM_CHALLENGE_BUFFER).unwrap();
decode::<LicensePdu>(&PLATFORM_CHALLENGE_BUFFER).unwrap();
}
#[test]
fn read_license_header_handles_valid_client_correctly() {
match decode::<ServerPlatformChallenge>(&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::<ServerPlatformChallenge>(&UNEXPECTED_ERROR_BUFFER) {
Err(e) if matches!(e.kind(), PduErrorKind::InvalidMessage { .. }) => (),
e => panic!("The function has return an invalid error: {:?}", e),
}
let pdu = decode::<LicensePdu>(&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()
);
}

View file

@ -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()
)),
}

View file

@ -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()),