Annotate

plugins/sasl.lua @ 467:8e6a7a5e70b3

sasl: Expose what mechanisms were offered on authentication-failure
author Matthew Wild <mwild1@gmail.com>
date Fri, 17 Mar 2023 09:24:36 +0000
parent 456:6a65142052c8
child 490:6b2f31da9610
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
395
e86144a4eaa1 plugins: Cleanup [luacheck]
Kim Alvefur <zash@zash.se>
parents: 380
diff changeset
1 local verse = require"verse";
354
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
2 local base64, unbase64 = require "mime".b64, require"mime".unb64;
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
3 local xmlns_sasl = "urn:ietf:params:xml:ns:xmpp-sasl";
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
5 function verse.plugins.sasl(stream)
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6 local function handle_features(features_stanza)
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7 if stream.authenticated then return; end
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8 stream:debug("Authenticating with SASL...");
354
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
9 local sasl_mechanisms = features_stanza:get_child("mechanisms", xmlns_sasl);
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
10 if not sasl_mechanisms then return end
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
11
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
12 local mechanisms = {};
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
13 local preference = {};
467
8e6a7a5e70b3 sasl: Expose what mechanisms were offered on authentication-failure
Matthew Wild <mwild1@gmail.com>
parents: 456
diff changeset
14 local offered = {};
354
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
15
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
16 for mech in sasl_mechanisms:childtags("mechanism") do
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
17 mech = mech:get_text();
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
18 stream:debug("Server offers %s", mech);
467
8e6a7a5e70b3 sasl: Expose what mechanisms were offered on authentication-failure
Matthew Wild <mwild1@gmail.com>
parents: 456
diff changeset
19 offered[mech] = true;
354
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
20 if not mechanisms[mech] then
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
21 local name = mech:match("[^-]+");
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
22 local ok, impl = pcall(require, "util.sasl."..name:lower());
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
23 if ok then
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
24 stream:debug("Loaded SASL %s module", name);
360
ac3940bad1bf plugins.sasl: Store mechanisms with the correct name
Kim Alvefur <zash@zash.se>
parents: 358
diff changeset
25 mechanisms[mech], preference[mech] = impl(stream, mech);
354
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
26 elseif not tostring(impl):match("not found") then
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
27 stream:debug("Loading failed: %s", tostring(impl));
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
28 end
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
29 end
315
3742107e2505 plugins/sasl: Use ANONYMOUS authentication when no username provided
James Callahan <james@chatid.com>
parents: 302
diff changeset
30 end
354
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
31
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
32 local supported = {}; -- by the server
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
33 for mech in pairs(mechanisms) do
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
34 table.insert(supported, mech);
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
35 end
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
36 if not supported[1] then
467
8e6a7a5e70b3 sasl: Expose what mechanisms were offered on authentication-failure
Matthew Wild <mwild1@gmail.com>
parents: 456
diff changeset
37 stream:event("authentication-failure", { condition = "no-supported-sasl-mechanisms", mechanisms = offered });
354
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
38 stream:close();
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
39 return;
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
40 end
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
41 table.sort(supported, function (a, b) return preference[a] > preference[b]; end);
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
42 local mechanism, initial_data = supported[1];
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
43 stream:debug("Selecting %s mechanism...", mechanism);
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
44 stream.sasl_mechanism = coroutine.wrap(mechanisms[mechanism]);
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
45 initial_data = stream:sasl_mechanism(mechanism);
315
3742107e2505 plugins/sasl: Use ANONYMOUS authentication when no username provided
James Callahan <james@chatid.com>
parents: 302
diff changeset
46 local auth_stanza = verse.stanza("auth", { xmlns = xmlns_sasl, mechanism = mechanism });
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47 if initial_data then
354
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
48 auth_stanza:text(base64(initial_data));
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49 end
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50 stream:send(auth_stanza);
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
51 return true;
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52 end
380
0891b4e27766 Discard trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 360
diff changeset
53
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
54 local function handle_sasl(sasl_stanza)
354
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
55 if sasl_stanza.name == "failure" then
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
56 local err = sasl_stanza.tags[1];
302
0c83cb476246 plugins.sasl: Collect text message on SASL failure
Kim Alvefur <zash@zash.se>
parents: 197
diff changeset
57 local text = sasl_stanza:get_child_text("text");
0c83cb476246 plugins.sasl: Collect text message on SASL failure
Kim Alvefur <zash@zash.se>
parents: 197
diff changeset
58 stream:event("authentication-failure", { condition = err.name, text = text });
354
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
59 stream:close();
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
60 return false;
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
61 end
354
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
62 local ok, err = stream.sasl_mechanism(sasl_stanza.name, unbase64(sasl_stanza:get_text()));
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
63 if not ok then
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
64 stream:event("authentication-failure", { condition = err });
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
65 stream:close();
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
66 return false;
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
67 elseif ok == true then
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
68 stream:event("authentication-success");
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
69 stream.authenticated = true
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
70 stream:reopen();
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
71 else
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
72 stream:send(verse.stanza("response", { xmlns = xmlns_sasl }):text(base64(ok)));
58cd27b74ba5 Almost a SASL framework, supports negotiation and challenge-response, mechanism code split out into util/sasl/
Kim Alvefur <zash@zash.se>
parents: 315
diff changeset
73 end
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
74 return true;
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75 end
380
0891b4e27766 Discard trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 360
diff changeset
76
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
77 stream:hook("stream-features", handle_features, 300);
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
78 stream:hook("stream/"..xmlns_sasl, handle_sasl);
380
0891b4e27766 Discard trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 360
diff changeset
79
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
80 return true;
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
81 end
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
82