feat(acceptor): negotiate the MCS message channel#1347
Merged
Benoît Cortier (CBenoit) merged 1 commit intoJun 24, 2026
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the server-side acceptor handshake to properly negotiate the MCS message channel by advertising Extended Client Data Blocks support and, when requested by the client, allocating/joining the message channel and surfacing its ID in AcceptorResult. This enables server-initiated PDUs that must use the message channel (e.g., network auto-detect) to have a valid transport.
Changes:
- Set
EXTENDED_CLIENT_DATA_SUPPORTEDin the RDP Negotiation Response so clients sendClient Message Channel Data. - Allocate an MCS message channel ID when requested, advertise it via
Server Message Channel Data, and join it during channel join (unless skip-join is negotiated). - Add tests asserting the extended-client-data flag and the presence of server message channel data with the allocated ID.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
crates/ironrdp-acceptor/src/connection.rs |
Advertises extended client data support, allocates/joins message channel, and exposes message_channel_id on AcceptorResult. |
crates/ironrdp-testsuite-core/tests/server/acceptor.rs |
Adds coverage for negotiation flags and Server Message Channel Data advertisement/ID allocation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Contributor
Author
|
My monitoring protocls broker. I'm working on this now. |
Set the EXTENDED_CLIENT_DATA_SUPPORTED flag in the RDP Negotiation Response so the client sends Client Message Channel Data (section 2.2.1.3.7). When the client requests the message channel, allocate an MCS channel ID for it after the I/O channel and any static virtual channels, return it in Server Message Channel Data (section 2.2.1.4.5), and add it to the set of channels joined during the MCS channel join phase. The allocated ID is surfaced on AcceptorResult so the server can route PDUs that ride the message channel. The immediate consumer is server network auto-detect (section 2.2.14); the channel is also the transport for multitransport bootstrap and heartbeat. Previously the acceptor never advertised the channel, so a spec-compliant client withheld its Client Message Channel Data and these features had no transport.
a81d671 to
30ba311
Compare
Benoît Cortier (CBenoit)
approved these changes
Jun 24, 2026
efa5732
into
Devolutions:master
21 checks passed
Greg Lamberson (glamberson)
added a commit
to lamco-admin/IronRDP
that referenced
this pull request
Jun 24, 2026
NetworkAutoDetect was modeled as a slow-path Share Data PDU (ShareDataPduType::AutoDetect, a fabricated 0x3B) carried on the I/O channel. Per [MS-RDPBCGR] 2.2.14.3 / 2.2.14.4 the auto-detect PDUs are framed by a Basic Security Header (SEC_AUTODETECT_REQ / SEC_AUTODETECT_RSP) and ride the MCS message channel, so neither mstsc nor xfreerdp answered the requests. ironrdp-pdu: add AutoDetectReqPdu / AutoDetectRspPdu, which wrap the request and response data with the security header (mirroring the multitransport PDUs). Remove the ShareDataPdu::AutoDetectReq / AutoDetectRsp variants and the ShareDataPduType::AutoDetect discriminant, which did not correspond to any real PDUTYPE2. ironrdp-server: send auto-detect requests and receive responses on the message channel surfaced by the acceptor, with the new framing. ironrdp-connector and ironrdp-session: the client now requests the message channel (Client Message Channel Data), advertises SUPPORT_NET_CHAR_AUTODETECT, joins the channel, and answers RTT requests on it. The connector handles connect-time auto-detection (previously a no-op) and the session handles continuous auto-detection. Resolves the client side of the message-channel TODO (Devolutions#140). Builds on the acceptor message-channel negotiation merged in Devolutions#1347 (efa5732).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The acceptor never advertised support for Extended Client Data Blocks, so a
spec-compliant client withheld its Client Message Channel Data and the MCS
message channel was never negotiated. Server-initiated PDUs that must ride the
message channel per MS-RDPBCGR (network auto-detect in section 2.2.14,
multitransport bootstrap, heartbeat) therefore had no transport.
This change:
so the client sends Client Message Channel Data (section 2.2.1.3.7).
it after the I/O channel and any static virtual channels, and returns it in
Server Message Channel Data (section 2.2.1.4.5).
client advertises SUPPORT_SKIP_CHANNELJOIN).
that ride this channel.
The immediate consumer is server-side network auto-detect, which a follow-up
will frame correctly and route over this channel. AcceptorResult gains a
message_channel_id field, mirroring the additive shape of the credentials field
added in #1155.
Tested in crates/ironrdp-testsuite-core/tests/server/acceptor.rs: the test
drives the acceptor to the ConnectResponse and asserts Server Message Channel
Data is advertised with the allocated ID, plus the EXTENDED_CLIENT_DATA_SUPPORTED
flag on the connection confirm.