Two RFB protocol bugs in the /screen client:
1. ServerInit parsed framebuffer-height from byte offset 1 instead of
2. RFB 3.8 ServerInit is width@0-1, height@2-3; u16be(b,1) mixes
the low byte of width with the high byte of height. The wrong
height went into the initial non-incremental FramebufferUpdate-
Request; neatvnc feeds the client's width/height straight into
pixman_region_union_rect un-clipped (src/server.c), so an
out-of-range height corrupts the server damage region and pixman
reports 'Invalid rectangle passed'.
2. FramebufferUpdate handler had a stray drainTo(1) after the 3-byte
padding+nRects header, consuming the first byte of the first
rectangle and desyncing every update.
Closes#128
Two bugs found via the weston journal (issue #92):
1. MD5 rotation index used (j>>2 & 3) for the round number, which
cycles every 4 steps instead of every 16. Verified against RFC 1321
test vectors: md5("") was 7a1dce5b... instead of d41d8cd9... — the
derived AES key was wrong, so the server decrypted the credentials
to garbage. Fixed to j>>4.
2. weston's vnc_handle_auth calls getpwnam(username) and requires
pw_uid == weston's own uid before PAM is consulted. We sent an empty
username, which fails outright ("VNC: wrong user"). weston runs as
root, so send username "root"; the empty password still passes via
pam_permit.so on the weston-remote-access service.
Fixes#92
rfb_apple_dh_client_msg has encrypted_credentials at offset 0 and
public_key as a flexible array at offset 128. We were sending them
in the wrong order (pub_key first), so neatvnc decrypted the wrong
bytes as credentials and sent the wrong bytes as the DH public key,
causing a mismatched shared secret and SecurityResult=1.
Fixes#92
weston's VNC backend (neatvnc) uses VeNCrypt (security type 19) as
the outer type even with --disable-transport-layer-security, offering
sub-type 1 (None, no TLS, no password) within it.
The old screen.html only handled type 1 (plain None) and type 2 (VNC
auth), causing 'auth failed' against weston.
Add VeNCrypt states to the RFB state machine:
- vencrypt-version: echo back server's major.minor
- vencrypt-subtypes: pick sub-type 1 (None) if available
- vencrypt-accept: check server's acceptance byte
Then falls through to the normal security-result / server-init path.
Reads /etc/hyperhive/gui.json at startup to get the VNC port written
by the weston-vnc ExecStart script (issue #50). Adds:
- gui_vnc_port: Option<u16> on AppState
- gui_enabled: bool on StateSnapshot (for issue #52 screen link)
- GET /screen: serves a minimal RFB-over-WebSocket viewer (screen.html)
- GET /screen/ws: upgrades to WebSocket and byte-pumps to 127.0.0.1:<vnc_port>
The relay is a pure two-task byte pump (WS→TCP and TCP→WS), transparent
to any RFB variant including VeNCrypt. Returns 404 when gui is not
enabled.
screen.html is a self-contained RFB client: handshake, FramebufferUpdate
(Raw encoding), pointer and keyboard forwarding — enough to display the
desktop and interact with it. noVNC assets (issue #52) replace this.
Closes#51