rdp/core/
per.rs

1use model::data::{Message, U16, Trame, U32};
2use std::io::{Read, Write};
3use model::error::{RdpResult, Error, RdpError, RdpErrorKind};
4
5
6/// PER encoding length
7/// read length of following payload
8/// # Example
9/// ```
10/// use std::io::Cursor;
11/// use rdp::core::per::read_length;
12/// let mut s = Cursor::new(&[0x10]);
13/// assert_eq!(read_length(&mut s).unwrap(), 0x10);
14/// let mut s2 = Cursor::new(&[0x81, 0x10]);
15/// assert_eq!(read_length(&mut s2).unwrap(), 0x110);
16/// ```
17pub fn read_length(s: &mut dyn Read) -> RdpResult<u16> {
18    let mut byte: u8 = 0;
19    byte.read(s)?;
20    if byte & 0x80 != 0 {
21        byte = byte & !0x80;
22        let mut size = (byte as u16) << 8 ;
23        byte.read(s)?;
24        size += byte as u16;
25        Ok(size)
26    }
27    else {
28        Ok(byte as u16)
29    }
30}
31
32/// Write PER encoded length
33/// # Example
34/// ```
35/// use std::io::Cursor;
36/// use rdp::core::per::write_length;
37/// use rdp::model::data::Message;
38/// let mut s = Cursor::new(vec![]);
39/// write_length(0x10).unwrap().write(&mut s).unwrap();
40/// assert_eq!(s.into_inner(), [0x10]);
41/// let mut s2 = Cursor::new(vec![]);
42/// write_length(0x110).unwrap().write(&mut s2).unwrap();
43/// assert_eq!(s2.into_inner(), [0x81, 0x10]);
44/// ```
45pub fn write_length(length: u16) -> RdpResult<Trame> {
46    if length > 0x7f {
47        Ok(trame![U16::BE(length | 0x8000)])
48    }
49    else {
50        Ok(trame![length as u8])
51    }
52}
53
54/// Read a choice value in PER encoded stream
55///
56/// # Exemple
57/// ```
58/// use std::io::Cursor;
59/// use rdp::core::per::read_choice;
60/// let mut s = Cursor::new([1]);
61/// assert_eq!(read_choice(&mut s).unwrap(), 1)
62/// ```
63pub fn read_choice(s: &mut dyn Read) -> RdpResult<u8> {
64    let mut result : u8 = 0;
65    result.read(s)?;
66    Ok(result)
67}
68
69/// PER write choice
70/// This is convenient method
71///
72/// # Exemple
73/// ```
74/// use std::io::Cursor;
75/// use rdp::core::per::write_choice;
76/// let mut s = Cursor::new(vec![]);
77/// write_choice(1, &mut s).unwrap();
78/// assert_eq!(s.into_inner(), [1]);
79/// ```
80pub fn write_choice(choice: u8, s: &mut dyn Write) -> RdpResult<()> {
81    choice.write(s)?;
82    Ok(())
83}
84
85/// Read a selection value in PER encoded stream
86///
87/// # Exemple
88/// ```
89/// use std::io::Cursor;
90/// use rdp::core::per::read_selection;
91/// let mut s = Cursor::new([1]);
92/// assert_eq!(read_selection(&mut s).unwrap(), 1)
93/// ```
94pub fn read_selection(s: &mut dyn Read) -> RdpResult<u8> {
95    let mut result : u8 = 0;
96    result.read(s)?;
97    Ok(result)
98}
99
100/// PER write selection
101/// This is convenient method
102///
103/// # Exemple
104/// ```
105/// use std::io::Cursor;
106/// use rdp::core::per::write_selection;
107/// let mut s = Cursor::new(vec![]);
108/// write_selection(1, &mut s).unwrap();
109/// assert_eq!(s.into_inner(), [1]);
110/// ```
111pub fn write_selection(selection: u8, s: &mut dyn Write) -> RdpResult<()> {
112    selection.write(s)?;
113    Ok(())
114}
115
116/// Read a number of set value in PER encoded stream
117///
118/// # Exemple
119/// ```
120/// use std::io::Cursor;
121/// use rdp::core::per::read_number_of_set;
122/// let mut s = Cursor::new([1]);
123/// assert_eq!(read_number_of_set(&mut s).unwrap(), 1)
124/// ```
125pub fn read_number_of_set(s: &mut dyn Read) -> RdpResult<u8> {
126    let mut result : u8 = 0;
127    result.read(s)?;
128    Ok(result)
129}
130
131/// PER write number of set
132/// This is convenient method
133///
134/// # Exemple
135/// ```
136/// use std::io::Cursor;
137/// use rdp::core::per::write_number_of_set;
138/// let mut s = Cursor::new(vec![]);
139/// write_number_of_set(1, &mut s).unwrap();
140/// assert_eq!(s.into_inner(), [1]);
141/// ```
142pub fn write_number_of_set(number_of_set: u8, s: &mut dyn Write) -> RdpResult<()> {
143    number_of_set.write(s)?;
144    Ok(())
145}
146
147/// Read an enumerates value in PER encoded stream
148///
149/// # Exemple
150/// ```
151/// use std::io::Cursor;
152/// use rdp::core::per::read_enumerates;
153/// let mut s = Cursor::new([1]);
154/// assert_eq!(read_enumerates(&mut s).unwrap(), 1)
155/// ```
156pub fn read_enumerates(s: &mut dyn Read) -> RdpResult<u8> {
157    let mut result : u8 = 0;
158    result.read(s)?;
159    Ok(result)
160}
161
162/// PER write enumerates
163/// This is convenient method
164///
165/// # Exemple
166/// ```
167/// use rdp::core::per::write_enumerates;
168/// use rdp::model::data::to_vec;
169/// assert_eq!(to_vec(&write_enumerates(1).unwrap()), [1]);
170/// ```
171pub fn write_enumerates(enumerate: u8) -> RdpResult<u8> {
172    Ok(enumerate)
173}
174
175/// Read an PER encoded integer
176/// Variable sized integer
177///
178/// # Example
179/// ```
180/// use std::io::Cursor;
181/// use rdp::core::per::read_integer;
182/// let mut su8 = Cursor::new([0x1, 0x1]);
183/// assert_eq!(read_integer(&mut su8).unwrap(), 1);
184/// let mut su16 = Cursor::new([0x2, 0x0, 0x1]);
185/// assert_eq!(read_integer(&mut su16).unwrap(), 1);
186/// let mut su32 = Cursor::new([0x4, 0x0, 0x0, 0x0, 0x1]);
187/// assert_eq!(read_integer(&mut su32).unwrap(), 1);
188/// let mut sinvalid = Cursor::new([0x67]);
189/// assert!(read_integer(&mut sinvalid).is_err())
190/// ```
191pub fn read_integer(s: &mut dyn Read) -> RdpResult<u32> {
192    let size = read_length(s)?;
193    match size {
194        1 => {
195            let mut result: u8 = 0;
196            result.read(s)?;
197            Ok(result as u32)
198        },
199        2 => {
200            let mut result = U16::BE(0);
201            result.read(s)?;
202            Ok(result.inner() as u32)
203        },
204        4 => {
205            let mut result = U32::BE(0);
206            result.read(s)?;
207            Ok(result.inner() as u32)
208        },
209        _ => Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidSize, "PER integer encoded with an invalid size")))
210    }
211}
212
213/// Write an integer into PER format
214///
215/// # Example
216/// ```
217/// use std::io::Cursor;
218/// use rdp::core::per::write_integer;
219/// let mut su8 = Cursor::new(vec![]);
220/// write_integer(1, &mut su8).unwrap();
221/// assert_eq!(su8.into_inner(), [0x1, 0x1]);
222/// let mut su16 = Cursor::new(vec![]);
223/// write_integer(256, &mut su16).unwrap();
224/// assert_eq!(su16.into_inner(), [0x2, 0x01, 0x00]);
225/// let mut su32 = Cursor::new(vec![]);
226/// write_integer(65536, &mut su32).unwrap();
227/// assert_eq!(su32.into_inner(), [0x4, 0x00, 0x01, 0x00, 0x00]);
228/// ```
229pub fn write_integer(integer: u32, s: &mut dyn Write) -> RdpResult<()> {
230    if integer < 0xFF {
231        write_length(1)?.write(s)?;
232        (integer as u8).write(s)?;
233    } else if integer < 0xFFFF {
234        write_length(2)?.write(s)?;
235        U16::BE(integer as u16).write(s)?;
236    } else {
237        write_length(4)?.write(s)?;
238        U32::BE(integer).write(s)?;
239    };
240    Ok(())
241}
242
243
244/// Read u16 integer PER encoded
245///
246/// # Example
247/// ```
248/// use std::io::Cursor;
249/// use rdp::core::per::read_integer_16;
250/// let mut s = Cursor::new([0x00, 0x01]);
251/// assert_eq!(read_integer_16(5, &mut s).unwrap(), 6);
252/// ```
253pub fn read_integer_16(minimum: u16, s: &mut dyn Read) -> RdpResult<u16> {
254    let mut result = U16::BE(0);
255    result.read(s)?;
256    Ok(result.inner() + minimum)
257}
258
259/// This is a convenient method for PER encoding
260///
261/// # Example
262/// ```
263/// use std::io::Cursor;
264/// use rdp::core::per::write_integer_16;
265/// let mut s = Cursor::new(vec![]);
266/// write_integer_16(4, 2, &mut s).unwrap();
267/// assert_eq!(s.into_inner(), [0x00, 0x02]);
268/// ```
269pub fn write_integer_16(integer: u16, minimum: u16, s: &mut dyn Write) -> RdpResult<()> {
270    U16::BE(integer - minimum).write(s)?;
271    Ok(())
272}
273
274
275/// Read an object identifier encoded in PER
276///
277/// # Example
278/// ```
279/// use std::io::Cursor;
280/// use rdp::core::per::read_object_identifier;
281/// let mut s1 = Cursor::new([5, 0, 20, 124, 0, 1]);
282/// assert!(read_object_identifier(&[0, 0, 20, 124, 0, 1], &mut s1).unwrap());
283/// let mut s2 = Cursor::new([6, 0, 20, 124, 0, 1]);
284/// assert!(read_object_identifier(&[0, 0, 20, 124, 0, 1], &mut s2).is_err());
285/// let mut s3 = Cursor::new([5, 0x11, 20, 124, 0, 1]);
286/// assert!(read_object_identifier(&[1, 1, 20, 124, 0, 1], &mut s3).unwrap())
287/// ```
288pub fn read_object_identifier(oid: &[u8], s: &mut dyn Read) -> RdpResult<bool> {
289    if oid.len() != 6 {
290        return Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidSize, "Oid to check have an invalid size")));
291    }
292
293    let length = read_length(s)?;
294    if length != 5 {
295        return Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidSize, "Oid source have an invalid size")));
296    }
297
298    let mut oid_parsed = [0; 6];
299    let mut tmp : u8 = 0;
300
301    tmp.read(s)?;
302    oid_parsed[0] = tmp >> 4;
303    oid_parsed[1] = tmp & 0xf;
304    tmp.read(s)?;
305    oid_parsed[2] = tmp;
306    tmp.read(s)?;
307    oid_parsed[3] = tmp;
308    tmp.read(s)?;
309    oid_parsed[5] = tmp;
310    tmp.read(s)?;
311    oid_parsed[5] = tmp;
312
313    Ok(oid_parsed == oid)
314}
315
316/// Write an object identifier using PER encoder
317///
318/// # Example
319/// ```
320/// use std::io::Cursor;
321/// use rdp::core::per::write_object_identifier;
322/// let mut s = Cursor::new(vec![]);
323/// write_object_identifier(&[1, 2, 3, 4, 5, 6], &mut s).unwrap();
324/// assert_eq!(s.into_inner(), [5, 0x12, 3, 4, 5, 6]);
325/// ```
326pub fn write_object_identifier(oid: &[u8], s: &mut dyn Write) ->RdpResult<()> {
327    if oid.len() != 6 {
328        return Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidSize, "PER: oid source don't have the correct size")))
329    }
330
331    trame![
332        5 as u8,
333        oid[0] << 4 | oid[1] & 0xF,
334        oid[2],
335        oid[3],
336        oid[4],
337        oid[5]
338    ].write(s)
339}
340
341/// Read a numeric string
342///
343/// # Example
344/// ```
345/// use std::io::Cursor;
346/// use rdp::core::per::read_numeric_string;
347/// let mut s = Cursor::new(vec![2, 0, 0, 0]);
348/// assert_eq!(read_numeric_string(0, &mut s).unwrap(), [0, 0, 0]);
349/// ```
350pub fn read_numeric_string(minimum: usize, s: &mut dyn Read) -> RdpResult<Vec<u8>> {
351    let length = read_length(s)?;
352    let mut result = vec![0 as u8; length as usize + minimum + 1];
353    result.read(s)?;
354    Ok(result)
355}
356
357pub fn write_numeric_string(string: &[u8], minimum: usize,  s: &mut dyn Write) -> RdpResult<()> {
358    let mut length = string.len();
359    if length as i64 - minimum as i64 >= 0 {
360        length -= minimum;
361    }
362
363    write_length(length as u16)?.write(s)?;
364
365    for i in 0..string.len() {
366        let mut c1 = string[i];
367        let mut c2 = if i + 1 < string.len() {
368            string[i+1]
369        } else {
370            0x30
371        };
372        c1 = (c1 - 0x30) % 10;
373        c2 = (c2 - 0x30) % 10;
374
375        ((c1 << 4) | c2).write(s)?;
376    }
377    Ok(())
378}
379
380/// Read exactly a number of bytes
381pub fn read_padding(length: usize, s: &mut dyn Read) -> RdpResult<()> {
382    let mut padding = vec![0; length];
383    s.read(&mut padding)?;
384    Ok(())
385}
386
387/// Write length zero bytes
388pub fn write_padding(length: usize, s: &mut dyn Write) -> RdpResult<()> {
389    vec![0 as u8; length].write(s)?;
390    Ok(())
391}
392
393/// Read a string encoded in PER
394///
395/// # Example
396/// ```
397/// use std::io::Cursor;
398/// use rdp::core::per::read_octet_stream;
399/// let mut s1 = Cursor::new(vec![3, 1, 2, 3]);
400/// read_octet_stream(&[1, 2, 3], 0, &mut s1).unwrap();
401/// let mut s2 = Cursor::new(vec![3, 1, 2, 4]);
402/// assert!(read_octet_stream(&[1, 2, 3], 0, &mut s2).is_err());
403/// ```
404pub fn read_octet_stream(octet_stream: &[u8], minimum: usize, s: &mut dyn Read) -> RdpResult<()> {
405    let length = read_length(s)? as usize + minimum;
406    if length != octet_stream.len() {
407        return Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidSize, "PER: source octet string have an invalid size")));
408    }
409    for i in 0..length {
410        let mut c: u8 = 0;
411        c.read(s)?;
412        if c != octet_stream[i] {
413            return Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidData, "PER: source octet string have an invalid char")));
414        }
415    }
416
417    Ok(())
418}
419
420pub fn write_octet_stream(octet_string: &[u8], minimum: usize, s: &mut dyn Write) -> RdpResult<()> {
421    let mut length = minimum;
422    if octet_string.len() as i64 - minimum as i64 >= 0 {
423        length = octet_string.len() - minimum;
424    }
425
426    write_length(length as u16)?.write(s)?;
427
428    octet_string.to_vec().write(s)?;
429    Ok(())
430}