mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-08 21:41:02 +03:00
fix(client): allow switch-sides back-connection in incoming-only mode (#15780)
* fix(client): allow switch-sides back-connection in incoming-only mode "Switch sides" makes the controlled client run `--connect <peer> --switch_uuid <uuid>`, which Client::_start rejected outright in incoming-only custom clients, so the feature silently dropped the session and never switched. Exempt exactly that back-connection: a default-conn session carrying a switch uuid may proceed. The uuid is then verified against the local server process in handle_hash(); if it is missing there (forged or expired), an incoming-only client now aborts with an error instead of falling through to password login, so the outgoing-connection restriction cannot be bypassed with a crafted --switch_uuid. Fixes rustdesk/rustdesk#11200 (discussion) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(client): validate switch-back grants before connecting - check pending peer/UUID grants before bypassing incoming-only mode - close rejected switch-back connections and suppress retries - keep grant consumption in handle_hash and test non-consuming checks Signed-off-by: 21pages <sunboeasy@gmail.com> * fix(client): prevent switch-back UUID reuse - claim pending switch-back grants before connecting - retain claimed grants to reject duplicate requests - bind authorization to the peer ID and UUID - use a shared TTL for switch-back grants Signed-off-by: 21pages <sunboeasy@gmail.com> * fix(client): defer switch UUID consumption until authentication Signed-off-by: 21pages <sunboeasy@gmail.com> * fix(client): reject repeated hash login in incoming-only mode Signed-off-by: 21pages <sunboeasy@gmail.com> --------- Signed-off-by: 21pages <sunboeasy@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: 21pages <sunboeasy@gmail.com>
This commit is contained in:
23
src/ipc.rs
23
src/ipc.rs
@@ -312,6 +312,14 @@ pub enum DataPortableService {
|
||||
CmShowElevation(bool),
|
||||
}
|
||||
|
||||
#[cfg(feature = "flutter")]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum SwitchSidesUuidAction {
|
||||
Check,
|
||||
Consume,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
pub enum Data {
|
||||
@@ -387,7 +395,7 @@ pub enum Data {
|
||||
SwitchSidesRequest(String),
|
||||
#[cfg(feature = "flutter")]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
SwitchSidesUuid(String, String, Option<bool>),
|
||||
SwitchSidesUuid(String, String, SwitchSidesUuidAction, Option<bool>),
|
||||
#[cfg(feature = "flutter")]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
SwitchSidesBack,
|
||||
@@ -1050,14 +1058,21 @@ async fn handle(data: Data, stream: &mut Connection) {
|
||||
}
|
||||
#[cfg(feature = "flutter")]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
Data::SwitchSidesUuid(uuid, id, None) => {
|
||||
Data::SwitchSidesUuid(uuid, id, action, None) => {
|
||||
let allowed = uuid
|
||||
.parse::<uuid::Uuid>()
|
||||
.map(|uuid| crate::server::remove_pending_switch_sides_uuid(&id, &uuid))
|
||||
.map(|uuid| match action {
|
||||
SwitchSidesUuidAction::Check => {
|
||||
crate::server::has_pending_switch_sides_uuid(&id, &uuid)
|
||||
}
|
||||
SwitchSidesUuidAction::Consume => {
|
||||
crate::server::claim_pending_switch_sides_uuid(&id, &uuid)
|
||||
}
|
||||
})
|
||||
.unwrap_or(false);
|
||||
allow_err!(
|
||||
stream
|
||||
.send(&Data::SwitchSidesUuid(uuid, id, Some(allowed)))
|
||||
.send(&Data::SwitchSidesUuid(uuid, id, action, Some(allowed)))
|
||||
.await
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user