From 8a87d3d87e51d8977ad1f5837061f6ba027d0207 Mon Sep 17 00:00:00 2001 From: 21pages Date: Mon, 2 Feb 2026 10:48:04 +0800 Subject: [PATCH 1/6] easy access Signed-off-by: 21pages --- protos/message.proto | 9 +++++---- protos/rendezvous.proto | 20 +++++++++++++++----- src/config.rs | 5 +++++ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/protos/message.proto b/protos/message.proto index 8b2136811..08808d6a1 100644 --- a/protos/message.proto +++ b/protos/message.proto @@ -88,10 +88,11 @@ message LoginRequest { string my_platform = 13; bytes hwid = 14; string avatar = 17; + bytes easy_access_challenge = 18; } message Terminal { - string service_id = 1; // Service ID for reconnecting to existing session + string service_id = 1; // Service ID for reconnecting to existing session } message Auth2FA { @@ -439,7 +440,7 @@ message FileTransferDigest { bool is_upload = 5; bool is_identical = 6; uint64 transferred_size = 7; // For resume. Indicates the size of the file already transferred - bool is_resume = 8; // For resume. Indicates if the transfer is a resume. + bool is_resume = 8; // For resume. Indicates if the transfer is a resume. // `is_resume` can let the controlled side know whether to check the `.digest` file. // When `is_resume` is false, `.digest` exists, the same file does not exist, // the controlled side should not check `.digest`, it should confirm with a new transfer request. @@ -890,7 +891,7 @@ message ScreenshotResponse { // Terminal messages - standalone feature like FileAction message OpenTerminal { - int32 terminal_id = 1; // 0 for default terminal + int32 terminal_id = 1; // 0 for default terminal uint32 rows = 2; uint32 cols = 3; } @@ -925,7 +926,7 @@ message TerminalOpened { bool success = 2; string message = 3; uint32 pid = 4; - string service_id = 5; // Service ID for persistent sessions + string service_id = 5; // Service ID for persistent sessions repeated int32 persistent_sessions = 6; // Used to restore the persistent sessions. bool replay_terminal_output = 7; // Whether the next data response replays buffered terminal output. } diff --git a/protos/rendezvous.proto b/protos/rendezvous.proto index 5c4dc3d1e..f0500e694 100644 --- a/protos/rendezvous.proto +++ b/protos/rendezvous.proto @@ -30,7 +30,8 @@ message PunchHoleRequest { bytes socket_addr_v6 = 10; } -message ControlPermissions { +// Data passed from server to controlled device (via PunchHole / FetchLocalAddr / RequestRelay) +message ControlledConfig { enum Permission { keyboard = 0; remote_printer = 1; @@ -46,7 +47,9 @@ message ControlPermissions { remote_modify = 11; privacy_mode = 12; } - uint64 permissions = 1; + uint64 control_permissions = 1; + bytes easy_access_signature = 2; // server signature for easy access challenge + bytes manager_id = 3; // user manager uuid } message PunchHole { @@ -57,7 +60,7 @@ message PunchHole { bool force_relay = 5; int32 upnp_port = 6; bytes socket_addr_v6 = 7; - ControlPermissions control_permissions = 8; + ControlledConfig conn_config = 8; } message TestNatRequest { @@ -109,6 +112,11 @@ message RegisterPkResponse { int32 keep_alive = 2; } +// Data passed from server to controller (via PunchHoleResponse / RelayResponse) +message ControllerConfig { + bytes easy_access_challenge = 1; // encrypted, opaque to both peers +} + message PunchHoleResponse { bytes socket_addr = 1; bytes pk = 2; @@ -129,6 +137,7 @@ message PunchHoleResponse { bool is_udp = 9; int32 upnp_port = 10; bytes socket_addr_v6 = 11; + ControllerConfig controller_config = 12; } message ConfigUpdate { @@ -145,7 +154,7 @@ message RequestRelay { string licence_key = 6; ConnType conn_type = 7; string token = 8; - ControlPermissions control_permissions = 9; + ControlledConfig conn_config = 9; } message RelayResponse { @@ -161,6 +170,7 @@ message RelayResponse { int32 feedback = 9; bytes socket_addr_v6 = 10; int32 upnp_port = 11; + ControllerConfig controller_config = 12; } message SoftwareUpdate { string url = 1; } @@ -173,7 +183,7 @@ message FetchLocalAddr { bytes socket_addr = 1; string relay_server = 2; bytes socket_addr_v6 = 3; - ControlPermissions control_permissions = 4; + ControlledConfig conn_config = 4; } message LocalAddr { diff --git a/src/config.rs b/src/config.rs index 4be1cb49a..a5a7fcf6b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -2767,6 +2767,11 @@ pub fn is_disable_installation() -> bool { is_some_hard_opton("disable-installation") } +#[inline] +pub fn is_allow_easy_access() -> bool { + is_some_hard_opton("allow-easy-access") +} + // This function must be kept the same as the one in flutter and sciter code. // flutter: flutter/lib/common.dart -> option2bool() // sciter: Does not have the function, but it should be kept the same. From 70ac8ba3fecaea6f8ebd20f98b28535d52d28db4 Mon Sep 17 00:00:00 2001 From: 21pages Date: Wed, 18 Mar 2026 20:06:56 +0800 Subject: [PATCH 2/6] request_id Signed-off-by: 21pages --- protos/rendezvous.proto | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/protos/rendezvous.proto b/protos/rendezvous.proto index f0500e694..b7e1445fc 100644 --- a/protos/rendezvous.proto +++ b/protos/rendezvous.proto @@ -28,6 +28,7 @@ message PunchHoleRequest { bool force_relay = 8; int32 upnp_port = 9; bytes socket_addr_v6 = 10; + bytes request_id = 11; } // Data passed from server to controlled device (via PunchHole / FetchLocalAddr / RequestRelay) @@ -61,6 +62,7 @@ message PunchHole { int32 upnp_port = 6; bytes socket_addr_v6 = 7; ControlledConfig conn_config = 8; + bytes request_id = 9; } message TestNatRequest { @@ -87,6 +89,7 @@ message PunchHoleSent { string version = 5; int32 upnp_port = 6; bytes socket_addr_v6 = 7; + bytes request_id = 8; } message RegisterPk { @@ -155,6 +158,7 @@ message RequestRelay { ConnType conn_type = 7; string token = 8; ControlledConfig conn_config = 9; + bytes request_id = 10; } message RelayResponse { @@ -171,6 +175,7 @@ message RelayResponse { bytes socket_addr_v6 = 10; int32 upnp_port = 11; ControllerConfig controller_config = 12; + bytes request_id = 13; } message SoftwareUpdate { string url = 1; } @@ -184,6 +189,7 @@ message FetchLocalAddr { string relay_server = 2; bytes socket_addr_v6 = 3; ControlledConfig conn_config = 4; + bytes request_id = 5; } message LocalAddr { @@ -193,6 +199,7 @@ message LocalAddr { string id = 4; string version = 5; bytes socket_addr_v6 = 6; + bytes request_id = 7; } message PeerDiscovery { From 2eaf15f2263e3efb0c167cd684ce9e5476725657 Mon Sep 17 00:00:00 2001 From: 21pages Date: Tue, 24 Mar 2026 15:56:59 +0800 Subject: [PATCH 3/6] proto: rename conn_config to controlled_config and remove PunchHoleRequest.request_id Signed-off-by: 21pages --- protos/rendezvous.proto | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/protos/rendezvous.proto b/protos/rendezvous.proto index b7e1445fc..5ef38098a 100644 --- a/protos/rendezvous.proto +++ b/protos/rendezvous.proto @@ -28,7 +28,6 @@ message PunchHoleRequest { bool force_relay = 8; int32 upnp_port = 9; bytes socket_addr_v6 = 10; - bytes request_id = 11; } // Data passed from server to controlled device (via PunchHole / FetchLocalAddr / RequestRelay) @@ -61,7 +60,7 @@ message PunchHole { bool force_relay = 5; int32 upnp_port = 6; bytes socket_addr_v6 = 7; - ControlledConfig conn_config = 8; + ControlledConfig controlled_config = 8; bytes request_id = 9; } @@ -157,7 +156,7 @@ message RequestRelay { string licence_key = 6; ConnType conn_type = 7; string token = 8; - ControlledConfig conn_config = 9; + ControlledConfig controlled_config = 9; bytes request_id = 10; } @@ -188,7 +187,7 @@ message FetchLocalAddr { bytes socket_addr = 1; string relay_server = 2; bytes socket_addr_v6 = 3; - ControlledConfig conn_config = 4; + ControlledConfig controlled_config = 4; bytes request_id = 5; } From 308fe0ecffd8257a92eb2de65cdc1185b81397af Mon Sep 17 00:00:00 2001 From: 21pages Date: Sun, 5 Apr 2026 17:41:10 +0800 Subject: [PATCH 4/6] add proto grant structure for device-bound approval Signed-off-by: 21pages --- protos/rendezvous.proto | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/protos/rendezvous.proto b/protos/rendezvous.proto index 5ef38098a..b65b48acc 100644 --- a/protos/rendezvous.proto +++ b/protos/rendezvous.proto @@ -15,6 +15,24 @@ enum ConnType { TERMINAL = 5; } +message EasyAccessTargetBinding { + bytes challenge = 1; // opaque controller challenge + bytes target_uuid = 2; // controlled device uuid + bytes target_pk = 3; // controlled device ed25519 public key +} + +message EasyAccessManagerApproval { + EasyAccessTargetBinding target_binding = 1; + bytes manager_signing_pk = 2; // manager ed25519 public key + bytes manager_approval_signature = 3; // signature over serialized EasyAccessTargetBinding +} + +message EasyAccessGrant { + uint32 version = 1; + bytes server_approval_signature = 2; // signature over serialized EasyAccessManagerApproval + bytes device_bound_proof = 3; // box(serialized manager approval, derived nonce, server_box_sk, target_box_pk) +} + message RegisterPeerResponse { bool request_pk = 2; } message PunchHoleRequest { @@ -48,8 +66,7 @@ message ControlledConfig { privacy_mode = 12; } uint64 control_permissions = 1; - bytes easy_access_signature = 2; // server signature for easy access challenge - bytes manager_id = 3; // user manager uuid + EasyAccessGrant easy_access_grant = 2; } message PunchHole { From a23cd182930aa8668391d32387c48d260c751fbe Mon Sep 17 00:00:00 2001 From: 21pages Date: Tue, 7 Apr 2026 21:41:50 +0800 Subject: [PATCH 5/6] add grant_id to EasyAccessTargetBinding Signed-off-by: 21pages --- protos/rendezvous.proto | 1 + 1 file changed, 1 insertion(+) diff --git a/protos/rendezvous.proto b/protos/rendezvous.proto index b65b48acc..0601e328a 100644 --- a/protos/rendezvous.proto +++ b/protos/rendezvous.proto @@ -19,6 +19,7 @@ message EasyAccessTargetBinding { bytes challenge = 1; // opaque controller challenge bytes target_uuid = 2; // controlled device uuid bytes target_pk = 3; // controlled device ed25519 public key + bytes grant_id = 4; // one-time server-issued grant id } message EasyAccessManagerApproval { From 8db11c314baa7b07c8ae529f4ce7b6f0180616a3 Mon Sep 17 00:00:00 2001 From: 21pages Date: Sat, 2 May 2026 17:19:10 +0800 Subject: [PATCH 6/6] easy access: move grant exchange from rendezvous to API server Signed-off-by: 21pages --- protos/message.proto | 31 ++++++++++++++++++++++++----- protos/rendezvous.proto | 44 +++++------------------------------------ 2 files changed, 31 insertions(+), 44 deletions(-) diff --git a/protos/message.proto b/protos/message.proto index 08808d6a1..f62c4eb60 100644 --- a/protos/message.proto +++ b/protos/message.proto @@ -69,6 +69,26 @@ message OSLogin { string password = 2; } +message EasyAccessTargetBinding { + bytes challenge = 1; // controlled device connection challenge + bytes target_uuid = 2; // controlled device uuid + bytes target_pk = 3; // controlled device ed25519 public key + bytes grant_id = 4; // one-time server-issued grant id +} + +message EasyAccessManagerApproval { + EasyAccessTargetBinding target_binding = 1; + bytes manager_pk = 2; // manager ed25519 public key + bytes manager_approval_signature = 3; // signature over serialized EasyAccessTargetBinding + bytes manager_id = 4; // stable manager uuid selected by the server +} + +message EasyAccessGrant { + uint32 version = 1; + bytes server_approval_signature = 2; // signature over serialized EasyAccessManagerApproval + bytes device_bound_proof = 3; // box(serialized manager approval, derived nonce, server_box_sk, target_box_pk) +} + message LoginRequest { string username = 1; bytes password = 2; @@ -88,11 +108,11 @@ message LoginRequest { string my_platform = 13; bytes hwid = 14; string avatar = 17; - bytes easy_access_challenge = 18; + bytes easy_access_grant_id = 18; } message Terminal { - string service_id = 1; // Service ID for reconnecting to existing session + string service_id = 1; // Service ID for reconnecting to existing session } message Auth2FA { @@ -330,6 +350,7 @@ message CursorPosition { message Hash { string salt = 1; string challenge = 2; + bytes easy_access_challenge = 3; } enum ClipboardFormat { @@ -440,7 +461,7 @@ message FileTransferDigest { bool is_upload = 5; bool is_identical = 6; uint64 transferred_size = 7; // For resume. Indicates the size of the file already transferred - bool is_resume = 8; // For resume. Indicates if the transfer is a resume. + bool is_resume = 8; // For resume. Indicates if the transfer is a resume. // `is_resume` can let the controlled side know whether to check the `.digest` file. // When `is_resume` is false, `.digest` exists, the same file does not exist, // the controlled side should not check `.digest`, it should confirm with a new transfer request. @@ -891,7 +912,7 @@ message ScreenshotResponse { // Terminal messages - standalone feature like FileAction message OpenTerminal { - int32 terminal_id = 1; // 0 for default terminal + int32 terminal_id = 1; // 0 for default terminal uint32 rows = 2; uint32 cols = 3; } @@ -926,7 +947,7 @@ message TerminalOpened { bool success = 2; string message = 3; uint32 pid = 4; - string service_id = 5; // Service ID for persistent sessions + string service_id = 5; // Service ID for persistent sessions repeated int32 persistent_sessions = 6; // Used to restore the persistent sessions. bool replay_terminal_output = 7; // Whether the next data response replays buffered terminal output. } diff --git a/protos/rendezvous.proto b/protos/rendezvous.proto index 0601e328a..5c4dc3d1e 100644 --- a/protos/rendezvous.proto +++ b/protos/rendezvous.proto @@ -15,25 +15,6 @@ enum ConnType { TERMINAL = 5; } -message EasyAccessTargetBinding { - bytes challenge = 1; // opaque controller challenge - bytes target_uuid = 2; // controlled device uuid - bytes target_pk = 3; // controlled device ed25519 public key - bytes grant_id = 4; // one-time server-issued grant id -} - -message EasyAccessManagerApproval { - EasyAccessTargetBinding target_binding = 1; - bytes manager_signing_pk = 2; // manager ed25519 public key - bytes manager_approval_signature = 3; // signature over serialized EasyAccessTargetBinding -} - -message EasyAccessGrant { - uint32 version = 1; - bytes server_approval_signature = 2; // signature over serialized EasyAccessManagerApproval - bytes device_bound_proof = 3; // box(serialized manager approval, derived nonce, server_box_sk, target_box_pk) -} - message RegisterPeerResponse { bool request_pk = 2; } message PunchHoleRequest { @@ -49,8 +30,7 @@ message PunchHoleRequest { bytes socket_addr_v6 = 10; } -// Data passed from server to controlled device (via PunchHole / FetchLocalAddr / RequestRelay) -message ControlledConfig { +message ControlPermissions { enum Permission { keyboard = 0; remote_printer = 1; @@ -66,8 +46,7 @@ message ControlledConfig { remote_modify = 11; privacy_mode = 12; } - uint64 control_permissions = 1; - EasyAccessGrant easy_access_grant = 2; + uint64 permissions = 1; } message PunchHole { @@ -78,8 +57,7 @@ message PunchHole { bool force_relay = 5; int32 upnp_port = 6; bytes socket_addr_v6 = 7; - ControlledConfig controlled_config = 8; - bytes request_id = 9; + ControlPermissions control_permissions = 8; } message TestNatRequest { @@ -106,7 +84,6 @@ message PunchHoleSent { string version = 5; int32 upnp_port = 6; bytes socket_addr_v6 = 7; - bytes request_id = 8; } message RegisterPk { @@ -132,11 +109,6 @@ message RegisterPkResponse { int32 keep_alive = 2; } -// Data passed from server to controller (via PunchHoleResponse / RelayResponse) -message ControllerConfig { - bytes easy_access_challenge = 1; // encrypted, opaque to both peers -} - message PunchHoleResponse { bytes socket_addr = 1; bytes pk = 2; @@ -157,7 +129,6 @@ message PunchHoleResponse { bool is_udp = 9; int32 upnp_port = 10; bytes socket_addr_v6 = 11; - ControllerConfig controller_config = 12; } message ConfigUpdate { @@ -174,8 +145,7 @@ message RequestRelay { string licence_key = 6; ConnType conn_type = 7; string token = 8; - ControlledConfig controlled_config = 9; - bytes request_id = 10; + ControlPermissions control_permissions = 9; } message RelayResponse { @@ -191,8 +161,6 @@ message RelayResponse { int32 feedback = 9; bytes socket_addr_v6 = 10; int32 upnp_port = 11; - ControllerConfig controller_config = 12; - bytes request_id = 13; } message SoftwareUpdate { string url = 1; } @@ -205,8 +173,7 @@ message FetchLocalAddr { bytes socket_addr = 1; string relay_server = 2; bytes socket_addr_v6 = 3; - ControlledConfig controlled_config = 4; - bytes request_id = 5; + ControlPermissions control_permissions = 4; } message LocalAddr { @@ -216,7 +183,6 @@ message LocalAddr { string id = 4; string version = 5; bytes socket_addr_v6 = 6; - bytes request_id = 7; } message PeerDiscovery {