Commit Graph
54 Commits
Author SHA1 Message Date
SirHumza 5a68bb63bf Green tests (portable tmpdir, snprintf), compat in test link, home/rest presence, mp art pipeline 2026-09-23 21:36:06 +02:00
SirHumza 1e49612e75 Daemon audit: SNTP rotation, reconnect backoff, heartbeat send check, urandom masks, fail-secure entropy, TLS verify, updater signed+redirects, health wiring, mp cache 2026-09-23 21:29:41 +02:00
SirHumza 44714eaeb1 WIP: injection guide (BinLoader, elfldr, one-shot rule, troubleshooting) 2026-09-23 21:09:23 +02:00
SirHumza d950661f78 WIP: default art pack URL (art works from first boot) 2026-09-23 20:57:24 +02:00
SirHumza 7dbb021290 WIP: mp: art resolution via external-assets + icon pack 2026-09-23 20:56:43 +02:00
SirHumza 49672ec2c8 WIP: SNTP wall-clock correction (PSN time blocked on jailbreak) 2026-09-23 20:34:08 +02:00
SirHumza fca5f17d74 WIP: socket timeouts always armed, per-minute alive tick 2026-09-23 20:22:11 +02:00
SirHumza 75835fff3b WIP: session resume window (flicker-proof timer) 2026-09-23 20:11:16 +02:00
SirHumza fb1c3aab37 WIP: lock checks peer process name (no recycled-PID deadlock) 2026-09-23 20:01:04 +02:00
SirHumza db38c05077 WIP: integer-ms timestamps (fixes 0:00), jl_new_int port 2026-09-23 19:10:59 +02:00
SirHumza 0d8c5cd254 WIP: presence display findings (art rules, Lanyard blind) 2026-09-23 19:05:35 +02:00
SirHumza de523d3c2e WIP: asset-key art only (URLs drop activities), own app id default, extended nametable 2026-09-23 19:04:13 +02:00
SirHumza 202d4012e3 WIP: single-instance lock (sysctl liveness), eboot+savedata detection for SDK builds 2026-09-23 18:06:39 +02:00
SirHumza c01fc3fb10 WIP: SDK-port net branches + findings archive 2026-09-23 16:56:25 +02:00
SirHumza 96c02b8cb4 WIP: debug gate, monotonic clock, titleId sessions, debounce, resolve cache 2026-09-22 17:58:07 +02:00
SirHumza c8fea26699 v04-plus: port TLS 1.2 ceiling + debug trace, since:null, titleId details, jl_new_null 2026-09-22 17:52:24 +02:00
SirHumza 3c7bf6180f Self-updater: versioned staged updates from GitHub releases 2026-09-19 11:28:35 +02:00
SirHumza 260b9dc8c0 Default art backend to public RPC app assets 2026-09-19 11:24:28 +02:00
SirHumza 63409c8e41 discord: single asset_key helper, drop duplicated lowering 2026-09-19 11:20:55 +02:00
SirHumza feec6f6695 daemon: document Rest Mode gap as unverified 2026-09-19 11:20:25 +02:00
SirHumza 825e10f3bb tmdb transport mirrors proven socket bring-up 2026-09-19 11:19:12 +02:00
SirHumza a16145df63 Docs: TMDB-first art and names 2026-09-19 11:17:18 +02:00
SirHumza cf76f1ebf8 Sony TMDB runtime names+icons; remove fuzzy appdb scan
- tmdb_crypto: self-contained SHA1/HMAC, URL builder, response parse,
  all verified against hashlib and Sony's live service in unit tests
- tmdb: plain-HTTP fetch with deadline plus 8-entry cache
- detect: TMDB in both resolve paths; artwork URL plumbed through
  detect_last_art into presence assets (official Sony CDN, no uploads)
- remove appdb byte-scan: boundary ambiguity returned wrong names,
  worse than raw IDs; also removes the multi-MB game-process read
- discord/daemon: full-URL artwork wins, pack URL next, asset key last
2026-09-19 11:16:09 +02:00
SirHumza e79ff0510d tls: local xorshift fallback instead of process-global rand 2026-09-19 10:28:59 +02:00
SirHumza 0dedb15ef8 jsonlite: depth cap + bounded number scan + hostile tests 2026-09-19 10:27:04 +02:00
SirHumza b671649d74 README status refresh to match verified reality 2026-09-19 10:25:38 +02:00
SirHumza 02d68410ac External-URL artwork pipeline + icon sync
- discord: large_image as <art_base_url><lower titleId>.png when
  configured (Discord accepts external URLs in asset fields);
  uploaded-asset keys remain as fallback via application_id
- cfg: art_base_url field with load/save support
- scripts/sync_icons.sh: FTP pulls all icon0.png (read-only)
- deploy/ARTWORK.md rewritten around URL-pack-first design
2026-09-19 10:24:20 +02:00
SirHumza 28f6275a05 Gateway precision, SFO OOB fix, build lists, artwork runbook
- discord: HELLO requires text frame; READY/HELLO timeout diagnostics;
  invalid-session fast retry path (-3); clamp warning; malformed close
- daemon: invalid session resets backoff instead of doubling it
- sfo: bounded key scan (no OOB on malformed files) + regression test
- build.sh + plugin Makefile compile sfo.c (link verified)
- deploy/ARTWORK.md: shared-app asset pipeline, no-URL rule
2026-09-19 10:18:39 +02:00
SirHumza cdb431cfa6 Names tiers, SFO parser, close-frame/diagnostics hardening
- detect: cost-tiered resolution; plugin path skips multi-MB app.db
  scan (game-process safety); payload tries pronunc, sfo, appxml,
  baked table, then app.db; sfo TITLE via app0/sce_sys paths
- sfo.c: bounds-checked PARAM.SFO parser + unit tests incl malformed
- nametable: generated fallback from title DB + generator script
- discord: malformed close frames reconnect loudly; one-time warning
  when artwork requested but no application_id configured
- ws comments de-BearSSLed; gitignore covers artifacts; drop .DS_Store,
  untrack test binary; README art claim corrected
2026-09-19 01:37:55 +02:00
SirHumza a7dd06ab5f README: backend status, names and art still open 2026-09-19 01:03:18 +02:00
SirHumza bf5579d6da Stable gateway backend: mbedTLS, 8MB READY, JSON-safe parsing
- BearSSL replaced with mbedTLS (TLSv1.3 passes Cloudflare)
- 8MB frame cap + truncation-proof gateway op/seq scanner
- Thread-safe compat, locked logging, atomic config with template
- Daemon keeps last-good config, persistent presence timer
- 256B token buffers, weak-libc shims, portable build preflights
- Tests: gateway spoof + OOM cases pass

Still open: display names fall back to titleId in sandbox,
cover art needs shared Discord app assets. Backend fully functional.
2026-09-19 01:03:17 +02:00
SirHumza 1ca687f8fb save work before cleanup 2026-09-18 18:00:13 +02:00
SirHumza 6dbfa1512c Harden networking, lifecycle, and build validation
Add BearSSL integration, strict utility handling, WebSocket validation,
plugin lifecycle cleanup, host regression tests, and reproducible GoldHEN
build support.
2026-08-27 20:38:39 +02:00
SirHumza 949240f590 daemon: auth via user session token; fix ws/gateway protocol bugs
The public Discord gateway rejects OAuth2 access tokens (close 4004),
so v1 could never set presence: switch config to a raw user token and
delete the oauth/http module.

- handle close frames; exit fatal on 4004 instead of looping forever
- fix reversed IPv4 packing in sceNetConnect (wrong host)
- fix SSL_read treating WANT_READ/no-data as disconnect
- keep frame bytes glued to the 101 handshake response (HELLO)
- grow recv buffer for large READY payloads; drain-and-skip >2MB
- mask all client frames incl. control; overflow-safe length checks
- drop RESUME (was dead: connect wiped session_id); fresh IDENTIFY
- clear presence stays online, add elapsed timestamps
- tick gateway every second so heartbeats never land late
- connect backoff 5s..300s; live config reload each cycle
2026-08-23 11:07:38 +02:00
SirHumza 91382fc53c daemon: reload config before each token attempt
The daemon loaded config once at startup and held it in memory, so an
operator editing auth_code/refresh_token on the console (FTP) while it
ran was ignored. Re-read the disk config each ensure_token() so edits
take effect live without a plugin reload.
2026-08-15 00:32:34 +02:00
SirHumza d5d1957668 plugin: run orbisRPC as a GoldHEN plugin (native auto-start)
/data/GoldHEN/payloads/ is not an auto-load folder (PPPwn only loads
goldhen.bin; folder auto-load is unimplemented GoldHEN feature #296), so the
ELF payload never ran regardless of reboots. Replace that route with the
GoldHEN plugin loader, which auto-starts into the game process at every boot
via plugins.ini [default] with no PC involvement.

- daemon.c/h: extract the payload main() loop into a shared daemon_run()
  usable from both the ELF entry (main.c thin wrapper) and the plugin
- detect.c/h: add detect_name_for_title() for the known-titleid plugin mode
- plugin/plugin.c: plugin_load() reads procInfo.titleid via sys_sdk_proc_info,
  skips non-game (NPXS/system) titles, starts daemon thread; plugin_unload()
  stops it cleanly
- plugin/Makefile: builds orbisrpc_plugin.prx against the GoldHEN SDK
  (libGoldHEN_Hook.a + crtprx.o)
- deploy/SETUP.md: rewrite for the plugin route; add plugins.ini [default]
  (plugin/plugins.ini.ps4)
- scripts/build.sh: include daemon.c
2026-08-15 00:23:33 +02:00
SirHumza c1565c3144 docs: identify-only scope; rpc.* scopes restricted to whitelisted apps 2026-08-14 23:19:52 +02:00
SirHumza d7b6de7acb deploy: use raw ELF as GoldHEN payload, not fself/eboot
GoldHEN's /data/GoldHEN/payloads/ auto-loader takes a raw ELF named .bin.
SETUP.md/README told users to deploy the .fself (or the confusingly named
eboot .bin), which would not load. Deploy orbisrpc.elf as orbisrpc.bin;
rename the fself eboot output to orbisrpc-eboot.bin to avoid the trap.
2026-08-14 23:13:06 +02:00
SirHumza 58a8017a87 stealth: add capabilities + presence to identify, drop Origin header
Real desktop clients send the gateway capabilities bitfield and an
initial presence inside IDENTIFY, and native clients do not send an
Origin header on the WebSocket upgrade. Match all three for a closer
desktop-client profile.
2026-08-14 20:33:12 +02:00
SirHumza a726d3dcb6 stealth: plausible desktop-client fingerprint instead of PS4/orbisRPC
- identify properties now present a Windows Discord desktop fingerprint
  (os windows, browser 'Discord Client', Electron UA) rather than
  advertising os:'PS4', browser:'orbisRPC'
- HTTP user-agent (API calls + WS upgrade) now a desktop-client UA
  instead of 'orbisRPC/1.0'
2026-08-14 20:28:47 +02:00
SirHumza d40fc600c4 revise: fix TLS handshake, heartbeat ack, RESUME, seq parse, party
ws: SSL_connect on the non-blocking socket now polls WANT_READ/WANT_WRITE
  with a deadline (previously it would fail the very first handshake);
  handshake response read in chunks so the 5s deadline can't spuriously
  trip; ws_send_text errors on oversized frames instead of silently
  truncating; added ws_send_pong for RFC6455 server pings.
discord: heartbeat ack tracking -> reconnect on 2x-interval silence;
  handle op 7 (reconnect) and op 9 (invalid session, clears session_id);
  parse the sequence from the correct "s" field (was "seq", never
  matched, heartbeat always sent d:0); READY captures session_id for
  RESUME; reconnect now RESUMEs (op 6) when a session exists and falls
  back to IDENTIFY on invalid-session; party size now emitted in the
  activity; dropped the unused 'intent' arg; zeroed gateway-fetch buffer.
main: use config presence_state (was hardcoded); reset last_name after
  reconnect so the current game is re-pushed immediately.
cfg: clamp poll_interval_s to [5,300]; atomic config save (tmp+rename).
log: seconds in timestamps; rotate log at 512 KB.
jsonlite: jl_obj_get/jl_arr_at return non-const (fixes const-drop
  warnings); stringify emits proper "null" for missing pair values.
detect: trim whitespace around app.xml title; drop per-poll log spam.
2026-08-14 20:24:24 +02:00
SirHumza 90c86d9f1a fix: leaks, OOB read, handshake timeout, identify shape, b64 terminator
- jsonlite: jl_free leaked every object inside an array (sibling pairs,
  keys, values). Verified 39/39 allocs freed (was 15 leaked/presence).
- discord: IDENTIFY now sends required connection properties
  os/browser/device; dropped bot-only intents field for user connection.
- ws: recv_frame returns bytes actually copied (was full payload length ->
  jl_parse OOB read on >1023B frames); handshake SSL_read handles
  WANT_READ with 5s deadline (was infinite busy-wait); per-frame random
  client mask (RFC 6455 5.3) instead of static 0x12345678.
- main: daemon retries token/gateway failures instead of exiting
  (GoldHEN payload runs once per boot).
- b64: NUL-terminate output (callers relied on pre-zeroed buffers).
2026-08-14 19:58:57 +02:00
SirHumza ac47151c7a fix(build): correct lld default path; docs: exact artifact sizes (KiB)
build.sh defaulted LLD to /usr/local/opt/lld@21/bin/ld.lld which
does not exist (lld 21 is built from source at /Users/mac/lldbuild/
build/bin/ld.lld). Bare ./scripts/build.sh now works with no env vars.
README size claims corrected to 182/188 KiB.
2026-08-14 11:09:38 +02:00
SirHumza 1a092b7951 docs: fix stale artifact refs (eboot.bin->orbisrpc.bin, sizes); drop broken scaffold Makefile
The scaffold Makefile globbed PS4RP/*.c (dir renamed to orbisrpc/),
referenced ps4rp.elf, and needed pkg assets that don't exist — 'make'
would fail. scripts/build.sh is the canonical, verified build path.
2026-08-14 10:50:10 +02:00
SirHumza af1a48dbf3 chore: rename project PS4RP -> orbisRPC
- Repo renamed to SirHumza/orbisRPC on GitHub
- Source dir PS4RP/ -> orbisrpc/
- Binaries ps4rp.{elf,fself,bin} -> orbisrpc.{elf,fself,bin}
- On-console config dir /data/PS4RP -> /data/orbisRPC
- Build outputs, HTTP UA, net pool/socket names, README, SETUP
  guide all updated to orbisRPC
2026-08-14 10:31:14 +02:00
SirHumza 7622c4915b fix(jsonlite/discord): two memory-safety bugs found via host ASan
1. jsonlite.c: jl_stringify started with out=NULL but emit's growth
   check (1 > cap) never triggered realloc, so the first '{' wrote to
   NULL -> guaranteed crash on first IDENTIFY/presence build. Pre-allocate.
   Also grow the buffer in the no-child fallback path.

2. discord.c: jl_obj_set(dd,"status","online") and "invisible"
   passed a const char* where jl_val_t* is expected. Compiles (both are
   pointers) but pair->child points at rodata -> jl_free reads garbage
   struct fields, double-free/global-buffer-overflow caught by ASan.

Verified with host-side ASan tests: presence payload roundtrips clean,
1000 READY parse/free cycles leak-free, b64 known-answer vectors pass.
2026-08-14 10:30:25 +02:00
SirHumza c41c7ab186 fix(ws): non-blocking recv with buffered frame parser
The old ws_recv_frame did a blocking SSL_read inside discord_tick, so
when the gateway sent nothing the whole poll loop stalled: detection
froze and heartbeats stopped, and Discord drops the connection after
~90s of silence. Now:
- socket set non-blocking (SO_NBIO=0x2000, SOL_SOCKET=0xffff)
- raw SSL_read bytes buffered in ws_t.rbuf
- try_parse_frame returns a complete unmasked server frame when
  available, 0 when partial, -1 on error
- discord_tick treats 0 as 'no data yet' (not a disconnect)

Handshake response read still blocks briefly (server replies
immediately) with a busy-wait for the non-blocking fd.
2026-08-14 08:53:07 +02:00
SirHumza 6be235b60f fix(discord): use unauthenticated /api/gateway endpoint, drop dead code
/api/gateway/bot requires a bot Authorization header; we authenticate
as a user OAuth2 token, so it always 401s. /api/gateway is public.
Remove a no-op ternary that selected the same resource either way.
2026-08-14 08:49:40 +02:00
SirHumza 7c6ea67e40 fix(ws): send TLS SNI via SSL_ctrl (SSL_set_tlsext_host_name)
libSceLibreSSL exports SSL_ctrl but not SSL_set_tls_host directly.
SNI is required for Discord's TLS termination to route the gateway
and token endpoints correctly; without it the handshake can be
rejected. Implemented via SSL_ctrl(s, SSL_CTRL_SET_TLSEXT_HOSTNAME=55,
TLSEXT_NAMETYPE_host_name=0, host) — stable across OpenSSL/LibreSSL.
2026-08-14 08:48:38 +02:00
SirHumza c5568ef702 fix(detect): use sceShellCoreUtilIsAppLaunched for reliable foreground detection
- Resolve ShellCoreUtil at runtime via dlopen/dlsym (no hard import;
  GoldHEN payload loader can't always statically bind it)
- IsAppLaunched returns 0 on the home screen -> presence now clears
  correctly when the user exits a game
- Fallback to sceUserServiceGetForegroundUser if ShellCoreUtil
  unavailable in the payload context
2026-08-14 08:48:02 +02:00