feat: RDP profiles, sessions and viewer

- Protocol::Rdp with RdpConfig (domain, password mode, certificate
  policy, TLS-only fallback, fixed or tab-sized resolution, SOCKS5/HTTP
  proxy, SSH tunnel); migration 008 adds rdp_config and drops the
  protocol CHECK constraint so new protocols no longer need a rebuild.
- Session manager: connect_rdp dials directly, via the shared proxy
  module (proxy password from the secret store) or an SSH tunnel; the
  server certificate goes through the known-hosts check (key type
  rdp-tls); a tab-sized desktop uses the tab's reported pixel size, and
  resizes wait until the server opens Display Control. Rejected NLA
  passwords count as auth failures, so a saved one is asked again.
- The VNC viewer becomes DesktopView for both protocols; a small adapter
  turns its keysyms and pointer masks into RDP scancodes, Unicode keys,
  buttons and wheel events. For RDP, Paste Clipboard types the text.
- Profile editor RDP section, Quick Connect, badges, docs.

Verified against xrdp in the app: logon, desktop, input, and connections
through SOCKS5 and HTTP CONNECT relays. Not verified here: Windows/NLA
servers, the SSH tunnel route, and Display Control resizing (xrdp
0.9.24 never opened the channel).
This commit is contained in:
Andy Dixon
2026-10-12 11:14:39 +01:00
parent 50c0104d57
commit d25746bb14
18 changed files with 662 additions and 75 deletions
+10 -1
View File
@@ -31,12 +31,15 @@ pub enum SecretKind {
IrcSshPassword,
IrcSshPassphrase,
ProxyPassword,
RdpPassword,
RdpSshPassword,
RdpSshPassphrase,
}
impl SecretKind {
/// Every kind, so deleting a profile can purge them all from the keychain. A new variant
/// must be added here as well as to `as_str`.
pub const ALL: [SecretKind; 12] = [
pub const ALL: [SecretKind; 15] = [
Self::Password,
Self::Passphrase,
Self::Totp,
@@ -49,6 +52,9 @@ impl SecretKind {
Self::IrcSshPassword,
Self::IrcSshPassphrase,
Self::ProxyPassword,
Self::RdpPassword,
Self::RdpSshPassword,
Self::RdpSshPassphrase,
];
/// The storage name, shared with the Go app.
@@ -66,6 +72,9 @@ impl SecretKind {
Self::IrcSshPassword => "irc-ssh-password",
Self::IrcSshPassphrase => "irc-ssh-passphrase",
Self::ProxyPassword => "proxy-password",
Self::RdpPassword => "rdp-password",
Self::RdpSshPassword => "rdp-ssh-password",
Self::RdpSshPassphrase => "rdp-ssh-passphrase",
}
}