//! * x.691-spec: <https://www.itu.int/rec/T-REC-X.691/en>
use nom::IResult;
-use nom::error::ErrorKind;
+use nom::error::{make_error, ErrorKind};
use nom::number::complete::{be_u16, be_u8, le_u16, le_u32, le_u8};
-use crate::rdp::error::RDP_NOT_X224_CLASS_0_ERROR;
+use crate::rdp::error::RdpError;
use crate::rdp::util::{
le_slice_to_string, parse_per_length_determinant, utf7_slice_to_string,
};
/// parser for t.123 and children
/// t.123-spec, section 8
-pub fn parse_t123_tpkt(input: &[u8]) -> IResult<&[u8], T123Tpkt> {
+pub fn parse_t123_tpkt(input: &[u8]) -> IResult<&[u8], T123Tpkt, RdpError> {
let (i1, _version) =
verify!(input, be_u8, |&x| x == TpktVersion::T123 as u8)?;
let (i2, _reserved) = try_parse!(i1, be_u8);
/// rdp-spec, section 2.2.1.1
fn parse_x224_connection_request(
input: &[u8],
-) -> IResult<&[u8], X224ConnectionRequest> {
+) -> IResult<&[u8], X224ConnectionRequest, RdpError> {
let (i1, length) = verify!(input, be_u8, |&x| x != 0xff)?; // 0xff is reserved
let (i2, cr_cdt) = bits!(
i1,
)
)?;
// less cr_cdt (u8), dst_ref (u16), src_ref (u16), class_options (u8)
- let (i6, sz) = expr_opt!(i5, length.checked_sub(6))?;
+ if length < 6 {
+ return make_error(i5, ErrorKind::Verify)?;
+ }
+ let i6 = i5;
+ let sz = length - 6;
//
// optionally find cookie and/or negotiation request
/// "An X.224 Class 0 Connection Request TPDU, as specified in [X224] section 13.3."
fn parse_x224_connection_request_class_0(
input: &[u8],
-) -> IResult<&[u8], X224ConnectionRequest> {
+) -> IResult<&[u8], X224ConnectionRequest, RdpError> {
let (i1, x224) = try_parse!(input, parse_x224_connection_request);
if x224.class == 0 && x224.options == 0 {
Ok((i1, x224))
} else {
- Err(nom::Err::Error(error_position!(
- input,
- ErrorKind::Custom(RDP_NOT_X224_CLASS_0_ERROR)
- )))
+ Err(nom::Err::Error(RdpError::NotX224Class0Error))
}
}
// rdp-spec, section 2.2.1.1.1
-fn parse_rdp_cookie(input: &[u8]) -> IResult<&[u8], RdpCookie> {
+fn parse_rdp_cookie(input: &[u8]) -> IResult<&[u8], RdpCookie, RdpError> {
do_parse! {
input,
_key: verify!(
// rdp-spec, section 2.2.1.1.1
fn parse_negotiation_request(
input: &[u8],
-) -> IResult<&[u8], NegotiationRequest> {
+) -> IResult<&[u8], NegotiationRequest, RdpError> {
do_parse! {
input,
_typ: verify!(
/// x.224-spec, section 13.3
fn parse_x224_connection_confirm(
input: &[u8],
-) -> IResult<&[u8], X224ConnectionConfirm> {
+) -> IResult<&[u8], X224ConnectionConfirm, RdpError> {
let (i1, length) = verify!(input, be_u8, |&x| x != 0xff)?; // 0xff is reserved
let (i2, cr_cdt) = bits!(
i1,
)?;
// less cr_cdt (u8), dst_ref (u16), src_ref (u16), class_options (u8)
- let (i6, sz) = expr_opt!(i5, length.checked_sub(6))?;
+ if length < 6 {
+ return make_error(i5, ErrorKind::Verify)?;
+ }
+ let i6 = i5;
+ let sz = length - 6;
// a negotiation message from the server might be absent (sz == 0)
let (i7, negotiation_from_server) = {
/// "An X.224 Class 0 Connection Confirm TPDU, as specified in [X224] section 13.4."
fn parse_x224_connection_confirm_class_0(
input: &[u8],
-) -> IResult<&[u8], X224ConnectionConfirm> {
+) -> IResult<&[u8], X224ConnectionConfirm, RdpError> {
let (i1, x224) = try_parse!(input, parse_x224_connection_confirm);
if x224.class == 0 && x224.options == 0 {
Ok((i1, x224))
} else {
// x.224, but not a class 0 x.224 message
- Err(nom::Err::Error(error_position!(
- input,
- ErrorKind::Custom(RDP_NOT_X224_CLASS_0_ERROR)
- )))
+ Err(nom::Err::Error(RdpError::NotX224Class0Error))
}
}
// rdp-spec, section 2.2.1.1.1
fn parse_negotiation_response(
input: &[u8],
-) -> IResult<&[u8], NegotiationResponse> {
+) -> IResult<&[u8], NegotiationResponse, RdpError> {
do_parse! {
input,
_typ: verify!(
// rdp-spec, section 2.2.1.1.1
fn parse_negotiation_failure(
input: &[u8],
-) -> IResult<&[u8], NegotiationFailure> {
+) -> IResult<&[u8], NegotiationFailure, RdpError> {
do_parse! {
input,
_typ: verify!(
}
/// x224-spec, section 13.7
-fn parse_x223_data_class_0(input: &[u8]) -> IResult<&[u8], X223Data> {
+fn parse_x223_data_class_0(input: &[u8]) -> IResult<&[u8], X223Data, RdpError> {
let (i1, _length) = verify!(input, be_u8, |&x| x == 2)?;
let (i2, _dt_x_roa) = bits!(
i1,
}
/// rdp-spec, section 2.2.1.3.2
-fn parse_mcs_connect(input: &[u8]) -> IResult<&[u8], McsConnectRequest> {
+fn parse_mcs_connect(input: &[u8]) -> IResult<&[u8], McsConnectRequest, RdpError> {
let (i1, _ber_type) = verify!(
input,
le_u8,
// rdp-spec, section 2.2.1.4
fn parse_mcs_connect_response(
input: &[u8],
-) -> IResult<&[u8], McsConnectResponse> {
+) -> IResult<&[u8], McsConnectResponse, RdpError> {
do_parse! {
input,
_ber_type: verify!(
use memchr::memchr;
use nom;
use nom::{IResult, Needed};
-use nom::error::ErrorKind;
-use crate::rdp::error::RDP_UNIMPLEMENTED_LENGTH_DETERMINANT;
+use crate::rdp::error::RdpError;
use std::io::Cursor;
use widestring::U16CString;
/// parses a PER length determinant, to determine the length of the data following
/// x.691-spec: section 10.9
-pub fn parse_per_length_determinant(input: &[u8]) -> IResult<&[u8], u32> {
+pub fn parse_per_length_determinant(input: &[u8]) -> IResult<&[u8], u32, RdpError> {
if input.is_empty() {
// need a single byte to begin length determination
Err(nom::Err::Incomplete(Needed::Size(1)))
_ => {
// byte starts with 0b11. Without an example to confirm 16K+ lengths are properly
// handled, leaving this branch unimplemented
- Err(nom::Err::Error(error_position!(
- input,
- ErrorKind::Custom(RDP_UNIMPLEMENTED_LENGTH_DETERMINANT)
- )))
+ Err(nom::Err::Error(RdpError::UnimplementedLengthDeterminant))
}
}
}
mod tests {
use super::*;
use nom;
- use crate::rdp::error::RDP_UNIMPLEMENTED_LENGTH_DETERMINANT;
+ use crate::rdp::error::RdpError;
#[test]
fn test_le_string_abc() {
fn test_length_16k_unimplemented() {
let bytes = &[0xc0];
assert_eq!(
- Err(nom::Err::Error(error_position!(
- &bytes[..],
- ErrorKind::Custom(RDP_UNIMPLEMENTED_LENGTH_DETERMINANT)
- ))),
+ Err(nom::Err::Error(RdpError::UnimplementedLengthDeterminant)),
parse_per_length_determinant(bytes)
)
}