annotate mod_sasl2_fast/mod_sasl2_fast.lua @ 5093:f2dfbcc676a6

mod_sasl2_bind2: Add explicit dependency on mod_sasl2 Ensures mod_sasl2 is installed and loaded so it can fire the relevant events.
author Kim Alvefur <zash@zash.se>
date Mon, 28 Nov 2022 19:05:48 +0100
parents dda2af7ed02f
children 745c7f4cca40
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5062
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";
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
3 local id = require "util.id";
5068
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
4 local jid = require "util.jid";
5062
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";
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
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: 5062
diff changeset
7 local hash = require "util.hashes";
5062
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
9 -- Tokens expire after 21 days by default
5062
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10 local fast_token_ttl = module:get_option_number("sasl2_fast_token_ttl", 86400*21);
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
11 -- Tokens are automatically rotated daily
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
12 local fast_token_min_ttl = module:get_option_number("sasl2_fast_token_min_ttl", 86400);
5062
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14 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
15 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
16
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
17 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: 5062
diff changeset
18
5076
eb46abc65dfd mod_sasl2_fast: Improved logging
Matthew Wild <mwild1@gmail.com>
parents: 5075
diff changeset
19 local log = module._log;
eb46abc65dfd mod_sasl2_fast: Improved logging
Matthew Wild <mwild1@gmail.com>
parents: 5075
diff changeset
20
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
21 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: 5062
diff changeset
22 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: 5062
diff changeset
23 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: 5062
diff changeset
24 local issued_at = now();
5070
5cc6f3749376 mod_sasl2_fast: Fix make_token() to return appropriate result
Matthew Wild <mwild1@gmail.com>
parents: 5069
diff changeset
25 local token_info = {
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
26 mechanism = mechanism;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
27 secret = new_token;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
28 issued_at = issued_at;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
29 expires_at = issued_at + fast_token_ttl;
5070
5cc6f3749376 mod_sasl2_fast: Fix make_token() to return appropriate result
Matthew Wild <mwild1@gmail.com>
parents: 5069
diff changeset
30 };
5cc6f3749376 mod_sasl2_fast: Fix make_token() to return appropriate result
Matthew Wild <mwild1@gmail.com>
parents: 5069
diff changeset
31 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: 5069
diff changeset
32 return nil;
5cc6f3749376 mod_sasl2_fast: Fix make_token() to return appropriate result
Matthew Wild <mwild1@gmail.com>
parents: 5069
diff changeset
33 end
5cc6f3749376 mod_sasl2_fast: Fix make_token() to return appropriate result
Matthew Wild <mwild1@gmail.com>
parents: 5069
diff changeset
34 return token_info;
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
35 end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
36
5071
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
37 local function new_token_tester(hmac_f)
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
38 return function (mechanism, username, client_id, token_hash, cb_data, invalidate)
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
39 local tried_current_token = false;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
40 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: 5062
diff changeset
41 local token;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
42 repeat
5076
eb46abc65dfd mod_sasl2_fast: Improved logging
Matthew Wild <mwild1@gmail.com>
parents: 5075
diff changeset
43 log("debug", "Looking for %s token %s/%s", mechanism, username, key);
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
44 token = token_store:get(username, key);
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
45 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: 5062
diff changeset
46 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: 5062
diff changeset
47 if hash.equals(expected_hash, token_hash) then
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
48 local current_time = now();
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
49 if token.expires_at < current_time then
5084
dda2af7ed02f mod_sasl2_fast: Add more debug logging
Matthew Wild <mwild1@gmail.com>
parents: 5083
diff changeset
50 log("debug", "Token found, but it has expired (%ds ago). Cleaning up...", current_time - token.expires_at);
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
51 token_store:set(username, key, nil);
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
52 return nil, "credentials-expired";
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
53 end
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
54 if not tried_current_token and not invalidate then
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
55 -- 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: 5062
diff changeset
56 token_store:set_keys(username, {
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
57 [key] = token_store.remove;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
58 [key:sub(1, -4).."-cur"] = token;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
59 });
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
60 end
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
61 local rotation_needed;
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
62 if invalidate then
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
63 token_store:set(username, key, nil);
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
64 elseif current_time - token.issued_at > fast_token_min_ttl then
5084
dda2af7ed02f mod_sasl2_fast: Add more debug logging
Matthew Wild <mwild1@gmail.com>
parents: 5083
diff changeset
65 log("debug", "FAST token due for rotation (age: %d)", current_time - token.issued_at);
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
66 rotation_needed = true;
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
67 end
5082
ddb1940b08e0 mod_sasl2_fast: Clean up backend return values (fixes constant rotation)
Matthew Wild <mwild1@gmail.com>
parents: 5078
diff changeset
68 return true, username, hmac_f(token.secret, "Responder"..cb_data), rotation_needed;
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
69 end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
70 end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
71 if not tried_current_token then
5076
eb46abc65dfd mod_sasl2_fast: Improved logging
Matthew Wild <mwild1@gmail.com>
parents: 5075
diff changeset
72 log("debug", "Trying next token...");
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
73 -- 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: 5062
diff changeset
74 tried_current_token = true;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
75 key = key:sub(1, -4).."-cur";
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
76 else
5076
eb46abc65dfd mod_sasl2_fast: Improved logging
Matthew Wild <mwild1@gmail.com>
parents: 5075
diff changeset
77 log("debug", "No matching %s token found for %s/%s", mechanism, username, key);
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
78 return nil;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
79 end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
80 until false;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
81 end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
82 end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
83
5071
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
84 function get_sasl_handler()
5062
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
85 local token_auth_profile = {
5071
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
86 ht_sha_256 = new_token_tester(hash.hmac_sha256);
5062
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
87 };
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
88 local handler = sasl.new(module.host, token_auth_profile);
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
89 handler.fast = true;
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
90 return handler;
5062
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
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
93 -- Advertise FAST to connecting clients
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
94 module:hook("advertise-sasl-features", function (event)
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
95 local session = event.origin;
5068
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
96 local username = session.username;
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
97 if not username then
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
98 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: 5066
diff changeset
99 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: 5066
diff changeset
100 end
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
101 local sasl_handler = get_sasl_handler(username);
5062
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
102 if not sasl_handler then return; end
5083
4837232474ca mod_sasl2_fast: Fixes to make channel binding work again
Matthew Wild <mwild1@gmail.com>
parents: 5082
diff changeset
103 sasl_handler.profile.cb = session.sasl_handler.profile.cb;
4837232474ca mod_sasl2_fast: Fixes to make channel binding work again
Matthew Wild <mwild1@gmail.com>
parents: 5082
diff changeset
104 sasl_handler.userdata = session.sasl_handler.userdata;
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
105 session.fast_sasl_handler = sasl_handler;
5062
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
106 local fast = st.stanza("fast", { xmlns = xmlns_fast });
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
107 for mech in pairs(sasl_handler:mechanisms()) do
5062
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
108 fast:text_tag("mechanism", mech);
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
109 end
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
110 event.features:add_child(fast);
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
111 end);
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
112
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
113 -- 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
114 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
115 -- Cache action for future processing (after auth success)
5072
d41677929f68 mod_sasl2_fast: Fixes for <authenticate> processing
Matthew Wild <mwild1@gmail.com>
parents: 5071
diff changeset
116 local fast_auth = auth:get_child("fast", xmlns_fast);
5062
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
117 if fast_auth then
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
118 -- Client says it is using FAST auth, so set our SASL handler
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
119 local fast_sasl_handler = session.fast_sasl_handler;
5072
d41677929f68 mod_sasl2_fast: Fixes for <authenticate> processing
Matthew Wild <mwild1@gmail.com>
parents: 5071
diff changeset
120 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: 5071
diff changeset
121 if fast_sasl_handler and client_id then
5068
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
122 session.log("debug", "Client is authenticating using FAST");
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
123 fast_sasl_handler.client_id = client_id;
5073
f158f18704c0 mod_sasl2_fast: Copy channel binding data state from original SASL handler
Matthew Wild <mwild1@gmail.com>
parents: 5072
diff changeset
124 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: 5072
diff changeset
125 fast_sasl_handler.userdata = session.sasl_handler.userdata;
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
126 local invalidate = fast_auth.attr.invalidate;
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
127 fast_sasl_handler.invalidate = invalidate == "1" or invalidate == "true";
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
128 -- Set our SASL handler as the session's SASL handler
5068
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
129 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: 5066
diff changeset
130 else
5076
eb46abc65dfd mod_sasl2_fast: Improved logging
Matthew Wild <mwild1@gmail.com>
parents: 5075
diff changeset
131 session.log("warn", "Client asked to auth via FAST, but SASL handler or client id missing");
5068
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
132 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: 5066
diff changeset
133 :tag("malformed-request"):up()
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
134 :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: 5066
diff changeset
135 session.send(failure);
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
136 return true;
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
137 end
5062
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
138 end
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
139 session.fast_sasl_handler = nil;
5072
d41677929f68 mod_sasl2_fast: Fixes for <authenticate> processing
Matthew Wild <mwild1@gmail.com>
parents: 5071
diff changeset
140 local fast_token_request = auth:get_child("request-token", xmlns_fast);
5062
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
141 if fast_token_request then
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
142 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
143 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
144 session.fast_token_request = {
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
145 mechanism = mech;
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
146 };
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, 100);
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
149
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
150 -- 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
151 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
152 local session = event.session;
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 token_request = session.fast_token_request;
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
155 local client_id = session.client_id;
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
156 local sasl_handler = session.sasl_handler;
5083
4837232474ca mod_sasl2_fast: Fixes to make channel binding work again
Matthew Wild <mwild1@gmail.com>
parents: 5082
diff changeset
157 if token_request or (sasl_handler.fast and sasl_handler.rotation_needed) then
5068
20e635eb4cdc mod_sasl2_fast: More robust handling of stream@from and user-agent@id
Matthew Wild <mwild1@gmail.com>
parents: 5066
diff changeset
158 if not client_id then
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
159 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: 5062
diff changeset
160 return;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
161 end
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
162 local mechanism = token_request and token_request.mechanism or session.sasl_handler.selected;
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
163 local token_info = make_token(session.username, client_id, mechanism)
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
164 if token_info then
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
165 session.log("debug", "Provided new FAST token to client");
5062
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
166 event.success:tag("token", {
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
167 xmlns = xmlns_fast;
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
168 expiry = dt.datetime(token_info.expires_at);
5074
1726050e9a4b mod_sasl2_fast: Fix field name for returned secret
Matthew Wild <mwild1@gmail.com>
parents: 5073
diff changeset
169 token = token_info.secret;
5062
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
170 }):up();
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
171 end
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
172 end
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
173 end, 75);
38a0e3621181 mod_sasl2_fast: New module for SASL2 FAST authentication (WIP)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
174
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
175 -- HT-* mechanisms
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
176
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
177 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: 5062
diff changeset
178 return function (sasl_handler, message)
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
179 local backend = sasl_handler.profile[backend_profile_name];
5082
ddb1940b08e0 mod_sasl2_fast: Clean up backend return values (fixes constant rotation)
Matthew Wild <mwild1@gmail.com>
parents: 5078
diff changeset
180 local authc_username, token_hash = message:match("^([^%z]+)%z(.+)$");
ddb1940b08e0 mod_sasl2_fast: Clean up backend return values (fixes constant rotation)
Matthew Wild <mwild1@gmail.com>
parents: 5078
diff changeset
181 if not authc_username then
5071
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
182 return "failure", "malformed-request";
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
183 end
bc983da908e6 mod_sasl2_fast: Take username from SASL exchange rather than stream@from
Matthew Wild <mwild1@gmail.com>
parents: 5070
diff changeset
184 local cb_data = cb_name and sasl_handler.profile.cb[cb_name](sasl_handler) or "";
5082
ddb1940b08e0 mod_sasl2_fast: Clean up backend return values (fixes constant rotation)
Matthew Wild <mwild1@gmail.com>
parents: 5078
diff changeset
185 local ok, authz_username, response, rotation_needed = backend(
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
186 mechanism_name,
5082
ddb1940b08e0 mod_sasl2_fast: Clean up backend return values (fixes constant rotation)
Matthew Wild <mwild1@gmail.com>
parents: 5078
diff changeset
187 authc_username,
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
188 sasl_handler.client_id,
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
189 token_hash,
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
190 cb_data,
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
191 sasl_handler.invalidate
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
192 );
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
193 if not ok then
5082
ddb1940b08e0 mod_sasl2_fast: Clean up backend return values (fixes constant rotation)
Matthew Wild <mwild1@gmail.com>
parents: 5078
diff changeset
194 -- authz_username is error condition
ddb1940b08e0 mod_sasl2_fast: Clean up backend return values (fixes constant rotation)
Matthew Wild <mwild1@gmail.com>
parents: 5078
diff changeset
195 return "failure", authz_username or "not-authorized";
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
196 end
5082
ddb1940b08e0 mod_sasl2_fast: Clean up backend return values (fixes constant rotation)
Matthew Wild <mwild1@gmail.com>
parents: 5078
diff changeset
197 sasl_handler.username = authz_username;
5078
36d3f11724c8 mod_sasl2_fast: Implement rotation and invalidation
Matthew Wild <mwild1@gmail.com>
parents: 5077
diff changeset
198 sasl_handler.rotation_needed = rotation_needed;
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
199 return "success", response;
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
200 end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
201 end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
202
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
203 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: 5062
diff changeset
204 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: 5062
diff changeset
205 name,
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
206 backend_profile_name,
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
207 cb_name
5075
ba2f1292d5fe mod_sasl2_fast: Register HT-* mechanisms with the required channel binding
Matthew Wild <mwild1@gmail.com>
parents: 5074
diff changeset
208 ),
5083
4837232474ca mod_sasl2_fast: Fixes to make channel binding work again
Matthew Wild <mwild1@gmail.com>
parents: 5082
diff changeset
209 cb_name and { cb_name } or nil);
5066
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
210 end
74145faceba2 mod_sasl2_fast: Implement most of FAST + SASL HT-SHA-256
Matthew Wild <mwild1@gmail.com>
parents: 5062
diff changeset
211
5069
e8342ae5ae12 mod_sasl2_fast: Improve backend profile name and correctly use it everywhere
Matthew Wild <mwild1@gmail.com>
parents: 5068
diff changeset
212 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: 5068
diff changeset
213 register_ht_mechanism("HT-SHA-256-UNIQ", "ht_sha_256", "tls-unique");
5083
4837232474ca mod_sasl2_fast: Fixes to make channel binding work again
Matthew Wild <mwild1@gmail.com>
parents: 5082
diff changeset
214 register_ht_mechanism("HT-SHA-256-ENDP", "ht_sha_256", "tls-server-end-point");
5069
e8342ae5ae12 mod_sasl2_fast: Improve backend profile name and correctly use it everywhere
Matthew Wild <mwild1@gmail.com>
parents: 5068
diff changeset
215 register_ht_mechanism("HT-SHA-256-EXPR", "ht_sha_256", "tls-exporter");