# HG changeset patch # User Kim Alvefur # Date 1775586941 -7200 # Node ID 8a4417d32b0fa5381da0fbbe2385a973d14a4341 # Parent 0e9e3efa381febc98baa0e7b80d350f1e488e901 mod_c2s,mod_s2s: Introduce separate pre-authentication stanza size limit This should prevent unauthenticated resource use via the XML parser. diff -r 0e9e3efa381f -r 8a4417d32b0f plugins/mod_c2s.lua --- a/plugins/mod_c2s.lua Thu Apr 02 20:53:04 2026 +0100 +++ b/plugins/mod_c2s.lua Tue Apr 07 20:35:41 2026 +0200 @@ -28,7 +28,8 @@ local c2s_timeout = module:get_option_period("c2s_timeout", "5 minutes"); local stream_close_timeout = module:get_option_period("c2s_close_timeout", 5); local opt_keepalives = module:get_option_boolean("c2s_tcp_keepalives", module:get_option_boolean("tcp_keepalives", true)); -local stanza_size_limit = module:get_option_integer("c2s_stanza_size_limit", 1024*256,10000); +local unauthed_stanza_size_limit = module:get_option_integer("c2s_unauthed_stanza_size_limit", 10000,1000); +local authed_stanza_size_limit = module:get_option_integer("c2s_stanza_size_limit", 1024*256,10000); local advertised_idle_timeout = 14*60; -- default in all net.server implementations local network_settings = module:get_option("network_settings"); @@ -137,11 +138,11 @@ local features = st.stanza("stream:features"); hosts[session.host].events.fire_event("stream-features", { origin = session, features = features, stream = attr }); if features.tags[1] or session.full_jid then - if stanza_size_limit or advertised_idle_timeout then + if session.stanza_size_limit or advertised_idle_timeout then features:reset(); local limits = features:tag("limits", { xmlns = "urn:xmpp:stream-limits:0" }); - if stanza_size_limit then - limits:text_tag("max-bytes", string.format("%d", stanza_size_limit)); + if session.stanza_size_limit then + limits:text_tag("max-bytes", string.format("%d", session.stanza_size_limit)); end if advertised_idle_timeout then limits:text_tag("idle-seconds", string.format("%d", advertised_idle_timeout)); @@ -352,7 +353,9 @@ session.close = session_close; - local stream = new_xmpp_stream(session, stream_callbacks, stanza_size_limit); + session.stanza_size_limit = unauthed_stanza_size_limit; + + local stream = new_xmpp_stream(session, stream_callbacks, session.stanza_size_limit); session.stream = stream; session.notopen = true; @@ -460,6 +463,13 @@ function module.add_host(module) module:hook("c2s-read-timeout", keepalive, -1); + module:hook("authentication-success", function(event) + local session = event.session; + if session.stream then + session.stanza_size_limit = authed_stanza_size_limit; + session.stream:set_stanza_size_limit(session.stanza_size_limit); + end + end); end module:hook("c2s-read-timeout", keepalive, -1); diff -r 0e9e3efa381f -r 8a4417d32b0f plugins/mod_s2s.lua --- a/plugins/mod_s2s.lua Thu Apr 02 20:53:04 2026 +0100 +++ b/plugins/mod_s2s.lua Tue Apr 07 20:35:41 2026 +0200 @@ -41,7 +41,8 @@ local secure_domains, insecure_domains = module:get_option_set("s2s_secure_domains", {})._items, module:get_option_set("s2s_insecure_domains", {})._items; local require_encryption = module:get_option_boolean("s2s_require_encryption", true); -local stanza_size_limit = module:get_option_integer("s2s_stanza_size_limit", 1024*512, 10000); +local unauthed_stanza_size_limit = module:get_option_integer("s2s_unauthed_stanza_size_limit", 10000, 1000); +local authed_stanza_size_limit = module:get_option_integer("s2s_stanza_size_limit", 1024*512, 10000); local sendq_size = module:get_option_integer("s2s_send_queue_size", 1024*32, 1); local advertised_idle_timeout = 14*60; -- default in all net.server implementations @@ -226,6 +227,8 @@ local host_session = s2s_new_outgoing(from_host, to_host); host_session.version = 1; + host_session.stanza_size_limit = unauthed_stanza_size_limit; + -- Store in buffer host_session.bounce_sendq = bounce_sendq; host_session.sendq = queue.new(sendq_size); @@ -270,10 +273,11 @@ module:hook("route/remote", route_to_existing_session, -1); module:hook("route/remote", route_to_new_session, -10); module:hook("s2sout-stream-features", function (event) - if not (stanza_size_limit or advertised_idle_timeout) then return end + local session = event.origin; + if not (session.stanza_size_limit or advertised_idle_timeout) then return end local limits = event.features:tag("limits", { xmlns = "urn:xmpp:stream-limits:0" }) - if stanza_size_limit then - limits:text_tag("max-bytes", string.format("%d", stanza_size_limit)); + if session.stanza_size_limit then + limits:text_tag("max-bytes", string.format("%d", session.stanza_size_limit)); end if advertised_idle_timeout then limits:text_tag("idle-seconds", string.format("%d", advertised_idle_timeout)); @@ -415,6 +419,9 @@ return false; end + session.stanza_size_limit = authed_stanza_size_limit; + session.stream:set_stanza_size_limit(session.stanza_size_limit); + if session.incoming and host then if not session.hosts[host] then session.hosts[host] = {}; end session.hosts[host].authed = true; @@ -573,11 +580,11 @@ end if ( session.type == "s2sin" or session.type == "s2sout" ) or features.tags[1] then - if stanza_size_limit or advertised_idle_timeout then + if session.stanza_size_limit or advertised_idle_timeout then features:reset(); local limits = features:tag("limits", { xmlns = "urn:xmpp:stream-limits:0" }); - if stanza_size_limit then - limits:text_tag("max-bytes", string.format("%d", stanza_size_limit)); + if session.stanza_size_limit then + limits:text_tag("max-bytes", string.format("%d", session.stanza_size_limit)); end if advertised_idle_timeout then limits:text_tag("idle-seconds", string.format("%d", advertised_idle_timeout)); @@ -794,7 +801,7 @@ -- Session initialization logic shared by incoming and outgoing local function initialize_session(session) - local stream = new_xmpp_stream(session, stream_callbacks, stanza_size_limit); + local stream = new_xmpp_stream(session, stream_callbacks, session.stanza_size_limit or unauthed_stanza_size_limit); session.thread = runner(function (item) if st.is_stanza(item) then