@@ -257,58 +257,59 @@ async fn process_cleanpath(
257257 // and X224 connection request/response to IronRDP client
258258 // - Without PCB: Gateway handles (1) X224 connection request, (2) X224 connection response,
259259 // then leaves TLS handshake and CredSSP to IronRDP client
260- let ( server_stream, x224_rsp) = if let Some ( pcb_string) = cleanpath_pdu. preconnection_blob {
261- debug ! ( "Sending preconnection blob to server" ) ;
262- let pcb = ironrdp_pdu:: pcb:: PreconnectionBlob {
263- version : ironrdp_pdu:: pcb:: PcbVersion :: V2 ,
264- id : 0 ,
265- v2_payload : Some ( pcb_string) ,
266- } ;
267-
268- let encoded = ironrdp_core:: encode_vec ( & pcb)
269- . context ( "failed to encode preconnection blob" )
270- . map_err ( CleanPathError :: BadRequest ) ?;
271-
272- server_stream. write_all ( & encoded) . await ?;
273-
274- let server_stream = crate :: tls:: connect ( selected_target. host ( ) . to_owned ( ) , server_stream)
275- . await
276- . map_err ( |source| CleanPathError :: TlsHandshake {
277- source,
278- target_server : selected_target. to_owned ( ) ,
279- } ) ?;
280-
281- ( server_stream, None )
282- } else {
283- // Send X224 connection request
284- let x224_req = cleanpath_pdu
285- . x224_connection_pdu
286- . context ( "request is missing X224 connection PDU" )
287- . map_err ( CleanPathError :: BadRequest ) ?;
260+ // Send preconnection blob and/or X224 connection request
261+ match ( & cleanpath_pdu. preconnection_blob , & cleanpath_pdu. x224_connection_pdu ) {
262+ ( None , None ) => {
263+ return Err ( CleanPathError :: BadRequest ( anyhow:: anyhow!(
264+ "RDCleanPath PDU is missing both preconnection blob and X224 connection PDU"
265+ ) ) ) ;
266+ }
267+ ( Some ( general_pcb) , Some ( _) ) => {
268+ server_stream. write_all ( general_pcb. as_bytes ( ) ) . await ?;
269+ }
270+ ( None , Some ( _) ) => { } // no preconnection blob to send
271+ // This is considered to be the case where the preconnection blob is used for Hyper-V VMs connection
272+ ( Some ( pcb) , None ) => {
273+ debug ! ( "Sending preconnection blob to server" ) ;
274+ let pcb = ironrdp_pdu:: pcb:: PreconnectionBlob {
275+ version : ironrdp_pdu:: pcb:: PcbVersion :: V2 ,
276+ id : 0 ,
277+ v2_payload : Some ( pcb. clone ( ) ) ,
278+ } ;
279+
280+ let encoded = ironrdp_core:: encode_vec ( & pcb)
281+ . context ( "failed to encode preconnection blob" )
282+ . map_err ( CleanPathError :: BadRequest ) ?;
283+
284+ server_stream. write_all ( & encoded) . await ?;
285+ }
286+ }
288287
289- server_stream. write_all ( x224_req. as_bytes ( ) ) . await ?;
288+ // Send X224 connection request if present
289+ let x224_rsp = if let Some ( x224_connection_pdu) = & cleanpath_pdu. x224_connection_pdu {
290+ server_stream. write_all ( x224_connection_pdu. as_bytes ( ) ) . await ?;
291+ debug ! ( "X224 connection request sent" ) ;
290292
291293 let x224_rsp = read_x224_response ( & mut server_stream)
292294 . await
293295 . with_context ( || format ! ( "read X224 response from {selected_target}" ) )
294296 . map_err ( CleanPathError :: BadRequest ) ?;
295297 trace ! ( "Receiving X224 response" ) ;
296298
297- let server_stream = crate :: tls:: connect ( selected_target. host ( ) . to_owned ( ) , server_stream)
298- . await
299- . map_err ( |source| CleanPathError :: TlsHandshake {
300- source,
301- target_server : selected_target. to_owned ( ) ,
302- } ) ?;
303- debug ! ( "X224 connection request sent" ) ;
304-
305- // Receive server X224 connection response
306-
307- trace ! ( "Establishing TLS connection with server" ) ;
308-
309- ( server_stream, Some ( x224_rsp) )
299+ Some ( x224_rsp)
300+ } else {
301+ None
310302 } ;
311303
304+ // Establish TLS connection
305+ trace ! ( "Establishing TLS connection with server" ) ;
306+ let server_stream = crate :: tls:: connect ( selected_target. host ( ) . to_owned ( ) , server_stream)
307+ . await
308+ . map_err ( |source| CleanPathError :: TlsHandshake {
309+ source,
310+ target_server : selected_target. to_owned ( ) ,
311+ } ) ?;
312+
312313 return Ok ( CleanPathResult {
313314 destination : selected_target. to_owned ( ) ,
314315 claims,
@@ -379,8 +380,12 @@ pub async fn handle(
379380
380381 trace ! ( "Sending RDCleanPath response" ) ;
381382
382- let rdcleanpath_rsp = RDCleanPathPdu :: new_response ( server_addr. to_string ( ) , x224_rsp, x509_chain)
383- . map_err ( |e| anyhow:: anyhow!( "couldn’t build RDCleanPath response: {e}" ) ) ?;
383+ let rdcleanpath_rsp = RDCleanPathPdu :: new_response (
384+ server_addr. to_string ( ) ,
385+ x224_rsp,
386+ x509_chain,
387+ )
388+ . map_err ( |e| anyhow:: anyhow!( "couldn’t build RDCleanPath response: {e}" ) ) ?;
384389
385390 send_clean_path_response ( & mut client_stream, & rdcleanpath_rsp) . await ?;
386391
0 commit comments