Merge 0.10->trunk
authorMatthew Wild <mwild1@gmail.com>
Wed, 02 Apr 2014 17:42:22 +0100
changeset 6055 596539a30e9b
parent 6039 f8df0a996575 (current diff)
parent 6054 7a5ddbaf758d (diff)
child 6059 0cbdf7243540
child 6144 cb08bba0443a
Merge 0.10->trunk
net/server_event.lua
net/server_select.lua
--- a/.hgtags	Tue Mar 25 19:18:32 2014 +0100
+++ b/.hgtags	Wed Apr 02 17:42:22 2014 +0100
@@ -51,3 +51,4 @@
 49e3c49eb0d8f33e94e2bf37e5421deacac5f499 0.9.2
 56b1f151f4a31fcc7dbde49e064a288715077ece 0.9.2
 872ff4851c9b6cd662aac4b1a056ac2a97c85ce5 0.9.3
+5d73412aa1ba39081683ab922575eae93e4e867a 0.9.4
--- a/Makefile	Tue Mar 25 19:18:32 2014 +0100
+++ b/Makefile	Wed Apr 02 17:42:22 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 Mar 25 19:18:32 2014 +0100
+++ b/core/portmanager.lua	Wed Apr 02 17:42:22 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/net/server_event.lua	Tue Mar 25 19:18:32 2014 +0100
+++ b/net/server_event.lua	Wed Apr 02 17:42:22 2014 +0100
@@ -368,6 +368,7 @@
 	function interface_mt:ssl()
 		return self._usingssl
 	end
+	interface_mt.clientport = interface_mt.port -- COMPAT server_select
 
 	function interface_mt:type()
 		return self._type or "client"
--- a/net/server_select.lua	Tue Mar 25 19:18:32 2014 +0100
+++ b/net/server_select.lua	Wed Apr 02 17:42:22 2014 +0100
@@ -402,6 +402,7 @@
 	handler.clientport = function( )
 		return clientport
 	end
+	handler.port = handler.clientport -- COMPAT server_event
 	local write = function( self, data )
 		bufferlen = bufferlen + #data
 		if bufferlen > maxsendlen then
--- a/plugins/mod_compression.lua	Tue Mar 25 19:18:32 2014 +0100
+++ b/plugins/mod_compression.lua	Wed Apr 02 17:42:22 2014 +0100
@@ -125,8 +125,8 @@
 
 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/plugins/muc/muc.lib.lua	Tue Mar 25 19:18:32 2014 +0100
+++ b/plugins/muc/muc.lib.lua	Wed Apr 02 17:42:22 2014 +0100
@@ -1032,7 +1032,7 @@
 	if actor_jid == true then return true; end
 
 	local actor = self._occupants[self._jid_nick[actor_jid]];
-	if actor.role == "moderator" then
+	if actor and actor.role == "moderator" then
 		if occupant.affiliation ~= "owner" and occupant.affiliation ~= "admin" then
 			if actor.affiliation == "owner" or actor.affiliation == "admin" then
 				return true;
--- a/util/dependencies.lua	Tue Mar 25 19:18:32 2014 +0100
+++ b/util/dependencies.lua	Wed Apr 02 17:42:22 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 Mar 25 19:18:32 2014 +0100
+++ b/util/xmppstream.lua	Wed Apr 02 17:42:22 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 + self:getcurrentbytecount();
+			end
 			t_insert(chardata, data);
+		elseif lxp_supports_bytecount then
+			cb_handleprogress(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,19 +224,39 @@
 	return xml_handlers, { reset = reset, set_session = set_session };
 end
 
-function new(session, stream_callbacks)
-	local handlers, meta = new_sax_handlers(session, stream_callbacks);
-	local parser = new_parser(handlers, ns_separator);
+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, false);
 	local parse = parser.parse;
 
 	return {
 		reset = function ()
-			parser = new_parser(handlers, ns_separator);
+			parser = new_parser(handlers, ns_separator, false);
 			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;
 	};