Skip to content

Commit 6396318

Browse files
elmarcoCBenoit
authored andcommitted
fix(server): drop unexpected PDUs during deactivation-reactivation
The current behaviour of handling unmatched PDUs in fn read_by_hint() isn't good enough. An unexpected PDUs may be received and fail to be decoded during Acceptor::step(). Change the code to simply drop unexpected PDUs (as opposed to attempting to replay the unmatched leftover, which isn't clearly needed) Signed-off-by: Marc-André Lureau <[email protected]>
1 parent ab8a87d commit 6396318

File tree

9 files changed

+63
-59
lines changed

9 files changed

+63
-59
lines changed

crates/ironrdp-acceptor/src/connection.rs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub struct Acceptor {
3434
static_channels: StaticChannelSet,
3535
saved_for_reactivation: AcceptorState,
3636
pub(crate) creds: Option<Credentials>,
37+
reactivation: bool,
3738
}
3839

3940
#[derive(Debug)]
@@ -62,6 +63,7 @@ impl Acceptor {
6263
static_channels: StaticChannelSet::new(),
6364
saved_for_reactivation: Default::default(),
6465
creds,
66+
reactivation: false,
6567
}
6668
}
6769

@@ -98,6 +100,7 @@ impl Acceptor {
98100
static_channels: StaticChannelSet::new(),
99101
saved_for_reactivation,
100102
creds: consumed.creds,
103+
reactivation: true,
101104
}
102105
}
103106

@@ -291,7 +294,9 @@ impl Sequence for Acceptor {
291294
}
292295

293296
fn step(&mut self, input: &[u8], output: &mut WriteBuf) -> ConnectorResult<Written> {
294-
let (written, next_state) = match mem::take(&mut self.state) {
297+
let prev_state = mem::take(&mut self.state);
298+
299+
let (written, next_state) = match prev_state {
295300
AcceptorState::InitiationWaitRequest => {
296301
let connection_request = decode::<X224<nego::ConnectionRequest>>(input)
297302
.map_err(ConnectorError::decode)
@@ -639,15 +644,38 @@ impl Sequence for Acceptor {
639644
)
640645
}
641646

642-
AcceptorState::CapabilitiesWaitConfirm { channels } => {
647+
AcceptorState::CapabilitiesWaitConfirm { ref channels } => {
643648
let message = decode::<X224<mcs::McsMessage<'_>>>(input)
644649
.map_err(ConnectorError::decode)
645-
.map(|p| p.0)?;
646-
650+
.map(|p| p.0);
651+
let message = match message {
652+
Ok(msg) => msg,
653+
Err(e) => {
654+
if self.reactivation {
655+
debug!("Dropping unexpected PDU during reactivation");
656+
self.state = prev_state;
657+
return Ok(Written::Nothing);
658+
} else {
659+
return Err(e);
660+
}
661+
}
662+
};
647663
match message {
648664
mcs::McsMessage::SendDataRequest(data) => {
649665
let capabilities_confirm = decode::<rdp::headers::ShareControlHeader>(data.user_data.as_ref())
650-
.map_err(ConnectorError::decode)?;
666+
.map_err(ConnectorError::decode);
667+
let capabilities_confirm = match capabilities_confirm {
668+
Ok(capabilities_confirm) => capabilities_confirm,
669+
Err(e) => {
670+
if self.reactivation {
671+
debug!("Dropping unexpected PDU during reactivation");
672+
self.state = prev_state;
673+
return Ok(Written::Nothing);
674+
} else {
675+
return Err(e);
676+
}
677+
}
678+
};
651679

652680
debug!(message = ?capabilities_confirm, "Received");
653681

@@ -659,7 +687,7 @@ impl Sequence for Acceptor {
659687
(
660688
Written::Nothing,
661689
AcceptorState::ConnectionFinalization {
662-
channels,
690+
channels: channels.clone(),
663691
finalization: FinalizationSequence::new(self.user_channel_id, self.io_channel_id),
664692
client_capabilities: confirm.pdu.capability_sets,
665693
},
@@ -673,7 +701,7 @@ impl Sequence for Acceptor {
673701
_ => {
674702
warn!(?message, "Unexpected MCS message received");
675703

676-
(Written::Nothing, AcceptorState::CapabilitiesWaitConfirm { channels })
704+
(Written::Nothing, prev_state)
677705
}
678706
}
679707
}
@@ -684,6 +712,7 @@ impl Sequence for Acceptor {
684712
client_capabilities,
685713
} => {
686714
let written = finalization.step(input, output)?;
715+
687716
let state = if finalization.is_done() {
688717
AcceptorState::Accepted {
689718
channels,

crates/ironrdp-acceptor/src/lib.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#[macro_use]
55
extern crate tracing;
66

7-
use ironrdp_async::bytes::Bytes;
87
use ironrdp_async::{single_sequence_step, Framed, FramedRead, FramedWrite, StreamWrapper};
98
use ironrdp_connector::credssp::KerberosConfig;
109
use ironrdp_connector::sspi::credssp::EarlyUserAuthResult;
@@ -50,7 +49,7 @@ where
5049
return Ok(result);
5150
}
5251

53-
single_sequence_step(&mut framed, acceptor, &mut buf, None).await?;
52+
single_sequence_step(&mut framed, acceptor, &mut buf).await?;
5453
}
5554
}
5655

@@ -84,7 +83,6 @@ where
8483
pub async fn accept_finalize<S>(
8584
mut framed: Framed<S>,
8685
acceptor: &mut Acceptor,
87-
mut unmatched: Option<&mut Vec<Bytes>>,
8886
) -> ConnectorResult<(Framed<S>, AcceptorResult)>
8987
where
9088
S: FramedRead + FramedWrite,
@@ -95,7 +93,7 @@ where
9593
if let Some(result) = acceptor.get_result() {
9694
return Ok((framed, result));
9795
}
98-
single_sequence_step(&mut framed, acceptor, &mut buf, unmatched.as_deref_mut()).await?;
96+
single_sequence_step(&mut framed, acceptor, &mut buf).await?;
9997
}
10098
}
10199

@@ -152,7 +150,7 @@ where
152150
);
153151

154152
let pdu = framed
155-
.read_by_hint(next_pdu_hint, None)
153+
.read_by_hint(next_pdu_hint)
156154
.await
157155
.map_err(|e| ironrdp_connector::custom_err!("read frame by hint", e))?;
158156

crates/ironrdp-async/src/connector.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ where
2323
info!("Begin connection procedure");
2424

2525
while !connector.should_perform_security_upgrade() {
26-
single_sequence_step(framed, connector, &mut buf, None).await?;
26+
single_sequence_step(framed, connector, &mut buf).await?;
2727
}
2828

2929
Ok(ShouldUpgrade)
@@ -73,7 +73,7 @@ where
7373
}
7474

7575
let result = loop {
76-
single_sequence_step(framed, &mut connector, &mut buf, None).await?;
76+
single_sequence_step(framed, &mut connector, &mut buf).await?;
7777

7878
if let ClientConnectorState::Connected { result } = connector.state {
7979
break result;
@@ -171,7 +171,7 @@ where
171171
);
172172

173173
let pdu = framed
174-
.read_by_hint(next_pdu_hint, None)
174+
.read_by_hint(next_pdu_hint)
175175
.await
176176
.map_err(|e| ironrdp_connector::custom_err!("read frame by hint", e))?;
177177

crates/ironrdp-async/src/framed.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,7 @@ where
165165
/// `tokio::select!` statement and some other branch
166166
/// completes first, then it is safe to drop the future and re-create it later.
167167
/// Data may have been read, but it will be stored in the internal buffer.
168-
pub async fn read_by_hint(
169-
&mut self,
170-
hint: &dyn PduHint,
171-
mut unmatched: Option<&mut Vec<Bytes>>,
172-
) -> io::Result<Bytes> {
168+
pub async fn read_by_hint(&mut self, hint: &dyn PduHint) -> io::Result<Bytes> {
173169
loop {
174170
match hint
175171
.find_size(self.peek())
@@ -179,10 +175,8 @@ where
179175
let bytes = self.read_exact(length).await?.freeze();
180176
if matched {
181177
return Ok(bytes);
182-
} else if let Some(ref mut unmatched) = unmatched {
183-
unmatched.push(bytes);
184178
} else {
185-
warn!("Received and lost an unexpected PDU");
179+
debug!("Received and lost an unexpected PDU");
186180
}
187181
}
188182
None => {
@@ -236,21 +230,19 @@ pub async fn single_sequence_step<S>(
236230
framed: &mut Framed<S>,
237231
sequence: &mut dyn Sequence,
238232
buf: &mut WriteBuf,
239-
unmatched: Option<&mut Vec<Bytes>>,
240233
) -> ConnectorResult<()>
241234
where
242235
S: FramedWrite + FramedRead,
243236
{
244237
buf.clear();
245-
let written = single_sequence_step_read(framed, sequence, buf, unmatched).await?;
238+
let written = single_sequence_step_read(framed, sequence, buf).await?;
246239
single_sequence_step_write(framed, buf, written).await
247240
}
248241

249242
pub async fn single_sequence_step_read<S>(
250243
framed: &mut Framed<S>,
251244
sequence: &mut dyn Sequence,
252245
buf: &mut WriteBuf,
253-
unmatched: Option<&mut Vec<Bytes>>,
254246
) -> ConnectorResult<Written>
255247
where
256248
S: FramedRead,
@@ -265,7 +257,7 @@ where
265257
);
266258

267259
let pdu = framed
268-
.read_by_hint(next_pdu_hint, unmatched)
260+
.read_by_hint(next_pdu_hint)
269261
.await
270262
.map_err(|e| ironrdp_connector::custom_err!("read frame by hint", e))?;
271263

crates/ironrdp-blocking/src/connector.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::io::{Read, Write};
22

3-
use bytes::Bytes;
43
use ironrdp_connector::credssp::{CredsspProcessGenerator, CredsspSequence, KerberosConfig};
54
use ironrdp_connector::sspi::credssp::ClientState;
65
use ironrdp_connector::sspi::generator::GeneratorState;
@@ -26,7 +25,7 @@ where
2625
info!("Begin connection procedure");
2726

2827
while !connector.should_perform_security_upgrade() {
29-
single_sequence_step(framed, connector, &mut buf, None)?;
28+
single_sequence_step(framed, connector, &mut buf)?;
3029
}
3130

3231
Ok(ShouldUpgrade)
@@ -79,7 +78,7 @@ where
7978
debug!("Remaining of connection sequence");
8079

8180
let result = loop {
82-
single_sequence_step(framed, &mut connector, &mut buf, None)?;
81+
single_sequence_step(framed, &mut connector, &mut buf)?;
8382

8483
if let ClientConnectorState::Connected { result } = connector.state {
8584
break result;
@@ -168,7 +167,7 @@ where
168167
);
169168

170169
let pdu = framed
171-
.read_by_hint(next_pdu_hint, None)
170+
.read_by_hint(next_pdu_hint)
172171
.map_err(|e| ironrdp_connector::custom_err!("read frame by hint", e))?;
173172

174173
trace!(length = pdu.len(), "PDU received");
@@ -189,7 +188,6 @@ pub fn single_sequence_step<S>(
189188
framed: &mut Framed<S>,
190189
connector: &mut ClientConnector,
191190
buf: &mut WriteBuf,
192-
unmatched: Option<&mut Vec<Bytes>>,
193191
) -> ConnectorResult<()>
194192
where
195193
S: Read + Write,
@@ -204,7 +202,7 @@ where
204202
);
205203

206204
let pdu = framed
207-
.read_by_hint(next_pdu_hint, unmatched)
205+
.read_by_hint(next_pdu_hint)
208206
.map_err(|e| ironrdp_connector::custom_err!("read frame by hint", e))?;
209207

210208
trace!(length = pdu.len(), "PDU received");

crates/ironrdp-blocking/src/framed.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ where
8787
}
8888

8989
/// Reads a frame using the provided PduHint.
90-
pub fn read_by_hint(&mut self, hint: &dyn PduHint, mut unmatched: Option<&mut Vec<Bytes>>) -> io::Result<Bytes> {
90+
pub fn read_by_hint(&mut self, hint: &dyn PduHint) -> io::Result<Bytes> {
9191
loop {
9292
match hint
9393
.find_size(self.peek())
@@ -97,10 +97,8 @@ where
9797
let bytes = self.read_exact(length)?.freeze();
9898
if matched {
9999
return Ok(bytes);
100-
} else if let Some(ref mut unmatched) = unmatched {
101-
unmatched.push(bytes);
102100
} else {
103-
warn!("Received and lost an unexpected PDU");
101+
debug!("Received and lost an unexpected PDU");
104102
}
105103
}
106104
None => {

crates/ironrdp-client/src/rdp.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -295,10 +295,9 @@ async fn active_session(
295295
debug!("Received Server Deactivate All PDU, executing Deactivation-Reactivation Sequence");
296296
let mut buf = WriteBuf::new();
297297
'activation_seq: loop {
298-
let written =
299-
single_sequence_step_read(&mut reader, &mut *connection_activation, &mut buf, None)
300-
.await
301-
.map_err(|e| session::custom_err!("read deactivation-reactivation sequence step", e))?;
298+
let written = single_sequence_step_read(&mut reader, &mut *connection_activation, &mut buf)
299+
.await
300+
.map_err(|e| session::custom_err!("read deactivation-reactivation sequence step", e))?;
302301

303302
if written.size().is_some() {
304303
writer.write_all(buf.filled()).await.map_err(|e| {

crates/ironrdp-server/src/server.rs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -901,32 +901,22 @@ impl RdpServer {
901901
where
902902
S: AsyncRead + AsyncWrite + Sync + Send + Unpin,
903903
{
904-
let mut other_pdus = None;
905-
906904
loop {
907-
let (new_framed, result) = ironrdp_acceptor::accept_finalize(framed, &mut acceptor, other_pdus.as_mut())
905+
let (new_framed, result) = ironrdp_acceptor::accept_finalize(framed, &mut acceptor)
908906
.await
909907
.context("failed to accept client during finalize")?;
910908

911-
let (stream, mut leftover) = new_framed.into_inner();
912-
913-
if let Some(pdus) = other_pdus.take() {
914-
let unmatched_frames = pdus.into_iter().flatten();
915-
let previous_leftover = leftover.split();
916-
leftover.extend(unmatched_frames);
917-
leftover.extend_from_slice(&previous_leftover);
918-
}
919-
920-
let (mut reader, mut writer) = split_tokio_framed(TokioFramed::new_with_leftover(stream, leftover));
909+
let (mut reader, mut writer) = split_tokio_framed(new_framed);
921910

922911
match self.client_accepted(&mut reader, &mut writer, result).await? {
923912
RunState::Continue => {
924913
unreachable!();
925914
}
926915
RunState::DeactivationReactivation { desktop_size } => {
927-
other_pdus = Some(Vec::new());
928-
acceptor = Acceptor::new_deactivation_reactivation(acceptor, desktop_size);
929-
self.attach_channels(&mut acceptor);
916+
acceptor = Acceptor::new_deactivation_reactivation(
917+
acceptor,
918+
desktop_size,
919+
);
930920
framed = unsplit_tokio_framed(reader, writer);
931921
continue;
932922
}

crates/ironrdp-web/src/session.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ impl Session {
653653
let mut buf = WriteBuf::new();
654654
'activation_seq: loop {
655655
let written =
656-
single_sequence_step_read(&mut framed, &mut *box_connection_activation, &mut buf, None)
656+
single_sequence_step_read(&mut framed, &mut *box_connection_activation, &mut buf)
657657
.await?;
658658

659659
if written.size().is_some() {
@@ -1018,7 +1018,7 @@ where
10181018
// RDCleanPath response
10191019

10201020
let rdcleanpath_res = framed
1021-
.read_by_hint(&RDCLEANPATH_HINT, None)
1021+
.read_by_hint(&RDCLEANPATH_HINT)
10221022
.await
10231023
.context("read RDCleanPath request")?;
10241024

0 commit comments

Comments
 (0)