- Rust 93.5%
- Nix 6.5%
|
|
||
|---|---|---|
| .cargo | ||
| docs | ||
| src | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
| rust-toolchain.toml | ||
winapp — Windows App for Linux
Connect to your Windows 365 / Azure Virtual Desktop / Dev Box VDIs from
Linux with a native session window. Protocol-compatible with the Microsoft
Store "Windows App" (MicrosoftCorporationII.Windows365 2.0.1485.0), which
was reverse-engineered to derive the service contract (see
docs/reversing-notes.md).
What it does
| Windows App | winapp |
|---|---|
| Entra sign-in (WAM/device) | winapp register (once) + winapp login |
| Workspace discovery | ARM feed discovery (msrdc UA) → MS-TSWP feed |
| List desktops/apps | winapp workspaces / winapp list |
| Launch a session | winapp connect <alias> — full native RDP session |
Conditional Access (error 53003)
If your tenant requires registered/compliant devices, plain device-code
sign-in fails with 53003 (Device state: Unregistered). On Windows the
Store app passes because its tokens are brokered by WAM with the device's
Entra registration + PRT. winapp reproduces that on Linux via
libhimmelblau (software keys, no TPM needed):
winapp register contoso.com # one-time: Entra device enrollment (DRS)
winapp login # user PRT bound to the enrolled device
winapp list # feed tokens via PRT exchange
Registration does not require your org to "support Himmelblau": it speaks
the same MS-DRS protocol Windows uses when you add a work account on a
personal PC, and "users may register devices" defaults to All in Entra. The
default join type is "Azure AD registered" (BYOD parity). If sign-in logs
show your policy filters on joined (not merely registered) devices, retry
winapp register --joined.
If your tenant additionally requires Intune compliance (not just
registration), run the full himmelblau daemon (distro package / NixOS module)
so the device reports compliant; winapp uses the same identity primitives.
winapp connect performs the same flow the Store app does: ARM connection
orchestration → reverse-connect WebSocket to the AVD gateway → TLS → RDP
(CredSSP/RDSTLS/AAD) → live framebuffer in a native window (winit +
softbuffer; Wayland/X11). The RDP engine is
IronRDP (MIT/Apache-2.0), pinned to
a specific revision; Entra token handling (including host proof-of-possession)
is delegated to its OAuthAvdTokenProvider with device-code login.
Usage
nix run .#default -- login # device-code: code + URL, sign in once
nix run .#default -- list # your desktops / RemoteApps
nix run .#default -- connect SessionDesktop # native session window
nix run .#default -- connect <alias> --headless # CI/smoke: frames → exit
nix run .#default -- connect <alias> --out x.rdp # also write .rdp handoff
Token cache: $XDG_STATE_HOME/windows-app/token-cache.json (0600).
Build
nix build # static-ish closure, rustls only, no OpenSSL
nix develop # fenix stable toolchain + rust-analyzer
Layout
src/cli.rs clap surface (register|login|workspaces|list|connect)
src/identity.rs Entra device enrollment + user PRT (libhimmelblau)
src/token.rs token cache + refresh
src/avd.rs feed discovery → workspaces → resources (MS-TSWP)
src/engine.rs IronRDP session: orchestration → WS gateway → RDP (own thread)
src/gui.rs native window (winit + softbuffer), frame blit, Poll loop
src/rdpfile.rs .rdp generation for external engines (FreeRDP etc.)
docs/ reversing notes (evidence-cited)
packages/ downloaded Store MSIX + deps (gitignored, not redistributed)
Status / limits (v2)
- Sign-in, feed, orchestration, native window: implemented.
- Input (keyboard/mouse/resize) events are wired in the engine API but not
yet forwarded from the window — the next milestone (
RdpInputEvent::FastPath). - Clipboard, drive/audio redirection: engine supports them; wiring is future scope. UDP shortpath falls back to WebSocket automatically.
- Verified against the protocol contract from the binary + IronRDP's own AVD integration tests; live-tenant end-to-end has not been run (no test account was provided). First connect against a real workspace is the remaining unknown.
Legal
Interoperates with Microsoft's public AVD endpoints for accounts you control.
packages/ contains Microsoft's app binaries fetched from Microsoft's CDN for
reverse-engineering; they are gitignored and not redistributed.