Diff

mod_sasl2_fast/mod_sasl2_fast.lua @ 5062:38a0e3621181

mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
author Matthew Wild <mwild1@gmail.com>
date Thu, 13 Oct 2022 22:47:35 +0100
child 5066:74145faceba2
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_sasl2_fast/mod_sasl2_fast.lua	Thu Oct 13 22:47:35 2022 +0100
@@ -0,0 +1,88 @@
+local tokenauth = module:depends("tokenauth");
+local sasl = require "util.sasl";
+local dt = require "util.datetime";
+local st = require "util.stanza";
+
+local fast_token_ttl = module:get_option_number("sasl2_fast_token_ttl", 86400*21);
+
+local xmlns_fast = "urn:xmpp:fast:0";
+local xmlns_sasl2 = "urn:xmpp:sasl:2";
+
+function get_sasl_handler(session) --luacheck: ignore session
+	local token_auth_profile = {
+		token_test = function (_, client_id, token, mech_name, counter) --luacheck: ignore
+			return false; -- FIXME
+		end;
+	};
+	return sasl.new(module.host, token_auth_profile);
+end
+
+-- Advertise FAST to connecting clients
+module:hook("advertise-sasl-features", function (event)
+	local sasl_handler = get_sasl_handler(event.session);
+	if not sasl_handler then return; end
+	event.session.fast_sasl_handler = sasl_handler;
+	local fast = st.stanza("fast", { xmlns = xmlns_fast });
+	for mech in sasl_handler:mechanisms() do
+		fast:text_tag("mechanism", mech);
+	end
+	event.features:add_child(fast);
+end);
+
+-- Process any FAST elements in <authenticate/>
+module:hook_tag(xmlns_sasl2, "authenticate", function (session, auth)
+	-- Cache action for future processing (after auth success)
+	local fast_auth = auth:get_child(xmlns_fast, "fast");
+	if fast_auth then
+		-- Client says it is using FAST auth, so set our SASL handler
+		session.log("debug", "Client is authenticating using FAST");
+		session.sasl_handler = session.fast_sasl_handler;
+	end
+	session.fast_sasl_handler = nil;
+	local fast_token_request = auth:get_child(xmlns_fast, "request-token");
+	if fast_token_request then
+		local mech = fast_token_request.attr.mechanism;
+		session.log("debug", "Client requested new FAST token for %s", mech);
+		session.fast_token_request = {
+			mechanism = mech;
+		};
+	end
+end, 100);
+
+-- Process post-success (new token generation, etc.)
+module:hook("sasl2/c2s/success", function (event)
+	local session = event.session;
+
+	local token_request = session.fast_token_request;
+	if token_request then
+		local token, token_info = tokenauth.create_jid_token(
+			session.full_jid,
+			session.full_jid,
+			session.role,
+			fast_token_ttl,
+			{
+				fast_token = true;
+				fast_mechanism = token_request.mechanism;
+			}
+		);
+		if token then
+			event.success:tag("token", {
+				xmlns = xmlns_fast;
+				expiry = dt.datetime(token_info.expiry);
+				token = token;
+			}):up();
+		end
+	end
+end, 75);
+
+
+-- X-PLAIN-TOKEN mechanism
+
+local function x_plain_token(self, message) --luacheck: ignore 212/self
+	if not message then
+		return nil, "malformed-request";
+	end
+	return nil, "temporary-auth-failure"; -- FIXME
+end
+
+sasl.registerMechanism("X-PLAIN-TOKEN", { "token_test" }, x_plain_token);