diff --git a/Cargo.lock b/Cargo.lock index cb1bc6d35..102bbc29d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4950,9 +4950,9 @@ dependencies = [ [[package]] name = "sspi" -version = "0.15.6" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27fb016d04750b9ce0b4576bfcdb978cf26a234536f2f6a7697b703e0f5bc048" +checksum = "334391dc5b51751fd80c960b8a40dc8862b903ce41d3b848f154b72ac47ed119" dependencies = [ "async-dnssd", "async-recursion", diff --git a/crates/ironrdp-async/src/connector.rs b/crates/ironrdp-async/src/connector.rs index 4d1b085dc..c50b97728 100644 --- a/crates/ironrdp-async/src/connector.rs +++ b/crates/ironrdp-async/src/connector.rs @@ -132,6 +132,7 @@ where server_name, server_public_key, kerberos_config, + connector.config.vmconnect.is_some(), )?; loop { diff --git a/crates/ironrdp-blocking/src/connector.rs b/crates/ironrdp-blocking/src/connector.rs index 765560e6e..c6cee9573 100644 --- a/crates/ironrdp-blocking/src/connector.rs +++ b/crates/ironrdp-blocking/src/connector.rs @@ -137,6 +137,7 @@ where server_name, server_public_key, kerberos_config, + connector.config.vmconnect.is_some(), )?; loop { diff --git a/crates/ironrdp-client/src/config.rs b/crates/ironrdp-client/src/config.rs index 564a22fef..c7511433f 100644 --- a/crates/ironrdp-client/src/config.rs +++ b/crates/ironrdp-client/src/config.rs @@ -238,6 +238,10 @@ struct Args { /// The bitmap codecs to use (remotefx:on, ...) #[clap(long, value_parser, num_args = 1.., value_delimiter = ',')] codecs: Vec, + + /// The Virtual Machine ID for Hyper-V, used as Pre Connection Blob + #[clap(long)] + vmconnect: Option, } impl Config { @@ -253,21 +257,6 @@ impl Config { .pipe(Destination::new)? }; - let username = if let Some(username) = args.username { - username - } else { - inquire::Text::new("Username:").prompt().context("Username prompt")? - }; - - let password = if let Some(password) = args.password { - password - } else { - inquire::Password::new("Password:") - .without_confirmation() - .prompt() - .context("Password prompt")? - }; - let codecs: Vec<_> = args.codecs.iter().map(|s| s.as_str()).collect(); let codecs = match client_codecs_capabilities(&codecs) { Ok(codecs) => codecs, @@ -302,8 +291,24 @@ impl Config { args.clipboard_type }; + let username = args.username.unwrap_or_else(|| { + inquire::Text::new("Username:") + .prompt() + .context("Username prompt") + .unwrap_or_else(|_| "Administrator".to_owned()) + }); + + let password = args.password.unwrap_or_else(|| { + inquire::Password::new("Password:") + .prompt() + .context("Password prompt") + .unwrap_or_else(|_| "password".to_owned()) + }); + + let credentials = Credentials::UsernamePassword { username, password }; + let connector = connector::Config { - credentials: Credentials::UsernamePassword { username, password }, + credentials, domain: args.domain, enable_tls: !args.no_tls, enable_credssp: !args.no_credssp, @@ -344,6 +349,7 @@ impl Config { request_data: None, pointer_software_rendering: true, performance_flags: PerformanceFlags::default(), + vmconnect: args.vmconnect, }; let rdcleanpath = args diff --git a/crates/ironrdp-client/src/rdp.rs b/crates/ironrdp-client/src/rdp.rs index 3f950d1cf..0169fc2f0 100644 --- a/crates/ironrdp-client/src/rdp.rs +++ b/crates/ironrdp-client/src/rdp.rs @@ -148,7 +148,7 @@ async fn connect( let should_upgrade = ironrdp_tokio::connect_begin(&mut framed, &mut connector).await?; - debug!("TLS upgrade"); + debug!(destination = ?config.destination,"TLS upgrade"); // Ensure there is no leftover let (initial_stream, leftover_bytes) = framed.into_inner(); @@ -292,25 +292,30 @@ where { // RDCleanPath request - let connector::ClientConnectorState::ConnectionInitiationSendRequest = connector.state else { - return Err(connector::general_err!("invalid connector state (send request)")); - }; + match connector.state { + connector::ClientConnectorState::ConnectionInitiationSendRequest { .. } => { + let written = connector.step_no_input(&mut buf)?; + let x224_pdu_len = written.size().expect("written size"); + debug_assert_eq!(x224_pdu_len, buf.filled_len()); + let x224_pdu = buf.filled().to_vec(); + + let rdcleanpath_req = + ironrdp_rdcleanpath::RDCleanPathPdu::new_x224_request(x224_pdu, destination, proxy_auth_token) + .map_err(|e| connector::custom_err!("new RDCleanPath request", e))?; + debug!(message = ?rdcleanpath_req, "Send RDCleanPath request"); + let rdcleanpath_req = rdcleanpath_req + .to_der() + .map_err(|e| connector::custom_err!("RDCleanPath request encode", e))?; + rdcleanpath_req + } + connector::ClientConnectorState::PreconnectionBlob { .. } => {} + _ => { + return Err(connector::general_err!("invalid connector state (send request)")); + } + } debug_assert!(connector.next_pdu_hint().is_none()); - let written = connector.step_no_input(&mut buf)?; - let x224_pdu_len = written.size().expect("written size"); - debug_assert_eq!(x224_pdu_len, buf.filled_len()); - let x224_pdu = buf.filled().to_vec(); - - let rdcleanpath_req = - ironrdp_rdcleanpath::RDCleanPathPdu::new_request(x224_pdu, destination, proxy_auth_token, pcb) - .map_err(|e| connector::custom_err!("new RDCleanPath request", e))?; - debug!(message = ?rdcleanpath_req, "Send RDCleanPath request"); - let rdcleanpath_req = rdcleanpath_req - .to_der() - .map_err(|e| connector::custom_err!("RDCleanPath request encode", e))?; - framed .write_all(&rdcleanpath_req) .await diff --git a/crates/ironrdp-connector/src/connection.rs b/crates/ironrdp-connector/src/connection.rs index 1ee02fb29..19f880ec2 100644 --- a/crates/ironrdp-connector/src/connection.rs +++ b/crates/ironrdp-connector/src/connection.rs @@ -36,7 +36,10 @@ pub enum ClientConnectorState { #[default] Consumed, - ConnectionInitiationSendRequest, + PreconnectionBlob, + ConnectionInitiationSendRequest { + selected_protocol: Option, + }, ConnectionInitiationWaitConfirm { requested_protocol: nego::SecurityProtocol, }, @@ -88,7 +91,8 @@ impl State for ClientConnectorState { fn name(&self) -> &'static str { match self { Self::Consumed => "Consumed", - Self::ConnectionInitiationSendRequest => "ConnectionInitiationSendRequest", + Self::PreconnectionBlob => "PreconnectionBlob", + Self::ConnectionInitiationSendRequest { .. } => "ConnectionInitiationSendRequest", Self::ConnectionInitiationWaitConfirm { .. } => "ConnectionInitiationWaitResponse", Self::EnhancedSecurityUpgrade { .. } => "EnhancedSecurityUpgrade", Self::Credssp { .. } => "Credssp", @@ -132,7 +136,7 @@ impl ClientConnector { pub fn new(config: Config, client_addr: SocketAddr) -> Self { Self { config, - state: ClientConnectorState::ConnectionInitiationSendRequest, + state: ClientConnectorState::PreconnectionBlob, client_addr, static_channels: StaticChannelSet::new(), } @@ -180,7 +184,8 @@ impl Sequence for ClientConnector { fn next_pdu_hint(&self) -> Option<&dyn PduHint> { match &self.state { ClientConnectorState::Consumed => None, - ClientConnectorState::ConnectionInitiationSendRequest => None, + ClientConnectorState::PreconnectionBlob => None, + ClientConnectorState::ConnectionInitiationSendRequest { .. } => None, ClientConnectorState::ConnectionInitiationWaitConfirm { .. } => Some(&ironrdp_pdu::X224_HINT), ClientConnectorState::EnhancedSecurityUpgrade { .. } => None, ClientConnectorState::Credssp { .. } => None, @@ -211,12 +216,86 @@ impl Sequence for ClientConnector { ClientConnectorState::Consumed => { return Err(general_err!("connector sequence state is consumed (this is a bug)",)) } + ClientConnectorState::PreconnectionBlob => 'state: { + let Some(connection_id) = self.config.vmconnect.as_ref() else { + break 'state ( + Written::Nothing, + ClientConnectorState::ConnectionInitiationSendRequest { + selected_protocol: None, + }, + ); + }; + + let pcb = ironrdp_pdu::pcb::PreconnectionBlob { + version: ironrdp_pdu::pcb::PcbVersion::V2, + id: 0, + // v2_payload: Some(connection_id.to_owned()), + v2_payload: Some(format!("{connection_id};EnhancedMode=1").into()), + }; + + debug!(message = ?pcb, "Send"); + + let written = ironrdp_core::encode_buf(&pcb, output).map_err(ConnectorError::encode)?; + + let mut security_protocol = nego::SecurityProtocol::empty(); + if self.config.enable_tls { + security_protocol.insert(nego::SecurityProtocol::SSL); + } + + if self.config.enable_credssp { + // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/902b090b-9cb3-4efc-92bf-ee13373371e3 + // The spec is stating that `PROTOCOL_SSL` "SHOULD" also be set when using `PROTOCOL_HYBRID`. + // > PROTOCOL_HYBRID (0x00000002) + // > Credential Security Support Provider protocol (CredSSP) (section 5.4.5.2). + // > If this flag is set, then the PROTOCOL_SSL (0x00000001) flag SHOULD also be set + // > because Transport Layer Security (TLS) is a subset of CredSSP. + // However, crucially, it’s not strictly required (not "MUST"). + // In fact, we purposefully choose to not set `PROTOCOL_SSL` unless `enable_winlogon` is `true`. + // This tells the server that we are not going to accept downgrading NLA to TLS security. + security_protocol.insert(nego::SecurityProtocol::HYBRID | nego::SecurityProtocol::HYBRID_EX); + } + if security_protocol.is_standard_rdp_security() { + return Err(reason_err!("Initiation", "standard RDP security is not supported",)); + } + + break 'state ( + Written::from_size(written)?, + ClientConnectorState::EnhancedSecurityUpgrade { + selected_protocol: security_protocol, + }, + ); + } //== Connection Initiation ==// // Exchange supported security protocols and a few other connection flags. - ClientConnectorState::ConnectionInitiationSendRequest => { + ClientConnectorState::ConnectionInitiationSendRequest { selected_protocol } => 'state: { debug!("Connection Initiation"); + if self.config.vmconnect.is_some() { + let selected_protocol = selected_protocol.ok_or(reason_err!( + "Initiation", + "VMConnect requires a selected protocol at ConnectionInitiationSendRequest state", + ))?; + + let connection_request = nego::ConnectionRequest { + nego_data: None, + flags: nego::RequestFlags::empty(), + protocol: selected_protocol, + }; + + debug!(message = ?connection_request, "Send"); + + let written = + ironrdp_core::encode_buf(&X224(connection_request), output).map_err(ConnectorError::encode)?; + + break 'state ( + Written::from_size(written)?, + ClientConnectorState::ConnectionInitiationWaitConfirm { + requested_protocol: selected_protocol, + }, + ); + } + let mut security_protocol = nego::SecurityProtocol::empty(); if self.config.enable_tls { @@ -289,7 +368,10 @@ impl Sequence for ClientConnector { ( Written::Nothing, - ClientConnectorState::EnhancedSecurityUpgrade { selected_protocol }, + match self.config.vmconnect.is_some() { + false => ClientConnectorState::EnhancedSecurityUpgrade { selected_protocol }, + true => ClientConnectorState::BasicSettingsExchangeSendInitial { selected_protocol }, + }, ) } @@ -311,10 +393,20 @@ impl Sequence for ClientConnector { } //== CredSSP ==// - ClientConnectorState::Credssp { selected_protocol } => ( - Written::Nothing, - ClientConnectorState::BasicSettingsExchangeSendInitial { selected_protocol }, - ), + ClientConnectorState::Credssp { selected_protocol } => 'state: { + if self.config.vmconnect.is_some() { + break 'state ( + Written::Nothing, + ClientConnectorState::ConnectionInitiationSendRequest { + selected_protocol: Some(selected_protocol), + }, + ); + } + ( + Written::Nothing, + ClientConnectorState::BasicSettingsExchangeSendInitial { selected_protocol }, + ) + } //== Basic Settings Exchange ==// // Exchange basic settings including Core Data, Security Data and Network Data. diff --git a/crates/ironrdp-connector/src/lib.rs b/crates/ironrdp-connector/src/lib.rs index 8a4558df4..cd8e1796a 100644 --- a/crates/ironrdp-connector/src/lib.rs +++ b/crates/ironrdp-connector/src/lib.rs @@ -187,6 +187,8 @@ pub struct Config { pub no_server_pointer: bool, pub pointer_software_rendering: bool, pub performance_flags: PerformanceFlags, + + pub vmconnect: Option, } ironrdp_core::assert_impl!(Config: Send, Sync); diff --git a/crates/ironrdp-core/src/cursor.rs b/crates/ironrdp-core/src/cursor.rs index 4501377f8..2ddf8db45 100644 --- a/crates/ironrdp-core/src/cursor.rs +++ b/crates/ironrdp-core/src/cursor.rs @@ -578,6 +578,12 @@ impl<'a> WriteCursor<'a> { self.pos } + /// Returns the number of bytes written. + #[inline] + pub const fn bytes_written(&self) -> usize { + self.pos + } + /// Write an array of bytes to the buffer. #[inline] #[track_caller] diff --git a/crates/ironrdp-pdu/src/rdp/client_info.rs b/crates/ironrdp-pdu/src/rdp/client_info.rs index dff21f04f..f550df4e6 100644 --- a/crates/ironrdp-pdu/src/rdp/client_info.rs +++ b/crates/ironrdp-pdu/src/rdp/client_info.rs @@ -313,6 +313,9 @@ impl Encode for ExtendedClientOptionalInfo { dst.write_array(reconnect_cookie); } + dst.write_u16(0); // reserved1 + dst.write_u16(0); // reserved2 + Ok(()) } @@ -336,6 +339,8 @@ impl Encode for ExtendedClientOptionalInfo { size += RECONNECT_COOKIE_LENGTH_SIZE + RECONNECT_COOKIE_LEN; } + size += 2 * 2; // reserved1 and reserved2 + size } } diff --git a/crates/ironrdp-rdcleanpath/src/lib.rs b/crates/ironrdp-rdcleanpath/src/lib.rs index 4294b5977..a6c4fb0e3 100644 --- a/crates/ironrdp-rdcleanpath/src/lib.rs +++ b/crates/ironrdp-rdcleanpath/src/lib.rs @@ -197,30 +197,34 @@ impl RDCleanPathPdu { } } - pub fn new_request( - x224_pdu: Vec, - destination: String, - proxy_auth: String, - pcb: Option, - ) -> der::Result { + pub fn new_x224_request(x224_pdu: Vec, destination: String, proxy_auth: String) -> der::Result { Ok(Self { version: VERSION_1, destination: Some(destination), proxy_auth: Some(proxy_auth), - preconnection_blob: pcb, x224_connection_pdu: Some(OctetString::new(x224_pdu)?), ..Self::default() }) } + pub fn new_pcb_request(preconnection_blob: String, destination: String, proxy_auth: String) -> der::Result { + Ok(Self { + version: VERSION_1, + destination: Some(destination), + proxy_auth: Some(proxy_auth), + preconnection_blob: Some(preconnection_blob), + ..Self::default() + }) + } + pub fn new_response( server_addr: String, - x224_pdu: Vec, + x224_pdu: Option>, x509_chain: impl IntoIterator>, ) -> der::Result { Ok(Self { version: VERSION_1, - x224_connection_pdu: Some(OctetString::new(x224_pdu)?), + x224_connection_pdu: x224_pdu.map(OctetString::new).transpose()?, server_cert_chain: Some( x509_chain .into_iter() diff --git a/crates/ironrdp-testsuite-core/tests/pcb.rs b/crates/ironrdp-testsuite-core/tests/pcb.rs index c31dd812f..546a57335 100644 --- a/crates/ironrdp-testsuite-core/tests/pcb.rs +++ b/crates/ironrdp-testsuite-core/tests/pcb.rs @@ -84,6 +84,15 @@ encode_decode_test! { "004b00770056004d0048004300660059007400650036004900330066004c006100590031005f006200330053007200", "77005800490057006a006e00350041000000" )).expect("pcb_v2_with_jwt payload"); + v2_hyperv_guid : + PreconnectionBlob { + version: PcbVersion::V2, + id: 0, + v2_payload: Some(String::from("ff995b48-a34f-404a-938f-303e4bb5bf31")), + }, + hex::decode(concat!( + "5c0000000000000002000000000000002500660066003900390035006200340038002d0061003300340066002d0034003000340061002d0039003300380066002d003300300033006500340062006200350062006600330031000000" + )).expect("v2_hyperv_guid payload"); } const PRECONNECTION_PDU_V1_NULL_SIZE_BUF: [u8; 16] = [ @@ -165,4 +174,4 @@ fn pcb_v2_string_too_big() { } "#]] .assert_debug_eq(&e); -} +} \ No newline at end of file diff --git a/crates/ironrdp-testsuite-core/tests/rdcleanpath.rs b/crates/ironrdp-testsuite-core/tests/rdcleanpath.rs index 4c91f3b34..569d0d96b 100644 --- a/crates/ironrdp-testsuite-core/tests/rdcleanpath.rs +++ b/crates/ironrdp-testsuite-core/tests/rdcleanpath.rs @@ -2,7 +2,7 @@ use ironrdp_rdcleanpath::{DetectionResult, RDCleanPathPdu, VERSION_1}; use rstest::rstest; fn request() -> RDCleanPathPdu { - RDCleanPathPdu::new_request( + RDCleanPathPdu::new_x224_request( vec![0xDE, 0xAD, 0xBE, 0xFF], "destination".to_owned(), "proxy auth".to_owned(), diff --git a/crates/ironrdp-testsuite-extra/tests/tests.rs b/crates/ironrdp-testsuite-extra/tests/tests.rs index 53cbfc118..2aa108218 100644 --- a/crates/ironrdp-testsuite-extra/tests/tests.rs +++ b/crates/ironrdp-testsuite-extra/tests/tests.rs @@ -302,5 +302,6 @@ fn default_client_config() -> connector::Config { no_server_pointer: true, pointer_software_rendering: true, performance_flags: Default::default(), + vmconnect: None, } } diff --git a/crates/ironrdp-web/src/session.rs b/crates/ironrdp-web/src/session.rs index 39b773a60..168fe03fc 100644 --- a/crates/ironrdp-web/src/session.rs +++ b/crates/ironrdp-web/src/session.rs @@ -315,7 +315,6 @@ impl iron_remote_desktop::SessionBuilder for SessionBuilder { config, proxy_auth_token: auth_token, destination, - pcb, kdc_proxy_url, clipboard_backend: clipboard.as_ref().map(|clip| clip.backend()), use_display_control, @@ -861,6 +860,8 @@ fn build_config( desktop_scale_factor: 0, hardware_id: None, license_cache: None, + // TODO: implement this + vmconnect: None, } } @@ -890,7 +891,6 @@ struct ConnectParams { config: connector::Config, proxy_auth_token: String, destination: String, - pcb: Option, kdc_proxy_url: Option, clipboard_backend: Option, use_display_control: bool, @@ -902,7 +902,6 @@ async fn connect( config, proxy_auth_token, destination, - pcb, kdc_proxy_url, clipboard_backend, use_display_control, @@ -926,7 +925,7 @@ async fn connect( } let (upgraded, server_public_key) = - connect_rdcleanpath(&mut framed, &mut connector, destination.clone(), proxy_auth_token, pcb).await?; + connect_rdcleanpath(&mut framed, &mut connector, destination.clone(), proxy_auth_token).await?; let connection_result = ironrdp_futures::connect_finalize( upgraded, @@ -956,7 +955,6 @@ async fn connect_rdcleanpath( connector: &mut ClientConnector, destination: String, proxy_auth_token: String, - pcb: Option, ) -> Result<(ironrdp_futures::Upgraded, Vec), IronError> where S: ironrdp_futures::FramedRead + FramedWrite, @@ -986,30 +984,53 @@ where info!("Begin connection procedure"); + debug!(?connector, "Connector state before RDCleanPath request"); { - // RDCleanPath request + let rdcleanpath_req = match connector.state { + connector::ClientConnectorState::ConnectionInitiationSendRequest { .. } => { + debug_assert!(connector.next_pdu_hint().is_none()); - let connector::ClientConnectorState::ConnectionInitiationSendRequest = connector.state else { - return Err(anyhow::Error::msg("invalid connector state (send request)").into()); - }; + let written = connector.step_no_input(&mut buf)?; + let x224_pdu_len = written.size().expect("written size"); + debug_assert_eq!(x224_pdu_len, buf.filled_len()); + let x224_pdu = buf.filled().to_vec(); - debug_assert!(connector.next_pdu_hint().is_none()); + let rdcleanpath_req = + ironrdp_rdcleanpath::RDCleanPathPdu::new_x224_request(x224_pdu, destination, proxy_auth_token) + .context("new RDCleanPath request")?; - let written = connector.step_no_input(&mut buf)?; - let x224_pdu_len = written.size().expect("written size"); - debug_assert_eq!(x224_pdu_len, buf.filled_len()); - let x224_pdu = buf.filled().to_vec(); + rdcleanpath_req + } + connector::ClientConnectorState::PreconnectionBlob => { + debug_assert!(connector.next_pdu_hint().is_none()); + let written = connector.step_no_input(&mut buf)?; + let pcb_len = written.size().expect("written size"); + debug_assert_eq!(pcb_len, buf.filled_len()); + let preconnection_blob = buf.filled().to_vec(); + + let rdcleanpath_req = ironrdp_rdcleanpath::RDCleanPathPdu::new_vmconnect_request( + preconnection_blob, + destination, + proxy_auth_token, + ) + .context("new RDCleanPath preconnection blob request")?; + + rdcleanpath_req + } + _ => { + return Err(anyhow::Error::msg("invalid connector state (send request)").into()); + } + }; - let rdcleanpath_req = - ironrdp_rdcleanpath::RDCleanPathPdu::new_request(x224_pdu, destination, proxy_auth_token, pcb) - .context("new RDCleanPath request")?; - debug!(message = ?rdcleanpath_req, "Send RDCleanPath request"); - let rdcleanpath_req = rdcleanpath_req.to_der().context("RDCleanPath request encode")?; + debug!(message = ?rdcleanpath_req, "Send RDCleanPath preconnection blob request"); + let rdcleanpath_req = rdcleanpath_req + .to_der() + .context("RDCleanPath preconnection blob request encode")?; framed .write_all(&rdcleanpath_req) .await - .context("couldn’t write RDCleanPath request")?; + .context("couldn’t write RDCleanPath preconnection blob request")?; } { @@ -1050,7 +1071,11 @@ where debug_assert!(connector.next_pdu_hint().is_some()); buf.clear(); - let written = connector.step(x224_connection_response.as_bytes(), &mut buf)?; + + let written = match x224_connection_response { + Some(x224_connection_response) => connector.step(x224_connection_response.as_bytes(), &mut buf)?, + None => connector.step_no_input(&mut buf)?, + }; debug_assert!(written.is_nothing()); diff --git a/ffi/src/connector/config.rs b/ffi/src/connector/config.rs index ac49ae3c6..922e262ea 100644 --- a/ffi/src/connector/config.rs +++ b/ffi/src/connector/config.rs @@ -42,6 +42,7 @@ pub mod ffi { pub no_audio_playback: Option, pub pointer_software_rendering: Option, pub performance_flags: Option, + pub vmconnect: Option, } #[diplomat::enum_convert(ironrdp::pdu::gcc::KeyboardType)] @@ -152,6 +153,10 @@ pub mod ffi { self.pointer_software_rendering = Some(pointer_software_rendering); } + pub fn set_vm_connect(&mut self, vmconnect: &str) { + self.vmconnect = Some(vmconnect.to_owned()); + } + pub fn build(&self) -> Result, Box> { let inner_config = ironrdp::connector::Config { credentials: self.credentials.clone().ok_or("credentials not set")?, @@ -200,6 +205,7 @@ pub mod ffi { desktop_scale_factor: 0, hardware_id: None, license_cache: None, + vmconnect: self.vmconnect.clone(), }; tracing::debug!(config=?inner_config, "Built config"); Ok(Box::new(Config(inner_config))) diff --git a/ffi/src/connector/state.rs b/ffi/src/connector/state.rs index 97ccfeae1..70ff3deee 100644 --- a/ffi/src/connector/state.rs +++ b/ffi/src/connector/state.rs @@ -33,7 +33,7 @@ pub mod ffi { .ok_or_else(|| ValueConsumedError::for_item("ClientConnectorState"))? { ironrdp::connector::ClientConnectorState::Consumed => ClientConnectorStateType::Consumed, - ironrdp::connector::ClientConnectorState::ConnectionInitiationSendRequest => { + ironrdp::connector::ClientConnectorState::ConnectionInitiationSendRequest { .. } => { ClientConnectorStateType::ConnectionInitiationSendRequest } ironrdp::connector::ClientConnectorState::ConnectionInitiationWaitConfirm { .. } => { diff --git a/ffi/src/credssp/mod.rs b/ffi/src/credssp/mod.rs index b912d2685..76bdd370b 100644 --- a/ffi/src/credssp/mod.rs +++ b/ffi/src/credssp/mod.rs @@ -54,6 +54,7 @@ pub mod ffi { server_name: &str, server_public_key: &[u8], kerbero_configs: Option<&KerberosConfig>, + vmconnect: bool, ) -> Result, Box> { let Some(connector) = connector.0.as_ref() else { return Err(ValueConsumedError::for_item("connector").into()); @@ -68,6 +69,7 @@ pub mod ffi { server_name.into(), server_public_key.to_owned(), kerbero_configs.map(|config| config.0.clone()), + vmconnect, )?; Ok(Box::new(CredsspSequenceInitResult { diff --git a/web-client/iron-svelte-client/src/lib/login/login.svelte b/web-client/iron-svelte-client/src/lib/login/login.svelte index 7dc19cf05..0dc302a3d 100644 --- a/web-client/iron-svelte-client/src/lib/login/login.svelte +++ b/web-client/iron-svelte-client/src/lib/login/login.svelte @@ -11,12 +11,12 @@ let username = 'Administrator'; let password = 'DevoLabs123!'; let gatewayAddress = 'ws://localhost:7171/jet/rdp'; - let hostname = '10.10.0.3:3389'; + let hostname = import.meta.env.VITE_IRON_HOSTNAME ?? '10.10.0.3:3389'; let domain = ''; let authtoken = ''; let kdc_proxy_url = ''; let desktopSize = { width: 1280, height: 720 }; - let pcb = ''; + let pcb = import.meta.env.VITE_IRON_RDP_PCB ?? ''; let pop_up = false; let enable_clipboard = true; diff --git a/xtask/src/check.rs b/xtask/src/check.rs index ed44a721e..bd3038827 100644 --- a/xtask/src/check.rs +++ b/xtask/src/check.rs @@ -9,6 +9,7 @@ pub fn fmt(sh: &Shell) -> anyhow::Result<()> { anyhow::bail!("Bad formatting, please run 'cargo +stable fmt --all'"); } + println!("All good!"); Ok(())