diff --git a/src/client.rs b/src/client.rs index 321a49ee6..fdc91ff0f 100644 --- a/src/client.rs +++ b/src/client.rs @@ -30,6 +30,7 @@ use uuid::Uuid; use crate::{ check_port, common::input::{MOUSE_BUTTON_LEFT, MOUSE_BUTTON_RIGHT, MOUSE_TYPE_DOWN, MOUSE_TYPE_UP}, + common::PLATFORM_ADDITION_IS_LOGIN_SCREEN, create_symmetric_key_msg, decode_id_pk, get_rs_pk, is_keyboard_mode_supported, kcp_stream::KcpStream, secure_tcp, @@ -1901,11 +1902,11 @@ impl LoginConfigHandler { /// Check if the client should auto login. /// Return password if the client should auto login, otherwise return empty string. - pub fn should_auto_login(&self) -> String { + pub fn should_auto_login(&self, pi: &PeerInfo) -> String { let l = self.lock_after_session_end.v; let a = !self.get_option("auto-login").is_empty(); let p = self.get_option("os-password"); - if !p.is_empty() && l && a { + if !p.is_empty() && l && a && !peer_reports_unlocked_desktop(pi) { p } else { "".to_owned() @@ -2804,6 +2805,67 @@ impl LoginConfigHandler { } } +fn peer_reports_unlocked_desktop(pi: &PeerInfo) -> bool { + serde_json::from_str::>(&pi.platform_additions) + .ok() + .and_then(|platform_additions| { + platform_additions + .get(PLATFORM_ADDITION_IS_LOGIN_SCREEN) + .and_then(|value| value.as_bool()) + }) + == Some(false) +} + +#[cfg(test)] +mod tests { + use hbb_common::message_proto::PeerInfo; + + fn login_config_handler() -> super::LoginConfigHandler { + let mut handler = super::LoginConfigHandler::default(); + handler.config.lock_after_session_end.v = true; + handler + .config + .options + .insert("auto-login".to_owned(), "Y".to_owned()); + handler + .config + .options + .insert("os-password".to_owned(), "secret".to_owned()); + handler + } + + fn peer_info(platform_additions: &str) -> PeerInfo { + PeerInfo { + platform_additions: platform_additions.to_owned(), + ..Default::default() + } + } + + #[test] + fn should_auto_login_skips_unlocked_peer() { + let handler = login_config_handler(); + let pi = peer_info(r#"{"is_login_screen":false}"#); + + assert_eq!("", handler.should_auto_login(&pi)); + } + + #[test] + fn should_auto_login_keeps_peer_on_login_screen() { + let handler = login_config_handler(); + let pi = peer_info(r#"{"is_login_screen":true}"#); + + assert_eq!("secret", handler.should_auto_login(&pi)); + } + + #[test] + fn should_auto_login_keeps_legacy_peer_without_login_screen_state() { + let handler = login_config_handler(); + let pi = peer_info(""); + + assert_eq!("secret", handler.should_auto_login(&pi)); + } +} + /// Media data. pub enum MediaData { VideoQueue, diff --git a/src/common.rs b/src/common.rs index 69e3ec304..070813fb5 100644 --- a/src/common.rs +++ b/src/common.rs @@ -59,6 +59,7 @@ pub const PLATFORM_WINDOWS: &str = "Windows"; pub const PLATFORM_LINUX: &str = "Linux"; pub const PLATFORM_MACOS: &str = "Mac OS"; pub const PLATFORM_ANDROID: &str = "Android"; +pub const PLATFORM_ADDITION_IS_LOGIN_SCREEN: &str = "is_login_screen"; pub const TIMER_OUT: Duration = Duration::from_secs(1); pub const DEFAULT_KEEP_ALIVE: i32 = 60_000; diff --git a/src/server/connection.rs b/src/server/connection.rs index 5e0825bc4..1f3ba08f8 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -1623,6 +1623,10 @@ impl Connection { } #[cfg(target_os = "macos")] { + platform_additions.insert( + crate::common::PLATFORM_ADDITION_IS_LOGIN_SCREEN.into(), + json!(crate::platform::is_prelogin() || crate::platform::is_locked()), + ); platform_additions.insert( "supported_privacy_mode_impl".into(), json!(privacy_mode::get_supported_privacy_mode_impl()), diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index ddc2574f2..523c23af0 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -1806,7 +1806,7 @@ impl Interface for Session { return; } self.try_change_init_resolution(pi.current_display); - let p = self.lc.read().unwrap().should_auto_login(); + let p = self.lc.read().unwrap().should_auto_login(&pi); if !p.is_empty() { input_os_password(p, true, self.clone()); }