Annotate

plugins/sasl.lua @ 456:6a65142052c8

sasl: Include offered mechanisms in event when no supported mechanisms found This allows consumers of the event to determine what may be required in order to successfully authenticate.
author Matthew Wild <mwild1@gmail.com>
date Fri, 03 Mar 2023 12:10:54 +0000
parent 395:e86144a4eaa1
child 467:8e6a7a5e70b3
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 = {};
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
14
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 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
16 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
17 stream:debug("Server offers %s", 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
18 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
19 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
20 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
21 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
22 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
23 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
24 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
25 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
26 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
27 end
315
3742107e2505 plugins/sasl: Use ANONYMOUS authentication when no username provided
James Callahan <james@chatid.com>
parents: 302
diff changeset
28 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
29
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
30 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
31 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
32 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
33 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
34 if not supported[1] then
456
6a65142052c8 sasl: Include offered mechanisms in event when no supported mechanisms found
Matthew Wild <mwild1@gmail.com>
parents: 395
diff changeset
35 stream:event("authentication-failure", { condition = "no-supported-sasl-mechanisms", mechanisms = mechanisms });
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
36 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
37 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
38 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
39 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
40 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
41 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
42 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
43 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
44 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
45 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
46 auth_stanza:text(base64(initial_data));
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47 end
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 stream:send(auth_stanza);
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49 return true;
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50 end
380
0891b4e27766 Discard trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 360
diff changeset
51
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52 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
53 if sasl_stanza.name == "failure" then
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
54 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
55 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
56 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
57 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
58 return false;
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
59 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
60 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
61 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
62 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
63 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
64 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
65 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
66 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
67 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
68 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
69 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
70 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
71 end
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
72 return true;
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
73 end
380
0891b4e27766 Discard trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 360
diff changeset
74
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75 stream:hook("stream-features", handle_features, 300);
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
76 stream:hook("stream/"..xmlns_sasl, handle_sasl);
380
0891b4e27766 Discard trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 360
diff changeset
77
8
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
78 return true;
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
79 end
f2b55ba66e14 plugins.sasl: Add plugin
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
80