mod_sasl2_fast/mod_sasl2_fast.lua
author Matthew Wild <mwild1@gmail.com>
Sat, 15 Oct 2022 19:47:05 +0100
changeset 5079 ba2f1292d5fe
parent 5078 1726050e9a4b
child 5080 eb46abc65dfd
permissions -rw-r--r--
mod_sasl2_fast: Register HT-* mechanisms with the required channel binding
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5066
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     1
local sasl = require "util.sasl";
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     2
local dt = require "util.datetime";
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
     3
local id = require "util.id";
5072
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
     4
local jid = require "util.jid";
5066
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     5
local st = require "util.stanza";
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
     6
local now = require "util.time".now;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
     7
local hash = require "util.hashes";
5066
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     9
local fast_token_ttl = module:get_option_number("sasl2_fast_token_ttl", 86400*21);
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    10
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    11
local xmlns_fast = "urn:xmpp:fast:0";
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    12
local xmlns_sasl2 = "urn:xmpp:sasl:2";
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    13
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    14
local token_store = module:open_store("fast_tokens", "map");
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    15
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    16
local function make_token(username, client_id, mechanism)
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    17
	local new_token = "secret-token:fast-"..id.long();
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    18
	local key = hash.sha256(client_id, true).."-new";
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    19
	local issued_at = now();
5074
5cc6f3749376 mod_sasl2_fast: Fix make_token() to return appropriate result
Matthew Wild <mwild1@gmail.com>
parents: 5073
diff changeset
    20
	local token_info = {
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    21
		mechanism = mechanism;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    22
		secret = new_token;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    23
		issued_at = issued_at;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    24
		expires_at = issued_at + fast_token_ttl;
5074
5cc6f3749376 mod_sasl2_fast: Fix make_token() to return appropriate result
Matthew Wild <mwild1@gmail.com>
parents: 5073
diff changeset
    25
	};
5cc6f3749376 mod_sasl2_fast: Fix make_token() to return appropriate result
Matthew Wild <mwild1@gmail.com>
parents: 5073
diff changeset
    26
	if not token_store:set(username, key, token_info) then
5cc6f3749376 mod_sasl2_fast: Fix make_token() to return appropriate result
Matthew Wild <mwild1@gmail.com>
parents: 5073
diff changeset
    27
		return nil;
5cc6f3749376 mod_sasl2_fast: Fix make_token() to return appropriate result
Matthew Wild <mwild1@gmail.com>
parents: 5073
diff changeset
    28
	end
5cc6f3749376 mod_sasl2_fast: Fix make_token() to return appropriate result
Matthew Wild <mwild1@gmail.com>
parents: 5073
diff changeset
    29
	return token_info;
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    30
end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    31
5075
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5074
diff changeset
    32
local function new_token_tester(hmac_f)
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5074
diff changeset
    33
	return function (mechanism, username, client_id, token_hash, cb_data)
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    34
		local tried_current_token = false;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    35
		local key = hash.sha256(client_id, true).."-new";
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    36
		local token;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    37
		repeat
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    38
			token = token_store:get(username, key);
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    39
			if token and token.mechanism == mechanism then
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    40
				local expected_hash = hmac_f(token.secret, "Initiator"..cb_data);
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    41
				if hash.equals(expected_hash, token_hash) then
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    42
					if token.expires_at < now() then
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    43
						token_store:set(username, key, nil);
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    44
						return nil, "credentials-expired";
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    45
					end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    46
					if not tried_current_token then
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    47
						-- The new token is becoming the current token
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    48
						token_store:set_keys(username, {
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    49
							[key] = token_store.remove;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    50
							[key:sub(1, -4).."-cur"] = token;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    51
						});
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    52
					end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    53
					return true, username, hmac_f(token.secret, "Responder"..cb_data);
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    54
				end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    55
			end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    56
			if not tried_current_token then
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    57
				-- Try again with the current token instead
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    58
				tried_current_token = true;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    59
				key = key:sub(1, -4).."-cur";
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    60
			else
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    61
				return nil;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    62
			end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    63
		until false;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    64
	end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    65
end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    66
5075
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5074
diff changeset
    67
function get_sasl_handler()
5066
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    68
	local token_auth_profile = {
5075
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5074
diff changeset
    69
		ht_sha_256 = new_token_tester(hash.hmac_sha256);
5066
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    70
		token_test = function (_, client_id, token, mech_name, counter) --luacheck: ignore
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    71
			return false; -- FIXME
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    72
		end;
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    73
	};
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    74
	return sasl.new(module.host, token_auth_profile);
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    75
end
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    76
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    77
-- Advertise FAST to connecting clients
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    78
module:hook("advertise-sasl-features", function (event)
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    79
	local session = event.origin;
5072
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
    80
	local username = session.username;
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
    81
	if not username then
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
    82
		username = jid.node(event.stream.from);
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
    83
		if not username then return; end
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
    84
	end
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
    85
	local sasl_handler = get_sasl_handler(username);
5066
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    86
	if not sasl_handler then return; end
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    87
	session.fast_sasl_handler = sasl_handler;
5066
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    88
	local fast = st.stanza("fast", { xmlns = xmlns_fast });
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
    89
	for mech in pairs(sasl_handler:mechanisms()) do
5066
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    90
		fast:text_tag("mechanism", mech);
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    91
	end
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    92
	event.features:add_child(fast);
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    93
end);
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    94
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    95
-- Process any FAST elements in <authenticate/>
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    96
module:hook_tag(xmlns_sasl2, "authenticate", function (session, auth)
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    97
	-- Cache action for future processing (after auth success)
5076
d41677929f68 mod_sasl2_fast: Fixes for <authenticate> processing
Matthew Wild <mwild1@gmail.com>
parents: 5075
diff changeset
    98
	local fast_auth = auth:get_child("fast", xmlns_fast);
5066
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    99
	if fast_auth then
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   100
		-- Client says it is using FAST auth, so set our SASL handler
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   101
		local fast_sasl_handler = session.fast_sasl_handler;
5076
d41677929f68 mod_sasl2_fast: Fixes for <authenticate> processing
Matthew Wild <mwild1@gmail.com>
parents: 5075
diff changeset
   102
		local client_id = auth:get_child_attr("user-agent", nil, "id");
d41677929f68 mod_sasl2_fast: Fixes for <authenticate> processing
Matthew Wild <mwild1@gmail.com>
parents: 5075
diff changeset
   103
		if fast_sasl_handler and client_id then
5072
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
   104
			session.log("debug", "Client is authenticating using FAST");
5076
d41677929f68 mod_sasl2_fast: Fixes for <authenticate> processing
Matthew Wild <mwild1@gmail.com>
parents: 5075
diff changeset
   105
			fast_sasl_handler.profile._client_id = client_id;
5077
f158f18704c0 mod_sasl2_fast: Copy channel binding data state from original SASL handler
Matthew Wild <mwild1@gmail.com>
parents: 5076
diff changeset
   106
			fast_sasl_handler.profile.cb = session.sasl_handler.profile.cb;
f158f18704c0 mod_sasl2_fast: Copy channel binding data state from original SASL handler
Matthew Wild <mwild1@gmail.com>
parents: 5076
diff changeset
   107
			fast_sasl_handler.userdata = session.sasl_handler.userdata;
5072
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
   108
			session.sasl_handler = fast_sasl_handler;
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
   109
		else
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
   110
			session.log("warn", "Client asked to auth via FAST, but no SASL handler available");
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
   111
			local failure = st.stanza("failure", { xmlns = xmlns_sasl2 })
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
   112
				:tag("malformed-request"):up()
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
   113
				:text_tag("text", "FAST is not available on this stream");
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
   114
			session.send(failure);
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
   115
			return true;
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
   116
		end
5066
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   117
	end
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   118
	session.fast_sasl_handler = nil;
5076
d41677929f68 mod_sasl2_fast: Fixes for <authenticate> processing
Matthew Wild <mwild1@gmail.com>
parents: 5075
diff changeset
   119
	local fast_token_request = auth:get_child("request-token", xmlns_fast);
5066
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   120
	if fast_token_request then
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   121
		local mech = fast_token_request.attr.mechanism;
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   122
		session.log("debug", "Client requested new FAST token for %s", mech);
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   123
		session.fast_token_request = {
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   124
			mechanism = mech;
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   125
		};
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   126
	end
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   127
end, 100);
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   128
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   129
-- Process post-success (new token generation, etc.)
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   130
module:hook("sasl2/c2s/success", function (event)
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   131
	local session = event.session;
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   132
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   133
	local token_request = session.fast_token_request;
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   134
	local client_id = session.client_id;
5066
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   135
	if token_request then
5072
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
   136
		if not client_id then
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   137
			session.log("warn", "FAST token requested, but missing client id");
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   138
			return;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   139
		end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   140
		local token_info = make_token(session.username, client_id, token_request.mechanism)
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   141
		if token_info then
5066
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   142
			event.success:tag("token", {
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   143
				xmlns = xmlns_fast;
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   144
				expiry = dt.datetime(token_info.expires_at);
5078
1726050e9a4b mod_sasl2_fast: Fix field name for returned secret
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
   145
				token = token_info.secret;
5066
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   146
			}):up();
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   147
		end
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   148
	end
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   149
end, 75);
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   150
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   151
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   152
-- X-PLAIN-TOKEN mechanism
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   153
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   154
local function x_plain_token(self, message) --luacheck: ignore 212/self
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   155
	if not message then
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   156
		return nil, "malformed-request";
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   157
	end
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   158
	return nil, "temporary-auth-failure"; -- FIXME
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   159
end
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   160
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   161
sasl.registerMechanism("X-PLAIN-TOKEN", { "token_test" }, x_plain_token);
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   162
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   163
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   164
-- HT-* mechanisms
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   165
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   166
local function new_ht_mechanism(mechanism_name, backend_profile_name, cb_name)
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   167
	return function (sasl_handler, message)
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   168
		local backend = sasl_handler.profile[backend_profile_name];
5075
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5074
diff changeset
   169
		local username, token_hash = message:match("^([^%z]+)%z(.+)$");
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5074
diff changeset
   170
		if not username then
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5074
diff changeset
   171
			return "failure", "malformed-request";
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5074
diff changeset
   172
		end
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5074
diff changeset
   173
		local cb_data = cb_name and sasl_handler.profile.cb[cb_name](sasl_handler) or "";
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5074
diff changeset
   174
		local ok, status, response = backend(mechanism_name, username, sasl_handler.profile._client_id, token_hash, cb_data);
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   175
		if not ok then
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   176
			return "failure", status or "not-authorized";
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   177
		end
5075
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5074
diff changeset
   178
		sasl_handler.username = status;
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   179
		return "success", response;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   180
	end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   181
end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   182
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   183
local function register_ht_mechanism(name, backend_profile_name, cb_name)
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   184
	return sasl.registerMechanism(name, { backend_profile_name }, new_ht_mechanism(
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   185
		name,
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   186
		backend_profile_name,
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   187
		cb_name
5079
ba2f1292d5fe mod_sasl2_fast: Register HT-* mechanisms with the required channel binding
Matthew Wild <mwild1@gmail.com>
parents: 5078
diff changeset
   188
	),
ba2f1292d5fe mod_sasl2_fast: Register HT-* mechanisms with the required channel binding
Matthew Wild <mwild1@gmail.com>
parents: 5078
diff changeset
   189
	{ cb_name });
5070
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   190
end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
   191
5073
e8342ae5ae12 mod_sasl2_fast: Improve backend profile name and correctly use it everywhere
Matthew Wild <mwild1@gmail.com>
parents: 5072
diff changeset
   192
register_ht_mechanism("HT-SHA-256-NONE", "ht_sha_256", nil);
e8342ae5ae12 mod_sasl2_fast: Improve backend profile name and correctly use it everywhere
Matthew Wild <mwild1@gmail.com>
parents: 5072
diff changeset
   193
register_ht_mechanism("HT-SHA-256-UNIQ", "ht_sha_256", "tls-unique");
e8342ae5ae12 mod_sasl2_fast: Improve backend profile name and correctly use it everywhere
Matthew Wild <mwild1@gmail.com>
parents: 5072
diff changeset
   194
register_ht_mechanism("HT-SHA-256-ENDP", "ht_sha_256", "tls-endpoint");
e8342ae5ae12 mod_sasl2_fast: Improve backend profile name and correctly use it everywhere
Matthew Wild <mwild1@gmail.com>
parents: 5072
diff changeset
   195
register_ht_mechanism("HT-SHA-256-EXPR", "ht_sha_256", "tls-exporter");