mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-07-13 18:55:09 +03:00
Add authentication details to connection audit (#15456)
* Add authentication details to connection audit Signed-off-by: 21pages <sunboeasy@gmail.com> * rename normalize_conn_audit_primary_auth to normalize_conn_audit_auth_fields Signed-off-by: 21pages <sunboeasy@gmail.com> * Merge permanent password audit methods Signed-off-by: 21pages <sunboeasy@gmail.com> * Simplify connection audit auth methods Signed-off-by: 21pages <sunboeasy@gmail.com> --------- Signed-off-by: 21pages <sunboeasy@gmail.com>
This commit is contained in:
@@ -240,6 +240,36 @@ pub enum AuthConnType {
|
|||||||
Terminal,
|
Terminal,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
#[repr(i64)]
|
||||||
|
enum ConnAuditPrimaryAuth {
|
||||||
|
None = 0,
|
||||||
|
Click = 1,
|
||||||
|
TemporaryPassword = 2,
|
||||||
|
PermanentPassword = 3,
|
||||||
|
SwitchSides = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConnAuditPrimaryAuth {
|
||||||
|
fn as_i64(self) -> i64 {
|
||||||
|
self as i64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
#[repr(i64)]
|
||||||
|
enum ConnAuditTwoFactor {
|
||||||
|
None = 0,
|
||||||
|
Totp = 1,
|
||||||
|
TrustedDevice = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConnAuditTwoFactor {
|
||||||
|
fn as_i64(self) -> i64 {
|
||||||
|
self as i64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
enum TerminalUserToken {
|
enum TerminalUserToken {
|
||||||
@@ -345,6 +375,8 @@ pub struct Connection {
|
|||||||
// For post requests that need to be sent sequentially.
|
// For post requests that need to be sent sequentially.
|
||||||
// eg. post_conn_audit
|
// eg. post_conn_audit
|
||||||
tx_post_seq: mpsc::UnboundedSender<(String, Value)>,
|
tx_post_seq: mpsc::UnboundedSender<(String, Value)>,
|
||||||
|
conn_audit_primary_auth: ConnAuditPrimaryAuth,
|
||||||
|
conn_audit_two_factor: ConnAuditTwoFactor,
|
||||||
// Tracks read job IDs delegated to CM process.
|
// Tracks read job IDs delegated to CM process.
|
||||||
// When a read job is delegated to CM (via FS::ReadFile), the job id is added here.
|
// When a read job is delegated to CM (via FS::ReadFile), the job id is added here.
|
||||||
// Used to filter stale responses (FileBlockFromCM, FileReadDone, etc.) for
|
// Used to filter stale responses (FileBlockFromCM, FileReadDone, etc.) for
|
||||||
@@ -542,6 +574,8 @@ impl Connection {
|
|||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
terminal_user_token: None,
|
terminal_user_token: None,
|
||||||
terminal_generic_service: None,
|
terminal_generic_service: None,
|
||||||
|
conn_audit_primary_auth: ConnAuditPrimaryAuth::None,
|
||||||
|
conn_audit_two_factor: ConnAuditTwoFactor::None,
|
||||||
};
|
};
|
||||||
let addr = hbb_common::try_into_v4(addr);
|
let addr = hbb_common::try_into_v4(addr);
|
||||||
if !conn.on_open(addr).await {
|
if !conn.on_open(addr).await {
|
||||||
@@ -625,6 +659,7 @@ impl Connection {
|
|||||||
Some(data) = rx_from_cm.recv() => {
|
Some(data) = rx_from_cm.recv() => {
|
||||||
match data {
|
match data {
|
||||||
ipc::Data::Authorize => {
|
ipc::Data::Authorize => {
|
||||||
|
conn.set_conn_audit_primary_auth(ConnAuditPrimaryAuth::Click);
|
||||||
conn.require_2fa.take();
|
conn.require_2fa.take();
|
||||||
if !conn.send_logon_response_and_keep_alive().await {
|
if !conn.send_logon_response_and_keep_alive().await {
|
||||||
break;
|
break;
|
||||||
@@ -1471,6 +1506,23 @@ impl Connection {
|
|||||||
crate::post_request(url, v.to_string(), "").await
|
crate::post_request(url, v.to_string(), "").await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_conn_audit_primary_auth(&mut self, method: ConnAuditPrimaryAuth) {
|
||||||
|
self.conn_audit_primary_auth = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_conn_audit_two_factor(&mut self, two_factor: ConnAuditTwoFactor) {
|
||||||
|
self.conn_audit_two_factor = two_factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn normalize_conn_audit_auth_fields(&mut self) {
|
||||||
|
if matches!(
|
||||||
|
self.conn_audit_primary_auth,
|
||||||
|
ConnAuditPrimaryAuth::Click | ConnAuditPrimaryAuth::SwitchSides
|
||||||
|
) {
|
||||||
|
self.conn_audit_two_factor = ConnAuditTwoFactor::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn normalize_port_forward_target(pf: &mut PortForward) -> (String, bool) {
|
fn normalize_port_forward_target(pf: &mut PortForward) -> (String, bool) {
|
||||||
let mut is_rdp = false;
|
let mut is_rdp = false;
|
||||||
if pf.host == "RDP" && pf.port == 0 {
|
if pf.host == "RDP" && pf.port == 0 {
|
||||||
@@ -1594,10 +1646,15 @@ impl Connection {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.get(&self.session_key())
|
.get(&self.session_key())
|
||||||
.map(|s| s.last_recv_time.clone());
|
.map(|s| s.last_recv_time.clone());
|
||||||
self.post_conn_audit(json!({
|
self.normalize_conn_audit_auth_fields();
|
||||||
"peer": ((&self.lr.my_id, &self.lr.my_name)),
|
let mut audit = json!({"peer": ((&self.lr.my_id, &self.lr.my_name)), "type": conn_type});
|
||||||
"type": conn_type,
|
if self.conn_audit_primary_auth != ConnAuditPrimaryAuth::None {
|
||||||
}));
|
audit["primary_auth"] = json!(self.conn_audit_primary_auth.as_i64());
|
||||||
|
}
|
||||||
|
if self.conn_audit_two_factor != ConnAuditTwoFactor::None {
|
||||||
|
audit["two_factor"] = json!(self.conn_audit_two_factor.as_i64());
|
||||||
|
}
|
||||||
|
self.post_conn_audit(audit);
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
let mut username = crate::platform::get_active_username();
|
let mut username = crate::platform::get_active_username();
|
||||||
let mut res = LoginResponse::new();
|
let mut res = LoginResponse::new();
|
||||||
@@ -2209,6 +2266,7 @@ impl Connection {
|
|||||||
if password::temporary_enabled() {
|
if password::temporary_enabled() {
|
||||||
let password = password::temporary_password();
|
let password = password::temporary_password();
|
||||||
if self.validate_password_plain(&password) {
|
if self.validate_password_plain(&password) {
|
||||||
|
self.set_conn_audit_primary_auth(ConnAuditPrimaryAuth::TemporaryPassword);
|
||||||
raii::AuthedConnID::update_or_insert_session(
|
raii::AuthedConnID::update_or_insert_session(
|
||||||
self.session_key(),
|
self.session_key(),
|
||||||
Some(password),
|
Some(password),
|
||||||
@@ -2232,6 +2290,7 @@ impl Connection {
|
|||||||
if local_permanent_password_storage_is_usable_for_auth(&local_storage, &local_salt)
|
if local_permanent_password_storage_is_usable_for_auth(&local_storage, &local_salt)
|
||||||
&& self.validate_password_storage(&local_storage)
|
&& self.validate_password_storage(&local_storage)
|
||||||
{
|
{
|
||||||
|
self.set_conn_audit_primary_auth(ConnAuditPrimaryAuth::PermanentPassword);
|
||||||
print_fallback();
|
print_fallback();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2240,6 +2299,7 @@ impl Connection {
|
|||||||
if preset_permanent_password_storage_is_usable_for_auth(&hard, &salt)
|
if preset_permanent_password_storage_is_usable_for_auth(&hard, &salt)
|
||||||
&& self.validate_preset_password_storage(&hard, &salt)
|
&& self.validate_preset_password_storage(&hard, &salt)
|
||||||
{
|
{
|
||||||
|
self.set_conn_audit_primary_auth(ConnAuditPrimaryAuth::PermanentPassword);
|
||||||
print_fallback();
|
print_fallback();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2264,6 +2324,11 @@ impl Connection {
|
|||||||
&& (tfa && session.tfa
|
&& (tfa && session.tfa
|
||||||
|| !tfa && self.validate_password_plain(&session.random_password))
|
|| !tfa && self.validate_password_plain(&session.random_password))
|
||||||
{
|
{
|
||||||
|
if tfa {
|
||||||
|
self.set_conn_audit_two_factor(ConnAuditTwoFactor::Totp);
|
||||||
|
} else {
|
||||||
|
self.set_conn_audit_primary_auth(ConnAuditPrimaryAuth::TemporaryPassword);
|
||||||
|
}
|
||||||
log::info!("is recent session");
|
log::info!("is recent session");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2357,6 +2422,7 @@ impl Connection {
|
|||||||
&& device.platform == lr.my_platform
|
&& device.platform == lr.my_platform
|
||||||
{
|
{
|
||||||
log::info!("2FA bypassed by trusted devices");
|
log::info!("2FA bypassed by trusted devices");
|
||||||
|
self.set_conn_audit_two_factor(ConnAuditTwoFactor::TrustedDevice);
|
||||||
self.require_2fa = None;
|
self.require_2fa = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2649,6 +2715,7 @@ impl Connection {
|
|||||||
if res {
|
if res {
|
||||||
self.update_failure(failure, true, 1);
|
self.update_failure(failure, true, 1);
|
||||||
self.require_2fa.take();
|
self.require_2fa.take();
|
||||||
|
self.set_conn_audit_two_factor(ConnAuditTwoFactor::Totp);
|
||||||
raii::AuthedConnID::set_session_2fa(self.session_key());
|
raii::AuthedConnID::set_session_2fa(self.session_key());
|
||||||
if !self.send_logon_response_and_keep_alive().await {
|
if !self.send_logon_response_and_keep_alive().await {
|
||||||
return false;
|
return false;
|
||||||
@@ -2704,6 +2771,7 @@ impl Connection {
|
|||||||
if let Some((_instant, uuid_old)) = uuid_old {
|
if let Some((_instant, uuid_old)) = uuid_old {
|
||||||
if uuid == uuid_old {
|
if uuid == uuid_old {
|
||||||
self.from_switch = true;
|
self.from_switch = true;
|
||||||
|
self.set_conn_audit_primary_auth(ConnAuditPrimaryAuth::SwitchSides);
|
||||||
if !self.send_logon_response_and_keep_alive().await {
|
if !self.send_logon_response_and_keep_alive().await {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user