Changeset

6428:3ee09bfe16e1

Merge 0.10->trunk
author Kim Alvefur <zash@zash.se>
date Tue, 23 Sep 2014 23:22:13 +0200
parents 6423:1c78f10f05d0 (current diff) 6427:7653bbd5247e (diff)
children 6429:675aea867574
files
diffstat 3 files changed, 45 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/mod_dialback.lua	Tue Sep 23 01:44:16 2014 +0200
+++ b/plugins/mod_dialback.lua	Tue Sep 23 23:22:13 2014 +0200
@@ -176,14 +176,6 @@
 	end
 end);
 
-module:hook_stanza("urn:ietf:params:xml:ns:xmpp-sasl", "failure", function (origin, stanza)
-	if origin.external_auth == "failed" then
-		module:log("debug", "SASL EXTERNAL failed, falling back to dialback");
-		initiate_dialback(origin);
-		return true;
-	end
-end, 100);
-
 module:hook_stanza(xmlns_stream, "features", function (origin, stanza)
 	if not origin.external_auth or origin.external_auth == "failed" then
 		module:log("debug", "Initiating dialback...");
--- a/plugins/mod_s2s/mod_s2s.lua	Tue Sep 23 01:44:16 2014 +0200
+++ b/plugins/mod_s2s/mod_s2s.lua	Tue Sep 23 23:22:13 2014 +0200
@@ -154,6 +154,10 @@
 			-- so the stream is ready for stanzas.  RFC 6120 Section 4.3
 			mark_connected(session);
 			return true;
+		elseif not session.dialback_verifying then
+			session.log("warn", "No SASL EXTERNAL offer and Dialback doesn't seem to be enabled, giving up");
+			session:close();
+			return false;
 		end
 	end, -1);
 end
--- a/plugins/mod_saslauth.lua	Tue Sep 23 01:44:16 2014 +0200
+++ b/plugins/mod_saslauth.lua	Tue Sep 23 23:22:13 2014 +0200
@@ -13,8 +13,6 @@
 local sm_make_authenticated = require "core.sessionmanager".make_authenticated;
 local base64 = require "util.encodings".base64;
 
-local cert_verify_identity = require "util.x509".verify_identity;
-
 local usermanager_get_sasl_handler = require "core.usermanager".get_sasl_handler;
 local tostring = tostring;
 
@@ -28,15 +26,15 @@
 
 local function build_reply(status, ret, err_msg)
 	local reply = st.stanza(status, {xmlns = xmlns_sasl});
-	if status == "challenge" then
-		--log("debug", "CHALLENGE: %s", ret or "");
-		reply:text(base64.encode(ret or ""));
-	elseif status == "failure" then
+	if status == "failure" then
 		reply:tag(ret):up();
 		if err_msg then reply:tag("text"):text(err_msg); end
-	elseif status == "success" then
-		--log("debug", "SUCCESS: %s", ret or "");
-		reply:text(base64.encode(ret or ""));
+	elseif status == "challenge" or status == "success" then
+		if ret == "" then
+			reply:text("=")
+		elseif ret then
+			reply:text(base64.encode(ret));
+		end
 	else
 		module:log("error", "Unknown sasl status: %s", status);
 	end
@@ -99,12 +97,10 @@
 	module:log("info", "SASL EXTERNAL with %s failed", session.to_host)
 	-- TODO: Log the failure reason
 	session.external_auth = "failed"
+	session:close();
+	return true;
 end, 500)
 
-module:hook_stanza(xmlns_sasl, "failure", function (session, stanza)
-	-- TODO: Dialback wasn't loaded.  Do something useful.
-end, 90)
-
 module:hook_stanza("http://etherx.jabber.org/streams", "features", function (session, stanza)
 	if session.type ~= "s2sout_unauthed" or not session.secure then return; end
 
@@ -124,71 +120,52 @@
 end, 150);
 
 local function s2s_external_auth(session, stanza)
+	if session.external_auth ~= "offered" then return end -- Unexpected request
+
 	local mechanism = stanza.attr.mechanism;
 
-	if not session.secure then
-		if mechanism == "EXTERNAL" then
-			session.sends2s(build_reply("failure", "encryption-required"))
-		else
-			session.sends2s(build_reply("failure", "invalid-mechanism"))
-		end
+	if mechanism ~= "EXTERNAL" then
+		session.sends2s(build_reply("failure", "invalid-mechanism"));
 		return true;
 	end
 
-	if mechanism ~= "EXTERNAL" or session.cert_chain_status ~= "valid" then
-		session.sends2s(build_reply("failure", "invalid-mechanism"))
+	if not session.secure then
+		session.sends2s(build_reply("failure", "encryption-required"));
 		return true;
 	end
 
-	local text = stanza[1]
+	local text = stanza[1];
 	if not text then
-		session.sends2s(build_reply("failure", "malformed-request"))
-		return true
-	end
-
-	-- Either the value is "=" and we've already verified the external
-	-- cert identity, or the value is a string and either matches the
-	-- from_host (
-
-	text = base64.decode(text)
-	if not text then
-		session.sends2s(build_reply("failure", "incorrect-encoding"))
+		session.sends2s(build_reply("failure", "malformed-request"));
 		return true;
 	end
 
-	if session.cert_identity_status == "valid" then
-		if text ~= "" and text ~= session.from_host then
-			session.sends2s(build_reply("failure", "invalid-authzid"))
-			return true
-		end
-	else
-		if text == "" then
-			session.sends2s(build_reply("failure", "invalid-authzid"))
-			return true
-		end
+	text = base64.decode(text);
+	if not text then
+		session.sends2s(build_reply("failure", "incorrect-encoding"));
+		return true;
+	end
 
-		local cert = session.conn:socket():getpeercertificate()
-		if (cert_verify_identity(text, "xmpp-server", cert)) then
-			session.cert_identity_status = "valid"
-		else
-			session.cert_identity_status = "invalid"
-			session.sends2s(build_reply("failure", "invalid-authzid"))
-			return true
-		end
+	-- The text value is either "" or equals session.from_host
+	if not ( text == "" or text == session.from_host ) then
+		session.sends2s(build_reply("failure", "invalid-authzid"));
+		return true;
 	end
 
-	session.external_auth = "succeeded"
-
-	if not session.from_host then
-		session.from_host = text;
+	-- We've already verified the external cert identity before offering EXTERNAL
+	if session.cert_chain_status ~= "valid" or session.cert_identity_status ~= "valid" then
+		session.sends2s(build_reply("failure", "not-authorized"));
+		session:close();
+		return true;
 	end
-	session.sends2s(build_reply("success"))
 
-	local domain = text ~= "" and text or session.from_host;
-	module:log("info", "Accepting SASL EXTERNAL identity from %s", domain);
-	module:fire_event("s2s-authenticated", { session = session, host = domain });
+	-- Success!
+	session.external_auth = "succeeded";
+	session.sends2s(build_reply("success"));
+	module:log("info", "Accepting SASL EXTERNAL identity from %s", session.from_host);
+	module:fire_event("s2s-authenticated", { session = session, host = session.from_host });
 	session:reset_stream();
-	return true
+	return true;
 end
 
 module:hook("stanza/urn:ietf:params:xml:ns:xmpp-sasl:auth", function(event)
@@ -268,10 +245,10 @@
 module:hook("s2s-stream-features", function(event)
 	local origin, features = event.origin, event.features;
 	if origin.secure and origin.type == "s2sin_unauthed" then
-		-- Offer EXTERNAL if chain is valid and either we didn't validate
-		-- the identity or it passed.
-		if origin.cert_chain_status == "valid" and origin.cert_identity_status ~= "invalid" then --TODO: Configurable
-			module:log("debug", "Offering SASL EXTERNAL")
+		-- Offer EXTERNAL only if both chain and identity is valid.
+		if origin.cert_chain_status == "valid" and origin.cert_identity_status == "valid" then
+			module:log("debug", "Offering SASL EXTERNAL");
+			origin.external_auth = "offered"
 			features:tag("mechanisms", { xmlns = xmlns_sasl })
 				:tag("mechanism"):text("EXTERNAL")
 			:up():up();