Changeset

6050:5d73412aa1ba 0.9.4

Merge
author Matthew Wild <mwild1@gmail.com>
date Tue, 01 Apr 2014 16:03:21 +0100
parents 6048:e447601cf13c (diff) 6049:6d410ffd6e13 (current diff)
children 6051:46b4af3cf5ce
files
diffstat 5 files changed, 95 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Tue Apr 01 10:02:58 2014 -0400
+++ b/Makefile	Tue Apr 01 16:03:21 2014 +0100
@@ -55,7 +55,7 @@
 	$(MAKE) install -C util-src
 
 %.install: %
-	sed "1s/\blua\b/$(RUNWITH)/; \
+	sed "1s| lua$$| $(RUNWITH)|; \
 		s|^CFG_SOURCEDIR=.*;$$|CFG_SOURCEDIR='$(INSTALLEDSOURCE)';|; \
 		s|^CFG_CONFIGDIR=.*;$$|CFG_CONFIGDIR='$(INSTALLEDCONFIG)';|; \
 		s|^CFG_DATADIR=.*;$$|CFG_DATADIR='$(INSTALLEDDATA)';|; \
--- a/core/portmanager.lua	Tue Apr 01 10:02:58 2014 -0400
+++ b/core/portmanager.lua	Tue Apr 01 16:03:21 2014 +0100
@@ -29,6 +29,8 @@
 	table.insert(default_local_interfaces, "::1");
 end
 
+local default_mode = config.get("*", "network_default_read_size") or 4096;
+
 --- Private state
 
 -- service_name -> { service_info, ... }
@@ -111,7 +113,7 @@
 		   }
 	bind_ports = set.new(type(bind_ports) ~= "table" and { bind_ports } or bind_ports );
 
-	local mode, ssl = listener.default_mode or "*a";
+	local mode, ssl = listener.default_mode or default_mode;
 	local hooked_ports = {};
 	
 	for interface in bind_interfaces do
--- a/plugins/mod_compression.lua	Tue Apr 01 10:02:58 2014 -0400
+++ b/plugins/mod_compression.lua	Tue Apr 01 16:03:21 2014 +0100
@@ -126,7 +126,7 @@
 module:hook("stanza/http://jabber.org/protocol/compress:compressed", function(event)
 	local session = event.origin;
 	
-	if session.type == "s2sout_unauthed" or session.type == "s2sout" then
+	if session.type == "s2sout" then
 		session.log("debug", "Activating compression...")
 		-- create deflate and inflate streams
 		local deflate_stream = get_deflate_stream(session);
@@ -150,7 +150,7 @@
 module:hook("stanza/http://jabber.org/protocol/compress:compress", function(event)
 	local session, stanza = event.origin, event.stanza;
 
-	if session.type == "c2s" or session.type == "s2sin" or session.type == "c2s_unauthed" or session.type == "s2sin_unauthed" then
+	if session.type == "c2s" or session.type == "s2sin" then
 		-- fail if we are already compressed
 		if session.compressed then
 			local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("setup-failed");
--- a/util/dependencies.lua	Tue Apr 01 10:02:58 2014 -0400
+++ b/util/dependencies.lua	Tue Apr 01 16:03:21 2014 +0100
@@ -140,7 +140,15 @@
 		if not pcall(lxp.new, { StartDoctypeDecl = false }) then
 			log("error", "The version of LuaExpat on your system leaves Prosody "
 				.."vulnerable to denial-of-service attacks. You should upgrade to "
-				.."LuaExpat 1.1.1 or higher as soon as possible. See "
+				.."LuaExpat 1.3.0 or higher as soon as possible. See "
+				.."http://prosody.im/doc/depends#luaexpat for more information.");
+		end
+		if not lxp.new({}).getcurrentbytecount then
+			log("error", "The version of LuaExpat on your system does not support "
+				.."stanza size limits, which may leave servers on untrusted "
+				.."networks (e.g. the internet) vulnerable to denial-of-service "
+				.."attacks. You should upgrade to LuaExpat 1.3.0 or higher as "
+				.."soon as possible. See "
 				.."http://prosody.im/doc/depends#luaexpat for more information.");
 		end
 	end
--- a/util/xmppstream.lua	Tue Apr 01 10:02:58 2014 -0400
+++ b/util/xmppstream.lua	Tue Apr 01 16:03:21 2014 +0100
@@ -6,7 +6,6 @@
 -- COPYING file in the source package for more information.
 --
 
-
 local lxp = require "lxp";
 local st = require "util.stanza";
 local stanza_mt = st.stanza_mt;
@@ -20,6 +19,10 @@
 
 -- COMPAT: w/LuaExpat 1.1.0
 local lxp_supports_doctype = pcall(lxp.new, { StartDoctypeDecl = false });
+local lxp_supports_xmldecl = pcall(lxp.new, { XmlDecl = false });
+local lxp_supports_bytecount = not not lxp.new({}).getcurrentbytecount;
+
+local default_stanza_size_limit = 1024*1024*10; -- 10MB
 
 module "xmppstream"
 
@@ -40,13 +43,16 @@
 _M.ns_separator = ns_separator;
 _M.ns_pattern = ns_pattern;
 
-function new_sax_handlers(session, stream_callbacks)
+local function dummy_cb() end
+
+function new_sax_handlers(session, stream_callbacks, cb_handleprogress)
 	local xml_handlers = {};
 	
 	local cb_streamopened = stream_callbacks.streamopened;
 	local cb_streamclosed = stream_callbacks.streamclosed;
 	local cb_error = stream_callbacks.error or function(session, e, stanza) error("XML stream error: "..tostring(e)..(stanza and ": "..tostring(stanza) or ""),2); end;
 	local cb_handlestanza = stream_callbacks.handlestanza;
+	cb_handleprogress = cb_handleprogress or dummy_cb;
 	
 	local stream_ns = stream_callbacks.stream_ns or xmlns_streams;
 	local stream_tag = stream_callbacks.stream_tag or "stream";
@@ -59,6 +65,7 @@
 	
 	local stack = {};
 	local chardata, stanza = {};
+	local stanza_size = 0;
 	local non_streamns_depth = 0;
 	function xml_handlers:StartElement(tagname, attr)
 		if stanza and #chardata > 0 then
@@ -87,10 +94,17 @@
 		end
 		
 		if not stanza then --if we are not currently inside a stanza
+			if lxp_supports_bytecount then
+				stanza_size = self:getcurrentbytecount();
+			end
 			if session.notopen then
 				if tagname == stream_tag then
 					non_streamns_depth = 0;
 					if cb_streamopened then
+						if lxp_supports_bytecount then
+							cb_handleprogress(stanza_size);
+							stanza_size = 0;
+						end
 						cb_streamopened(session, attr);
 					end
 				else
@@ -105,6 +119,9 @@
 			
 			stanza = setmetatable({ name = name, attr = attr, tags = {} }, stanza_mt);
 		else -- we are inside a stanza, so add a tag
+			if lxp_supports_bytecount then
+				stanza_size = stanza_size + self:getcurrentbytecount();
+			end
 			t_insert(stack, stanza);
 			local oldstanza = stanza;
 			stanza = setmetatable({ name = name, attr = attr, tags = {} }, stanza_mt);
@@ -112,12 +129,45 @@
 			t_insert(oldstanza.tags, stanza);
 		end
 	end
+	if lxp_supports_xmldecl then
+		function xml_handlers:XmlDecl(version, encoding, standalone)
+			if lxp_supports_bytecount then
+				cb_handleprogress(self:getcurrentbytecount());
+			end
+		end
+	end
+	function xml_handlers:StartCdataSection()
+		if lxp_supports_bytecount then
+			if stanza then
+				stanza_size = stanza_size + self:getcurrentbytecount();
+			else
+				cb_handleprogress(self:getcurrentbytecount());
+			end
+		end
+	end
+	function xml_handlers:EndCdataSection()
+		if lxp_supports_bytecount then
+			if stanza then
+				stanza_size = stanza_size + self:getcurrentbytecount();
+			else
+				cb_handleprogress(self:getcurrentbytecount());
+			end
+		end
+	end
 	function xml_handlers:CharacterData(data)
 		if stanza then
+			if lxp_supports_bytecount then
+				stanza_size = stanza_size + #data --self:getcurrentbytecount();
+			end
 			t_insert(chardata, data);
+		elseif lxp_supports_bytecount then
+			cb_handleprogress(#data--[[self:getcurrentbytecount()]]);
 		end
 	end
 	function xml_handlers:EndElement(tagname)
+		if lxp_supports_bytecount then
+			stanza_size = stanza_size + self:getcurrentbytecount()
+		end
 		if non_streamns_depth > 0 then
 			non_streamns_depth = non_streamns_depth - 1;
 		end
@@ -129,6 +179,10 @@
 			end
 			-- Complete stanza
 			if #stack == 0 then
+				if lxp_supports_bytecount then
+					cb_handleprogress(stanza_size);
+				end
+				stanza_size = 0;
 				if tagname ~= stream_error_tag then
 					cb_handlestanza(session, stanza);
 				else
@@ -159,7 +213,7 @@
 	xml_handlers.ProcessingInstruction = restricted_handler;
 	
 	local function reset()
-		stanza, chardata = nil, {};
+		stanza, chardata, stanza_size = nil, {}, 0;
 		stack = {};
 	end
 	
@@ -170,8 +224,20 @@
 	return xml_handlers, { reset = reset, set_session = set_session };
 end
 
-function new(session, stream_callbacks)
-	local handlers, meta = new_sax_handlers(session, stream_callbacks);
+function new(session, stream_callbacks, stanza_size_limit)
+	-- Used to track parser progress (e.g. to enforce size limits)
+	local n_outstanding_bytes = 0;
+	local handle_progress;
+	if lxp_supports_bytecount then
+		function handle_progress(n_parsed_bytes)
+			n_outstanding_bytes = n_outstanding_bytes - n_parsed_bytes;
+		end
+		stanza_size_limit = stanza_size_limit or default_stanza_size_limit;
+	elseif stanza_size_limit then
+		error("Stanza size limits are not supported on this version of LuaExpat")
+	end
+
+	local handlers, meta = new_sax_handlers(session, stream_callbacks, handle_progress);
 	local parser = new_parser(handlers, ns_separator);
 	local parse = parser.parse;
 
@@ -179,10 +245,18 @@
 		reset = function ()
 			parser = new_parser(handlers, ns_separator);
 			parse = parser.parse;
+			n_outstanding_bytes = 0;
 			meta.reset();
 		end,
 		feed = function (self, data)
-			return parse(parser, data);
+			if lxp_supports_bytecount then
+				n_outstanding_bytes = n_outstanding_bytes + #data;
+			end
+			local ok, err = parse(parser, data);
+			if lxp_supports_bytecount and n_outstanding_bytes > stanza_size_limit then
+				return nil, "stanza-too-large";
+			end
+			return ok, err;
 		end,
 		set_session = meta.set_session;
 	};