Client session resume (via LoC/SASL and draft/resume-0.5) - #95
Open
empus wants to merge 4 commits into
Open
Conversation
Add same-server, in-memory IRCv3 session resume for secure connections: an eligible client that loses its transport is held for a grace window instead of quitting, and may reattach keeping its nick, account, modes, and channels. - draft/resume-0.5 capability with bearer token (128-bit id + 256-bit secret, URL-safe base64), rotated on every resume; constant-time secret compare. - BRB for voluntary suspend; auto-detach on unexpected transport loss (EOF, reset, TLS error, abnormal WebSocket close); optional detach on ping timeout (RESUME_DETACH_PINGOUT) for silent losses a proxy never propagated. - Account-based auto-reattach (RESUME_AUTO_ACCOUNT): an authenticated client (SASL, login-on-connect, or a services login after connecting) that returns with the same nick+account reattaches with no token and no client support; the nick collision is deferred through registration. Per-account opt-out via the 0x080 account flag. - Preserves user modes/oper privileges/snomask/class limits across the connection swap; restores pre-detach away. - Eligibility requires TLS; RESUME_REQUIRE_WEBSOCKET (default TRUE) further restricts to secure WebSockets. Detached sessions capped by RESUME_MAX_DETACHED; window by RESUME_TIMEOUT (10-300s). - WHOIS shows a detached session to opers/self; detach/resume/expiry notices via RESUME_SERVER_NOTICES; tokens never logged or shown. - Off by default (RESUME). Docs in doc/readme.resume and doc/readme.features; tests under tests/pr_resume/.
…efer iauth nick - Re-send RPL_LOGGEDIN (900) during replay for an authenticated session that resumed via token. A token-path resumer never SASLs on the new connection, so it never received 900 and could not tell it was still logged in -- it would retry SASL on the next CAP NEW, which fails when services are down (the very case where a server-local token still lets it back in). Gated on the resumer not having authenticated on this connection, so account-path resumers are not sent a duplicate. - Flush the replay burst with send_queued() before restoring the SendQ ceiling, so a large rebuild cannot leave the queue backed up above the class limit and trip "Max SendQ exceeded" on the client's next message. Document that the ceiling is enforced at queue time, not at dispatch. - Withhold the deferred resume nick from iauth until it is actually committed, and forward it only once the client keeps it, so iauth/dronescan never evaluate a nick the client may not end up holding.
Carry state that must survive detach->resume across the connection swap and clean up the transient's registration state, so a resumed session no longer leaks or corrupts server-side bookkeeping: - Drop the transient's in-flight SASL cookie and timer before the swap frees it, so the SASL session table / timer can't dangle at a freed client (H0). - Carry the accumulated nick-change penalty (con_nextnick), closing a BRB-reconnect nick-flood bypass (M10). - Move the session's conf attachments (incl. any Operator block) onto the live connection so oper-class link accounting stays balanced (L20). - Carry the sockhost and byte counters so the local-count bucket balances and session traffic isn't lost to is_ni (L21). - Tell iauth the detached fd is gone, so it doesn't leak a record on a reusable fd (L19).
…etes A nick deferred for account-based reattach was withheld from iauth. iauth (login-on-connect) needs the client's nick to finish its registration handshake and send its verdict. The account is derived from the username, but it isn't applied to the client until iauth replies -- and iauth won't reply without the nick. So the account was never set, the reattach (which needs it) never fired, and the reconnecting client hung. Forward the nick to iauth even while deferred; it still stays out of the client nick-hash.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds same-server, in-memory IRCv3 session resume for secure connections. An eligible client that loses its transport is held in a limbo state for a grace window instead of quitting, and can reattach to the same session — keeping its nick, account, user modes, oper privileges, and channels — with no visible quit/rejoin to the rest of the network. Primarily designed to survive edge reployments or other short-lived interruptions of WebSocket connections.
Off by default (
RESUMEfeature flag); no behavior change unless explicitly enabled.What it does
draft/resume-0.5capability with a bearer token (128-bit id + 256-bit secret, URL-safe base64), rotated on every resume, constant-time secret comparison. Tokens are never logged or shown.BRBcommand for voluntary suspend; automatic detach on unexpected transport loss (EOF, reset, TLS error, abnormal WebSocket close); optional detach on ping timeout (RESUME_DETACH_PINGOUT) for silent losses a proxy never propagates.RESUME_AUTO_ACCOUNT): an authenticated client (SASL, login-on-connect, or a services login after connecting) returning with the same nick+account reattaches with no token and no client support — the nick collision is deferred through registration. Per-account opt-out via the0x080account flag.RPL_LOGGEDINis re-sent for authenticated sessions so a token-path resumer re-learns its account.Eligibility & limits
RESUME_REQUIRE_WEBSOCKET(default on) further restricts to secure WebSockets.RESUME_MAX_DETACHED; grace window byRESUME_TIMEOUT(10–300s).WHOISshows a detached session to opers/self; detach/resume/expiry operator notices viaRESUME_SERVER_NOTICES.Testing
tests/pr_resume/covering detach, resume, account auto-reattach, auto-detach, and the secure-WebSocket requirement.Docs
doc/readme.resume(feature guide),doc/readme.features, anddoc/example.conf.