rdp/core/
tpkt.rs

1use model::link::{Link};
2use model::data::{Message, U16, Component, Trame};
3use model::error::{RdpResult, RdpError, RdpErrorKind, Error};
4use std::io::{Cursor, Write, Read};
5use nla::cssp::cssp_connect;
6use nla::sspi::AuthenticationProtocol;
7
8/// TPKT must implement this two kind of payload
9pub enum Payload {
10    Raw(Cursor<Vec<u8>>),
11    FastPath(u8, Cursor<Vec<u8>>)
12}
13
14/// TPKT action header
15/// # see : https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/b8e7c588-51cb-455b-bb73-92d480903133
16/// # see : https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/68b5ee54-d0d5-4d65-8d81-e1c4025f7597
17#[derive(Copy, Clone)]
18pub enum Action {
19    FastPathActionFastPath = 0x0,
20    FastPathActionX224 = 0x3
21}
22
23/// TPKT layer header
24///
25/// This the header layout of any RDP packet
26fn tpkt_header(size: u16) -> Component {
27    component![
28        "action" => Action::FastPathActionX224 as u8,
29        "flag" => 0 as u8,
30        "size" => U16::BE(size + 4)
31    ]
32}
33
34/// Client Context of TPKT layer
35///
36/// # Example
37/// ```
38/// use std::io::Cursor;
39/// use rdp::model::link::{Link, Stream};
40/// use rdp::core::tpkt::Client;
41/// let mut stream = Cursor::new(vec![]);
42/// let tpkt_client = Client::new(Link::new(Stream::Raw(stream)));
43/// ```
44pub struct Client<S> {
45    transport: Link<S>
46}
47
48impl<S: Read + Write> Client<S> {
49    /// Ctor of TPKT client layer
50    pub fn new (transport: Link<S>) -> Self {
51        Client {
52            transport
53        }
54    }
55
56    /// Send a message to the link layer
57    /// with appropriate header
58    /// Move to avoid copy
59    ///
60    /// # Example
61    /// ```
62    /// #[macro_use]
63    /// # extern crate rdp;
64    /// # use rdp::core::tpkt;
65    /// # use rdp::model::link;
66    /// # use std::io::Cursor;
67    /// # use rdp::model::data::{U16, Trame, U32};
68    /// # fn main() {
69    ///     let mut tpkt = tpkt::Client::new(link::Link::new(link::Stream::Raw(Cursor::new(vec![]))));
70    ///     tpkt.write(trame![U16::BE(4), U32::LE(3)]).unwrap();
71    ///     // get_link and get_stream are not available on Crate
72    ///     // only use for integration test [features = integration]
73    ///     if let link::Stream::Raw(e) = tpkt.get_link().get_stream() {
74    ///         assert_eq!(e.into_inner(), [3, 0, 0, 10, 0, 4, 3, 0, 0, 0])
75    ///     }
76    ///     else {
77    ///         panic!("Must not happen")
78    ///     }
79    /// }
80    /// ```
81    pub fn write<T: 'static>(&mut self, message: T) -> RdpResult<()>
82    where T: Message {
83        self.transport.write(
84            &trame![
85                tpkt_header(message.length() as u16),
86                message
87            ]
88        )
89    }
90
91    /// Read a payload from the underlying layer
92    /// Check the tpkt header and provide a well
93    /// formed payload
94    ///
95    /// # Example
96    /// ```
97    /// use rdp::core::tpkt;
98    /// use rdp::model::link;
99    /// use std::io::Cursor;
100    /// let mut tpkt = tpkt::Client::new(link::Link::new(link::Stream::Raw(Cursor::new(vec![3, 0, 0, 10, 0, 4, 3, 0, 0, 0]))));
101    /// if let tpkt::Payload::Raw(c) = tpkt.read().unwrap() {
102    ///     assert_eq!(c.into_inner(), vec![0, 4, 3, 0, 0, 0])
103    /// }
104    /// else {
105    ///     panic!("unexpected result")
106    /// }
107    ///
108    /// tpkt = tpkt::Client::new(link::Link::new(link::Stream::Raw(Cursor::new(vec![0, 6, 0, 0, 0, 0]))));
109    /// if let tpkt::Payload::FastPath(_, c) = tpkt.read().unwrap() {
110    ///     assert_eq!(c.into_inner(), vec![0, 0, 0, 0])
111    /// }
112    /// else {
113    ///     panic!("unexpected result")
114    /// }
115    ///
116    /// tpkt = tpkt::Client::new(link::Link::new(link::Stream::Raw(Cursor::new(vec![0, 0x80, 7, 0, 0, 0, 0]))));
117    /// if let tpkt::Payload::FastPath(_, c) = tpkt.read().unwrap() {
118    ///     assert_eq!(c.into_inner(), vec![0, 0, 0, 0])
119    /// }
120    /// else {
121    ///     panic!("unexpected result")
122    /// }
123    /// ```
124    pub fn read(&mut self) -> RdpResult<Payload> {
125        let mut buffer = Cursor::new(self.transport.read(2)?);
126        let mut action: u8 = 0;
127        action.read(&mut buffer)?;
128        if action == Action::FastPathActionX224 as u8 {
129
130            // read padding
131            let mut padding: u8 = 0;
132            padding.read(&mut buffer)?;
133            // now wait extended header
134            buffer = Cursor::new(self.transport.read(2)?);
135
136            let mut size = U16::BE(0);
137            size.read(&mut buffer)?;
138
139            // now wait for body
140            Ok(Payload::Raw(Cursor::new(self.transport.read(size.inner() as usize - 4)?)))
141
142        } else {
143            // fast path
144            let sec_flag = (action >> 6) & 0x3;
145            let mut short_length: u8 = 0;
146            short_length.read(&mut buffer)?;
147            if short_length & 0x80 != 0 {
148                let mut hi_length: u8 = 0;
149                hi_length.read(&mut Cursor::new(self.transport.read(1)?))?;
150                let length :u16 = ((short_length & !0x80) as u16) << 8;
151                let length = length | hi_length as u16;
152                Ok(Payload::FastPath(sec_flag, Cursor::new(self.transport.read(length as usize - 3)?)))
153            }
154            else {
155                Ok(Payload::FastPath(sec_flag, Cursor::new(self.transport.read(short_length as usize - 2)?)))
156            }
157         }
158    }
159
160    /// This function transform the link layer with
161    /// raw data stream into a SSL data stream
162    ///
163    /// # Example
164    /// ```no_run
165    /// use std::net::{SocketAddr, TcpStream};
166    /// use rdp::core::tpkt;
167    /// use rdp::model::link;
168    /// let addr = "127.0.0.1:3389".parse::<SocketAddr>().unwrap();
169    /// let mut tcp = TcpStream::connect(&addr).unwrap();
170    /// let mut tpkt = tpkt::Client::new(link::Link::new(link::Stream::Raw(tcp)));
171    /// let mut tpkt_ssl = tpkt.start_ssl(false).unwrap();
172    /// ```
173    pub fn start_ssl(self, check_certificate: bool) -> RdpResult<Client<S>> {
174        Ok(Client::new(self.transport.start_ssl(check_certificate)?))
175    }
176
177    /// This function is used when NLA (Network Level Authentication)
178    /// Authentication is negotiated
179    ///
180    /// # Example
181    /// ```no_run
182    /// use std::net::{SocketAddr, TcpStream};
183    /// use rdp::core::tpkt;
184    /// use rdp::nla::ntlm::Ntlm;
185    /// use rdp::model::link;
186    /// let addr = "127.0.0.1:3389".parse::<SocketAddr>().unwrap();
187    /// let mut tcp = TcpStream::connect(&addr).unwrap();
188    /// let mut tpkt = tpkt::Client::new(link::Link::new(link::Stream::Raw(tcp)));
189    /// let mut tpkt_nla = tpkt.start_nla(false, &mut Ntlm::new("domain".to_string(), "username".to_string(), "password".to_string()), false);
190    /// ```
191    pub fn start_nla(self, check_certificate: bool, authentication_protocol: &mut dyn AuthenticationProtocol, restricted_admin_mode: bool) -> RdpResult<Client<S>> {
192        let mut link = self.transport.start_ssl(check_certificate)?;
193        cssp_connect(&mut link, authentication_protocol, restricted_admin_mode)?;
194        Ok(Client::new(link))
195    }
196
197    /// Shutdown current connection
198    pub fn shutdown(&mut self) -> RdpResult<()> {
199        self.transport.shutdown()
200    }
201
202    #[cfg(feature = "integration")]
203    pub fn get_link(self) -> Link<S> {
204        self.transport
205    }
206}
207
208#[cfg(test)]
209mod test {
210    use super::*;
211    use std::io::Cursor;
212    use model::data::{U32, DataType};
213
214    /// Test the tpkt header type in write context
215    #[test]
216    fn test_write_tpkt_header() {
217        let x = U32::BE(1);
218        let message = trame![
219            tpkt_header(x.length() as u16),
220            x
221        ];
222        let mut buffer = Cursor::new(Vec::new());
223        message.write(&mut buffer).unwrap();
224        assert_eq!(buffer.get_ref().as_slice(), [3, 0, 0, 8, 0, 0, 0, 1]);
225    }
226
227    /// Test read of TPKT header
228    #[test]
229    fn test_read_tpkt_header() {
230        let mut message =  tpkt_header(0);
231        let mut buffer = Cursor::new([3, 0, 0, 8, 0, 0, 0, 1]);
232        message.read(&mut buffer).unwrap();
233        assert_eq!(cast!(DataType::U16, message["size"]).unwrap(), 8);
234        assert_eq!(cast!(DataType::U8, message["action"]).unwrap(), Action::FastPathActionX224 as u8);
235    }
236}