use model::data::{Component, Check, DynOption, U16, MessageOption, U32, DataType, Message};
use model::error::{RdpResult, Error, RdpError, RdpErrorKind};
use std::io::{Cursor, Read};
use num_enum::TryFromPrimitive;
use std::convert::TryFrom;
pub enum LicenseMessage {
NewLicense,
ErrorAlert(Component)
}
#[repr(u8)]
#[allow(dead_code)]
enum Preambule {
PreambleVersion20 = 0x2,
PreambleVersion30 = 0x3,
ExtendedErrorMsgSupported = 0x80
}
#[repr(u8)]
#[derive(TryFromPrimitive)]
pub enum MessageType {
LicenseRequest = 0x01,
PlatformChallenge = 0x02,
NewLicense = 0x03,
UpgradeLicense = 0x04,
LicenseInfo = 0x12,
NewLicenseRequest = 0x13,
PlatformChallengeResponse = 0x15,
ErrorAlert = 0xFF
}
#[repr(u32)]
#[derive(PartialEq, Eq, TryFromPrimitive)]
pub enum ErrorCode {
ErrInvalidServerCertificate = 0x00000001,
ErrNoLicense = 0x00000002,
ErrInvalidScope = 0x00000004,
ErrNoLicenseServer = 0x00000006,
StatusValidClient = 0x00000007,
ErrInvalidClient = 0x00000008,
ErrInvalidProductid = 0x0000000B,
ErrInvalidMessageLen = 0x0000000C,
ErrInvalidMac = 0x00000003
}
#[repr(u32)]
#[derive(PartialEq, Eq, TryFromPrimitive)]
pub enum StateTransition {
StTotalAbort = 0x00000001,
StNoTransition = 0x00000002,
StResetPhaseToStart = 0x00000003,
StResendLastMessage = 0x00000004
}
fn preamble() -> Component {
component![
"bMsgtype" => 0 as u8,
"flag" => Check::new(Preambule::PreambleVersion30 as u8),
"wMsgSize" => DynOption::new(U16::LE(0), |size| MessageOption::Size("message".to_string(), size.inner() as usize - 4)),
"message" => Vec::<u8>::new()
]
}
fn license_binary_blob() -> Component {
component![
"wBlobType" => U16::LE(0),
"wBlobLen" => DynOption::new(U16::LE(0), | size | MessageOption::Size("blobData".to_string(), size.inner() as usize)),
"blobData" => Vec::<u8>::new()
]
}
fn licensing_error_message() -> Component {
component![
"dwErrorCode" => U32::LE(0),
"dwStateTransition" => U32::LE(0),
"blob" => license_binary_blob()
]
}
fn parse_payload(payload: &Component) -> RdpResult<LicenseMessage> {
match MessageType::try_from(cast!(DataType::U8, payload["bMsgtype"])?)? {
MessageType::NewLicense => Ok(LicenseMessage::NewLicense),
MessageType::ErrorAlert => {
let mut message = licensing_error_message();
let mut stream = Cursor::new(cast!(DataType::Slice, payload["message"])?);
message.read(&mut stream)?;
Ok(LicenseMessage::ErrorAlert(message))
}
_ => Err(Error::RdpError(RdpError::new(RdpErrorKind::NotImplemented, "Licensing nego not implemented")))
}
}
pub fn client_connect(s: &mut dyn Read) -> RdpResult<()> {
let mut license_message = preamble();
license_message.read(s)?;
match parse_payload(&license_message)? {
LicenseMessage::NewLicense => Ok(()),
LicenseMessage::ErrorAlert(blob) => {
if ErrorCode::try_from(cast!(DataType::U32, blob["dwErrorCode"])?)? == ErrorCode::StatusValidClient &&
StateTransition::try_from(cast!(DataType::U32, blob["dwStateTransition"])?)? == StateTransition::StNoTransition {
Ok(())
} else {
Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidRespond, "Server reject license, Actually license nego is not implemented")))
}
}
}
}