fix: guard mod_saslauth against session destroyed during async HTTP auth

mod_auth_http_async blocks the c2s async runner on an HTTP call inside
SASL plain_test. If the client disconnects during that call,
sessionmanager.retire_session nils every session field (incl.
base_type) and marks it destroyed. When the runner resumed,
mod_saslauth crashed at sasl_process_cdata line 94 on
'sasl/'..session.base_type..'/'. Bail out when the session is gone
instead of firing the event and sending a reply to a dead connection.

Part-of: <http://gitlab.vnc.biz/uxf/vnctalk-prosody/-/merge_requests/9>
This commit is contained in:
2026-07-16 08:38:14 +02:00
parent dde2e6a0e5
commit b49e9bcaa1
2 changed files with 13 additions and 0 deletions
+1
View File
@@ -22,6 +22,7 @@ To change a patch: extract the pristine tarball, apply all patches, edit, and re
| `hidden.lib.patch` | `plugins/muc/hidden.lib.lua` | Hide the "publicly searchable" room config option for everyone when public rooms are restricted (upstream exempts admins). | | `hidden.lib.patch` | `plugins/muc/hidden.lib.lua` | Hide the "publicly searchable" room config option for everyone when public rooms are restricted (upstream exempts admins). |
| `mod_muc_unique.patch` | `plugins/mod_muc_unique.lua` | Rework muc#unique handler; answer `item-not-found` for bare-JID requests. | | `mod_muc_unique.patch` | `plugins/mod_muc_unique.lua` | Rework muc#unique handler; answer `item-not-found` for bare-JID requests. |
| `mod_websocket.patch` | `plugins/mod_websocket.lua` | Re-add WebSocket continuation-frame (fragmented-message) support that was removed upstream in the 0.12/13.0 rewrite. VNCtalk clients fragment large WebSocket messages (e.g. vCard sets with avatars >~64 KB); 13.0.6's `validate_frame` hard-rejected any frame with `FIN=false` (close code 1003) **silently** — no log was emitted because the rejection fired on the partial-frame path before `handle_frame` was reached, and `websocket_close()` itself does not log. This patch removes the blanket `not frame.FIN` rejection from `validate_frame` and restores the `dataBuffer` fragment-accumulation logic from 0.11.6 inside `handle_frame`: text frames (opcode 0x1) with `FIN=false` start a buffer, continuation frames (opcode 0x0) append to it, and the concatenated data is returned only when a frame with `FIN=true` arrives. The accumulated size is capped by the configurable `websocket_max_message_size` option (default **2 MB**, 2×1024×1024); if exceeded the connection is closed with WebSocket close code 1009 ("Message too big") and the buffer is reset, preventing unbounded memory growth from buggy or malicious clients that never send a FIN frame. | | `mod_websocket.patch` | `plugins/mod_websocket.lua` | Re-add WebSocket continuation-frame (fragmented-message) support that was removed upstream in the 0.12/13.0 rewrite. VNCtalk clients fragment large WebSocket messages (e.g. vCard sets with avatars >~64 KB); 13.0.6's `validate_frame` hard-rejected any frame with `FIN=false` (close code 1003) **silently** — no log was emitted because the rejection fired on the partial-frame path before `handle_frame` was reached, and `websocket_close()` itself does not log. This patch removes the blanket `not frame.FIN` rejection from `validate_frame` and restores the `dataBuffer` fragment-accumulation logic from 0.11.6 inside `handle_frame`: text frames (opcode 0x1) with `FIN=false` start a buffer, continuation frames (opcode 0x0) append to it, and the concatenated data is returned only when a frame with `FIN=true` arrives. The accumulated size is capped by the configurable `websocket_max_message_size` option (default **2 MB**, 2×1024×1024); if exceeded the connection is closed with WebSocket close code 1009 ("Message too big") and the buffer is reset, preventing unbounded memory growth from buggy or malicious clients that never send a FIN frame. |
| `mod_saslauth.patch` | `plugins/mod_saslauth.lua` | Guard `sasl_process_cdata` against a session that was destroyed while the SASL handler was suspended. `mod_auth_http_async` performs a blocking async HTTP call inside the SASL `plain_test` callback, which parks the c2s async runner. If the client disconnects during that call, `sessionmanager.destroy_session``retire_session` nils every field on the session (including `base_type`) and marks it `destroyed`. When the HTTP call returns and the runner resumes, `mod_saslauth` then crashed at `module:fire_event("sasl/"..session.base_type.."/"..status, ...)` with `attempt to concatenate a nil value (field 'base_type')`. The patch bails out of `sasl_process_cdata` when `session.destroyed` or `session.base_type` is nil, so no event is fired and no reply is sent to an already-dead connection. Non-fatal for auth itself (the next login attempt on a fresh session succeeds), but it spammed the logs with a traceback on every disconnect-during-SASL. |
## Patches removed at the 0.12.6 upgrade (M1) ## Patches removed at the 0.12.6 upgrade (M1)
+12
View File
@@ -0,0 +1,12 @@
--- a/plugins/mod_saslauth.lua 2026-07-16 08:32:41.890007020 +0200
+++ b/plugins/mod_saslauth.lua 2026-07-16 08:33:10.667871912 +0200
@@ -89,6 +89,9 @@
end
local sasl_handler = session.sasl_handler;
local status, ret, err_msg = sasl_handler:process(text);
+ if session.destroyed or not session.base_type then
+ return true;
+ end
status, ret, err_msg = handle_status(session, status, ret, err_msg);
local event = { session = session, message = ret, error_text = err_msg };
module:fire_event("sasl/"..session.base_type.."/"..status, event);