Wed, 13 Jan 2016 00:45:54 +0100
util.random: Use /dev/urandom or LuaCrypto
395 | 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 | 3 | local xmlns_sasl = "urn:ietf:params:xml:ns:xmpp-sasl"; |
4 | ||
5 | function verse.plugins.sasl(stream) | |
6 | local function handle_features(features_stanza) | |
7 | if stream.authenticated then return; end | |
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 |
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 | stream:event("authentication-failure", { condition = "no-supported-sasl-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
|
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 | 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 | 47 | end |
48 | stream:send(auth_stanza); | |
49 | return true; | |
50 | end | |
380 | 51 | |
8 | 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 | 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 | 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 | 72 | return true; |
73 | end | |
380 | 74 | |
8 | 75 | stream:hook("stream-features", handle_features, 300); |
76 | stream:hook("stream/"..xmlns_sasl, handle_sasl); | |
380 | 77 | |
8 | 78 | return true; |
79 | end | |
80 |