1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#[cfg(test)]
pub mod test;

pub mod capability_sets;
pub mod server_license;
pub mod session_info;
pub mod vc;

mod client_info;
mod finalization_messages;
mod headers;
mod server_error_info;

pub use self::{
    capability_sets::{
        CapabilitySet, CapabilitySetsError, ClientConfirmActive, DemandActive, ServerDemandActive,
        VirtualChannel, SERVER_CHANNEL_ID,
    },
    client_info::{
        AddressFamily, ClientInfo, ClientInfoFlags, CompressionType, Credentials, DayOfWeek,
        DayOfWeekOccurrence, ExtendedClientInfo, ExtendedClientOptionalInfo, Month,
        PerformanceFlags, SystemTime, TimezoneInfo,
    },
    finalization_messages::{
        ControlAction, ControlPdu, FontPdu, MonitorLayoutPdu, SequenceFlags, SynchronizePdu,
    },
    headers::{
        BasicSecurityHeader, BasicSecurityHeaderFlags, CompressionFlags, ShareControlHeader,
        ShareControlPdu, ShareControlPduType, ShareDataHeader, ShareDataPdu, ShareDataPduType,
        StreamPriority, BASIC_SECURITY_HEADER_SIZE,
    },
    server_error_info::{
        ErrorInfo, ProtocolIndependentCode, ProtocolIndependentConnectionBrokerCode,
        ProtocolIndependentLicensingCode, RdpSpecificCode, ServerSetErrorInfoError,
        ServerSetErrorInfoPdu,
    },
};

use std::io;

use failure::Fail;

use self::{
    client_info::ClientInfoError, finalization_messages::FinalizationMessagesError,
    server_license::ServerLicenseError,
};
use crate::{impl_from_error, PduParsing};

#[derive(Debug, Clone, PartialEq)]
pub struct ClientInfoPdu {
    pub security_header: BasicSecurityHeader,
    pub client_info: ClientInfo,
}

impl PduParsing for ClientInfoPdu {
    type Error = RdpError;

    fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
        let security_header = BasicSecurityHeader::from_buffer(&mut stream)?;
        if security_header
            .flags
            .contains(BasicSecurityHeaderFlags::INFO_PKT)
        {
            let client_info = ClientInfo::from_buffer(&mut stream)?;

            Ok(Self {
                security_header,
                client_info,
            })
        } else {
            Err(RdpError::InvalidPdu(String::from(
                "Expected ClientInfo PDU, got invalid SecurityHeader flags",
            )))
        }
    }

    fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
        self.security_header.to_buffer(&mut stream)?;
        self.client_info.to_buffer(&mut stream)?;

        Ok(())
    }

    fn buffer_length(&self) -> usize {
        self.security_header.buffer_length() + self.client_info.buffer_length()
    }
}

#[derive(Debug, Fail)]
pub enum RdpError {
    #[fail(display = "IO error: {}", _0)]
    IOError(#[fail(cause)] io::Error),
    #[fail(display = "Client Info PDU error: {}", _0)]
    ClientInfoError(ClientInfoError),
    #[fail(display = "Server License PDU error: {}", _0)]
    ServerLicenseError(ServerLicenseError),
    #[fail(display = "Capability sets error: {}", _0)]
    CapabilitySetsError(CapabilitySetsError),
    #[fail(display = "Finalization PDUs error: {}", _0)]
    FinalizationMessagesError(FinalizationMessagesError),
    #[fail(display = "Invalid RDP security header")]
    InvalidSecurityHeader,
    #[fail(display = "Invalid RDP Share Control Header: {}", _0)]
    InvalidShareControlHeader(String),
    #[fail(display = "Invalid RDP Share Data Header: {}", _0)]
    InvalidShareDataHeader(String),
    #[fail(display = "Invalid RDP Connection Sequence PDU")]
    InvalidPdu(String),
    #[fail(display = "Unexpected RDP Share Control Header PDU type: {:?}", _0)]
    UnexpectedShareControlPdu(ShareControlPduType),
    #[fail(display = "Unexpected RDP Share Data Header PDU type: {:?}", _0)]
    UnexpectedShareDataPdu(ShareDataPduType),
    #[fail(display = "Save session info PDU error: {}", _0)]
    SaveSessionInfoError(session_info::SessionError),
    #[fail(display = "Server set error info PDU error: {}", _0)]
    ServerSetErrorInfoError(ServerSetErrorInfoError),
}

impl_from_error!(io::Error, RdpError, RdpError::IOError);
impl_from_error!(ClientInfoError, RdpError, RdpError::ClientInfoError);
impl_from_error!(ServerLicenseError, RdpError, RdpError::ServerLicenseError);
impl_from_error!(CapabilitySetsError, RdpError, RdpError::CapabilitySetsError);
impl_from_error!(
    FinalizationMessagesError,
    RdpError,
    RdpError::FinalizationMessagesError
);
impl_from_error!(
    session_info::SessionError,
    RdpError,
    RdpError::SaveSessionInfoError
);
impl_from_error!(
    ServerSetErrorInfoError,
    RdpError,
    RdpError::ServerSetErrorInfoError
);

impl From<RdpError> for io::Error {
    fn from(e: RdpError) -> io::Error {
        io::Error::new(
            io::ErrorKind::Other,
            format!("RDP Connection Sequence error: {}", e),
        )
    }
}