refactor(pdu): return whether hint::find_size() matches the expected hint

When compiled in debug mode, the code checks the expected Action hint.
But in release mode, no checks are done and the it will have to fail
later.

Instead, return whether the PDU is matching the hint, so the caller can
decide what to do in this case.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
Marc-André Lureau
2024-08-19 06:44:15 -04:00
committed by Benoît Cortier
parent d8f2d10558
commit 46b703e813
7 changed files with 23 additions and 19 deletions
+1 -1
View File
@@ -170,7 +170,7 @@ where
.find_size(self.peek())
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?
{
Some(length) => {
Some((_matched, length)) => {
return Ok(self.read_exact(length).await?.freeze());
}
None => {
+1 -1
View File
@@ -93,7 +93,7 @@ where
.find_size(self.peek())
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?
{
Some(length) => {
Some((_matched, length)) => {
return Ok(self.read_exact(length)?.freeze());
}
None => {
+4 -4
View File
@@ -43,9 +43,9 @@ struct CredsspTsRequestHint;
const CREDSSP_TS_REQUEST_HINT: CredsspTsRequestHint = CredsspTsRequestHint;
impl PduHint for CredsspTsRequestHint {
fn find_size(&self, bytes: &[u8]) -> ironrdp_pdu::PduResult<Option<usize>> {
fn find_size(&self, bytes: &[u8]) -> ironrdp_pdu::PduResult<Option<(bool, usize)>> {
match credssp::TsRequest::read_length(bytes) {
Ok(length) => Ok(Some(length)),
Ok(length) => Ok(Some((true, length))),
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => Ok(None),
Err(e) => Err(ironrdp_pdu::custom_err!("CredsspTsRequestHint", e)),
}
@@ -58,8 +58,8 @@ struct CredsspEarlyUserAuthResultHint;
const CREDSSP_EARLY_USER_AUTH_RESULT_HINT: CredsspEarlyUserAuthResultHint = CredsspEarlyUserAuthResultHint;
impl PduHint for CredsspEarlyUserAuthResultHint {
fn find_size(&self, _: &[u8]) -> ironrdp_pdu::PduResult<Option<usize>> {
Ok(Some(credssp::EARLY_USER_AUTH_RESULT_PDU_SIZE))
fn find_size(&self, _: &[u8]) -> ironrdp_pdu::PduResult<Option<(bool, usize)>> {
Ok(Some((true, credssp::EARLY_USER_AUTH_RESULT_PDU_SIZE)))
}
}
+12 -9
View File
@@ -333,7 +333,10 @@ pub fn find_size(bytes: &[u8]) -> PduResult<Option<PduInfo>> {
pub trait PduHint: Send + Sync + fmt::Debug + 'static {
/// Finds next PDU size by reading the next few bytes.
fn find_size(&self, bytes: &[u8]) -> PduResult<Option<usize>>;
///
/// Returns `Some((hint_matching, size))` if the size is known.
/// Returns `None` if the size cannot be determined yet.
fn find_size(&self, bytes: &[u8]) -> PduResult<Option<(bool, usize)>>;
}
// Matches both X224 and FastPath pdus
@@ -343,8 +346,8 @@ pub struct RdpHint;
pub const RDP_HINT: RdpHint = RdpHint;
impl PduHint for RdpHint {
fn find_size(&self, bytes: &[u8]) -> PduResult<Option<usize>> {
find_size(bytes).map(|opt| opt.map(|info| info.length))
fn find_size(&self, bytes: &[u8]) -> PduResult<Option<(bool, usize)>> {
find_size(bytes).map(|opt| opt.map(|info| (true, info.length)))
}
}
@@ -354,11 +357,11 @@ pub struct X224Hint;
pub const X224_HINT: X224Hint = X224Hint;
impl PduHint for X224Hint {
fn find_size(&self, bytes: &[u8]) -> PduResult<Option<usize>> {
fn find_size(&self, bytes: &[u8]) -> PduResult<Option<(bool, usize)>> {
match find_size(bytes)? {
Some(pdu_info) => {
debug_assert_eq!(pdu_info.action, Action::X224);
Ok(Some(pdu_info.length))
let res = (pdu_info.action == Action::X224, pdu_info.length);
Ok(Some(res))
}
None => Ok(None),
}
@@ -371,11 +374,11 @@ pub struct FastPathHint;
pub const FAST_PATH_HINT: FastPathHint = FastPathHint;
impl PduHint for FastPathHint {
fn find_size(&self, bytes: &[u8]) -> PduResult<Option<usize>> {
fn find_size(&self, bytes: &[u8]) -> PduResult<Option<(bool, usize)>> {
match find_size(bytes)? {
Some(pdu_info) => {
debug_assert_eq!(pdu_info.action, Action::FastPath);
Ok(Some(pdu_info.length))
let res = (pdu_info.action == Action::FastPath, pdu_info.length);
Ok(Some(res))
}
None => Ok(None),
}
+2 -2
View File
@@ -894,9 +894,9 @@ where
const RDCLEANPATH_HINT: RDCleanPathHint = RDCleanPathHint;
impl ironrdp::pdu::PduHint for RDCleanPathHint {
fn find_size(&self, bytes: &[u8]) -> ironrdp::pdu::PduResult<Option<usize>> {
fn find_size(&self, bytes: &[u8]) -> ironrdp::pdu::PduResult<Option<(bool, usize)>> {
match ironrdp_rdcleanpath::RDCleanPathPdu::detect(bytes) {
ironrdp_rdcleanpath::DetectionResult::Detected { total_length, .. } => Ok(Some(total_length)),
ironrdp_rdcleanpath::DetectionResult::Detected { total_length, .. } => Ok(Some((true, total_length))),
ironrdp_rdcleanpath::DetectionResult::NotEnoughBytes => Ok(None),
ironrdp_rdcleanpath::DetectionResult::Failed => Err(ironrdp::pdu::other_err!(
"RDCleanPathHint",
@@ -17,7 +17,7 @@ public partial struct PduHint
private const string NativeLib = "DevolutionsIronRdp";
[DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PduHint_find_size", ExactSpelling = true)]
public static unsafe extern ConnectorFfiResultBoxOptionalUsizeBoxIronRdpError FindSize(PduHint* self, byte* bytes, nuint bytesSz);
public static unsafe extern ConnectorFfiResultBoxOptionalUsizeBoxIronRdpError FindSize(PduHint* self, byte* bytes, nuint bytesSz, bool* matched);
[DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PduHint_destroy", ExactSpelling = true)]
public static unsafe extern void Destroy(PduHint* self);
+2 -1
View File
@@ -160,7 +160,8 @@ pub mod ffi {
impl<'a> PduHint<'a> {
pub fn find_size(&'a self, bytes: &[u8]) -> Result<Box<crate::utils::ffi::OptionalUsize>, Box<IronRdpError>> {
let pdu_hint = self.0;
let size = pdu_hint.find_size(bytes)?;
// TODO C# NuGet is only used on client-side so we probably dont need to break the ABI for that just now.
let size = pdu_hint.find_size(bytes)?.map(|(_match, size)| size);
Ok(Box::new(crate::utils::ffi::OptionalUsize(size)))
}
}