Mercurial > prosody-modules
comparison mod_sasl2_fast/mod_sasl2_fast.lua @ 5650:0eb2d5ea2428
merge
author | Stephen Paul Weber <singpolyma@singpolyma.net> |
---|---|
date | Sat, 06 May 2023 19:40:23 -0500 |
parents | b10a7082b3c3 |
children | 563c2c70cb9f |
comparison
equal
deleted
inserted
replaced
5649:2c69577b28c2 | 5650:0eb2d5ea2428 |
---|---|
1 local usermanager = require "core.usermanager"; | |
2 | |
1 local sasl = require "util.sasl"; | 3 local sasl = require "util.sasl"; |
2 local dt = require "util.datetime"; | 4 local dt = require "util.datetime"; |
3 local id = require "util.id"; | 5 local id = require "util.id"; |
4 local jid = require "util.jid"; | 6 local jid = require "util.jid"; |
5 local st = require "util.stanza"; | 7 local st = require "util.stanza"; |
36 return token_info; | 38 return token_info; |
37 end | 39 end |
38 | 40 |
39 local function new_token_tester(hmac_f) | 41 local function new_token_tester(hmac_f) |
40 return function (mechanism, username, client_id, token_hash, cb_data, invalidate) | 42 return function (mechanism, username, client_id, token_hash, cb_data, invalidate) |
43 local account_info = usermanager.get_account_info(username, module.host); | |
44 local last_password_change = account_info and account_info.password_updated; | |
41 local tried_current_token = false; | 45 local tried_current_token = false; |
42 local key = hash.sha256(client_id, true).."-new"; | 46 local key = hash.sha256(client_id, true).."-new"; |
43 local token; | 47 local token; |
44 repeat | 48 repeat |
45 log("debug", "Looking for %s token %s/%s", mechanism, username, key); | 49 log("debug", "Looking for %s token %s/%s", mechanism, username, key); |
50 local current_time = now(); | 54 local current_time = now(); |
51 if token.expires_at < current_time then | 55 if token.expires_at < current_time then |
52 log("debug", "Token found, but it has expired (%ds ago). Cleaning up...", current_time - token.expires_at); | 56 log("debug", "Token found, but it has expired (%ds ago). Cleaning up...", current_time - token.expires_at); |
53 token_store:set(username, key, nil); | 57 token_store:set(username, key, nil); |
54 return nil, "credentials-expired"; | 58 return nil, "credentials-expired"; |
59 elseif last_password_change and token.issued_at < last_password_change then | |
60 log("debug", "Token found, but issued prior to password change (%ds ago). Cleaning up...", | |
61 current_time - last_password_change | |
62 ); | |
63 token_store:set(username, key, nil); | |
64 return nil, "credentials-expired"; | |
55 end | 65 end |
56 if not tried_current_token and not invalidate then | 66 if not tried_current_token and not invalidate then |
57 -- The new token is becoming the current token | 67 -- The new token is becoming the current token |
58 token_store:set_keys(username, { | 68 token_store:set_keys(username, { |
59 [key] = token_store.remove; | 69 [key] = token_store.remove; |
60 [key:sub(1, -4).."-cur"] = token; | 70 [key:sub(1, -5).."-cur"] = token; |
61 }); | 71 }); |
62 end | 72 end |
63 local rotation_needed; | 73 local rotation_needed; |
64 if invalidate then | 74 if invalidate then |
65 token_store:set(username, key, nil); | 75 token_store:set(username, key, nil); |
72 end | 82 end |
73 if not tried_current_token then | 83 if not tried_current_token then |
74 log("debug", "Trying next token..."); | 84 log("debug", "Trying next token..."); |
75 -- Try again with the current token instead | 85 -- Try again with the current token instead |
76 tried_current_token = true; | 86 tried_current_token = true; |
77 key = key:sub(1, -4).."-cur"; | 87 key = key:sub(1, -5).."-cur"; |
78 else | 88 else |
79 log("debug", "No matching %s token found for %s/%s", mechanism, username, key); | 89 log("debug", "No matching %s token found for %s/%s", mechanism, username, key); |
80 return nil; | 90 return nil; |
81 end | 91 end |
82 until false; | 92 until false; |
100 username = jid.node(event.stream.from); | 110 username = jid.node(event.stream.from); |
101 if not username then return; end | 111 if not username then return; end |
102 end | 112 end |
103 local sasl_handler = get_sasl_handler(username); | 113 local sasl_handler = get_sasl_handler(username); |
104 if not sasl_handler then return; end | 114 if not sasl_handler then return; end |
115 sasl_handler.fast_auth = true; -- For informational purposes | |
105 -- Copy channel binding info from primary SASL handler | 116 -- Copy channel binding info from primary SASL handler |
106 sasl_handler.profile.cb = session.sasl_handler.profile.cb; | 117 sasl_handler.profile.cb = session.sasl_handler.profile.cb; |
107 sasl_handler.userdata = session.sasl_handler.userdata; | 118 sasl_handler.userdata = session.sasl_handler.userdata; |
108 -- Store this handler, in case we later want to use it for authenticating | 119 -- Store this handler, in case we later want to use it for authenticating |
109 session.fast_sasl_handler = sasl_handler; | 120 session.fast_sasl_handler = sasl_handler; |
215 | 226 |
216 register_ht_mechanism("HT-SHA-256-NONE", "ht_sha_256", nil); | 227 register_ht_mechanism("HT-SHA-256-NONE", "ht_sha_256", nil); |
217 register_ht_mechanism("HT-SHA-256-UNIQ", "ht_sha_256", "tls-unique"); | 228 register_ht_mechanism("HT-SHA-256-UNIQ", "ht_sha_256", "tls-unique"); |
218 register_ht_mechanism("HT-SHA-256-ENDP", "ht_sha_256", "tls-server-end-point"); | 229 register_ht_mechanism("HT-SHA-256-ENDP", "ht_sha_256", "tls-server-end-point"); |
219 register_ht_mechanism("HT-SHA-256-EXPR", "ht_sha_256", "tls-exporter"); | 230 register_ht_mechanism("HT-SHA-256-EXPR", "ht_sha_256", "tls-exporter"); |
231 | |
232 -- Public API | |
233 | |
234 --luacheck: ignore 131 | |
235 function is_client_fast(username, client_id, last_password_change) | |
236 local client_id_hash = hash.sha256(client_id, true); | |
237 local curr_time = now(); | |
238 local cur = token_store:get(username, client_id_hash.."-cur"); | |
239 if cur and cur.expires_at >= curr_time and (not last_password_change or last_password_change < cur.issued_at) then | |
240 return true; | |
241 end | |
242 local new = token_store:get(username, client_id_hash.."-new"); | |
243 if new and new.expires_at >= curr_time and (not last_password_change or last_password_change < new.issued_at) then | |
244 return true; | |
245 end | |
246 return false; | |
247 end | |
248 | |
249 function revoke_fast_tokens(username, client_id) | |
250 local client_id_hash = hash.sha256(client_id, true); | |
251 local cur_ok = token_store:set(username, client_id_hash.."-cur", nil); | |
252 local new_ok = token_store:set(username, client_id_hash.."-new", nil); | |
253 return cur_ok and new_ok; | |
254 end |