Commit graph

8 commits

Author SHA1 Message Date
Stephen Dennis
63aac9bc21 fix(proxy): WebSocket frag/UTF-8 and grpc-web parse fail-closed (#1886 #1887)
#1886: reject orphan CONTINUATION and new TEXT/BINARY while reassembly is
pending (1002); validate TEXT UTF-8 on complete and assembled messages
(1007); clear fragOpcode when reassembly finishes.  Mirrors engine #792.

#1887: gate every grpc-web RPC on ParseFromString success; return
INVALID_ARGUMENT (3) on truncated or malformed bodies instead of running
with default-valued requests.

proxy_regression covers fragmentation, UTF-8, and ParseFromString rejects.
2026-07-31 09:24:27 -06:00
Stephen Dennis
cb4c101125 fix: resolve Pass 4 Hydra Medium audit defects #1095–#1102
- #1095: WS RSV + control FIN/len≤125 before ext-len (no large PING→PONG)
- #1096: cap writeBuffers_ (256 KiB, close slow FD); subscriber queues drop oldest at 256
- #1097: gRPC/grpc-web login lockout by peer IP; /passwd requires old password
- #1098: RAND_bytes hard-fail; password/scrollback salts via CSPRNG
- #1099: ProcessManager::stopAndWait with SIGKILL escalate; restart + dtor wait/reap
- #1100: scrollback_lines applied on session create/restore; max_sessions_per_account enforced
- #1101: telnet IAC SB reassembly capped at 64 KiB
- #1102: /metrics loopback-only; ListGames/GetGameStatus require session

proxy_regression: ok (RSV, large PING, SB cap + prior WS cases)
hydra: builds with GRPC=1
2026-07-24 18:22:17 -06:00
Stephen Dennis
9674b6d834 fix: resolve Pass 4 Hydra High audit defects #1091–#1094
- #1091: saveSession uses ON CONFLICT upsert so REPLACE cannot CASCADE-wipe scrollback
- #1092: loadFromDb keeps memoryBytes_ in lockstep with append() (no size_t underflow)
- #1093: reset lenBytesRead before MaskKey after extended length (no maskKey OOB)
- #1094: deliver WS CLOSE (and protocol errors) so session paths close the FD;
  complete zero-length payloads after the mask key (empty CLOSE)

proxy_regression: ok (ext-len mask + CLOSE + unmasked teardown)
2026-07-24 17:39:49 -06:00
Stephen Dennis
1baa843572 Fix Hydra stream translation boundaries 2026-03-29 01:43:55 -06:00
Stephen Dennis
dde45b2ade Consolidate duplicate base64 into shared base64.h/cpp
Moved base64 encode/decode from websocket.cpp and grpc_web.cpp into a
single shared implementation.  Three overloads: raw bytes, std::string
encode, and std::string decode.  Removed declarations from grpc_web.h.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:35:17 -06:00
Stephen Dennis
b42aae8fb5 Harden Hydra proxy for internet-facing deployment
Security fixes from code review (ISSUES.md):
- TLS policy: allow_plaintext (default no), credential commands always
  require TLS, tls_required per game block (default yes)
- Admin authorization on /start /stop /restart and gRPC process RPCs
- CORS wildcard replaced with configurable cors_origin list
- Unbounded buffer DoS: cap lineBuf (8KB), httpBuf (1MB), WS fragBuf
- Constant-time password comparison via CRYPTO_memcmp
- PBKDF2 key derivation uniformly (replaces lossy crypt_r on POSIX)
- Session idle/detached timeout reaping in runTimers
- IP tracker map periodic pruning
- Content-Length stoul wrapped in try/catch
- ListenConfig bools initialized

Bug fixes:
- handleGrpcWebRequest used undeclared 'handle' (should be fd.handle)
- setFrontDoorTls called before front-door entry existed in map

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 20:41:51 -06:00
Stephen Dennis
09645a6c6a Add WsGameSession scaffolding: subprotocol, proto enum, FrontDoorState
Steps 2-4/7 of WebSocket GameSession transport:

- websocket.h/cpp: Parse Sec-WebSocket-Protocol during handshake,
  set WsState::isGameSession when hydra-gamesession is requested,
  echo the subprotocol in the 101 response
- hydra_types.h: Add WsGameSession to FrontDoorProto enum
- session_manager.h: Add subscriber fields to FrontDoorState
  (wsGameSessionSubId, wsGameSessionQueue, wsGameSessionOQ,
  wsGameSessionPersistId)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 00:26:13 -06:00
Stephen Dennis
567bef305d Add WebSocket front-door for browser clients (Phase 3 Step 2)
RFC 6455 WebSocket codec with HTTP upgrade handshake, frame
encode/decode, masking, ping/pong/close, and fragmentation reassembly.
WebSocket listeners are configured alongside telnet listeners and
routed by tag in the event loop.  Game output is wrapped in WS text
frames; client input is unwrapped and processed as lines.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:54:15 -06:00