# HG changeset patch # User Matthew Wild # Date 1665697655 -3600 # Node ID 38a0e36211810c62de8e4e5d43ab5f7d46e9cac5 # Parent e44b868cc575d689fba278f8202853f1db7081cc mod_sasl2_fast: New module for SASL2 FAST authentication (WIP) diff -r e44b868cc575 -r 38a0e3621181 mod_sasl2_fast/mod_sasl2_fast.lua --- /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 +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);