comparison mod_sasl2_sm/mod_sasl2_sm.lua @ 5030:3e79876d135b

mod_sasl2_sm: Integration with mod_sasl2_bind2
author Matthew Wild <mwild1@gmail.com>
date Fri, 02 Sep 2022 16:22:31 +0100
parents 8b9ab351dd78
children f7eaf73b8f30
comparison
equal deleted inserted replaced
5029:56b9f0b1409f 5030:3e79876d135b
3 local mod_smacks = module:depends("smacks"); 3 local mod_smacks = module:depends("smacks");
4 4
5 local xmlns_sasl2 = "urn:xmpp:sasl:1"; 5 local xmlns_sasl2 = "urn:xmpp:sasl:1";
6 local xmlns_sm = "urn:xmpp:sm:3"; 6 local xmlns_sm = "urn:xmpp:sm:3";
7 7
8 module:hook("stream-features", function (event) 8 -- Advertise what we can do
9 if event.origin.type ~= "c2s_unauthed" then return; end 9
10 module:hook("advertise-sasl-features", function (event)
10 local features = event.features; 11 local features = event.features;
11 local inline = features:get_child("inline", xmlns_sasl2); 12 features:tag("sm", { xmlns = xmlns_sm }):up();
12 if not inline then 13 end);
13 inline = st.stanza("inline", { xmlns = xmlns_sasl2 }); 14
14 features:add_child(inline); 15 module:hook("advertise-bind-features", function (event)
15 end 16 local features = event.features;
16 inline:tag("sm", { xmlns = xmlns_sm }):up(); 17 features:tag("feature", { var = xmlns_sm }):up();
17 end); 18 end);
18 19
19 module:hook_tag(xmlns_sasl2, "authenticate", function (session, auth) 20 module:hook_tag(xmlns_sasl2, "authenticate", function (session, auth)
20 -- Cache action for future processing (after auth success) 21 -- Cache action for future processing (after auth success)
21 session.sasl2_sm_action = auth:child_with_ns(xmlns_sm); 22 session.sasl2_sm_request = auth:child_with_ns(xmlns_sm);
22 end, 100); 23 end, 100);
24
25 -- SASL 2 integration (for resume)
23 26
24 module:hook("sasl2/c2s/success", function (event) 27 module:hook("sasl2/c2s/success", function (event)
25 local session = event.session; 28 local session = event.session;
26 local sm_action = session.sasl2_sm_action; 29 local sm_request = session.sasl2_sm_request;
27 if not sm_action then return; end 30 if not sm_request then return; end
28 session.sasl2_sm_action = nil; 31 session.sasl2_sm_request = nil;
29 local sm_result; 32 local sm_result;
30 if sm_action.name == "resume" then 33 if sm_request.name ~= "resume" then return; end
31 local resumed, err = mod_smacks.do_resume(session, sm_action); 34
32 if not resumed then 35 local resumed, err = mod_smacks.do_resume(session, sm_request);
33 local h = err.context and err.context.h; 36 if not resumed then
34 sm_result = st.stanza("failed", { xmlns = xmlns_sm, h = h and ("%d"):format(h) or nil }) 37 local h = err.context and err.context.h;
35 :add_error(err); 38 sm_result = st.stanza("failed", { xmlns = xmlns_sm, h = h and ("%d"):format(h) or nil })
36 else 39 :add_error(err);
37 event.session = resumed.session; -- Update to resumed session 40 else
38 event.sasl2_sm_finish = resumed.finish; -- To be called after sending final SASL response 41 event.session = resumed.session; -- Update to resumed session
39 sm_result = st.stanza("resumed", { xmlns = xmlns_sm, 42 event.sasl2_sm_success = resumed; -- To be called after sending final SASL response
40 h = ("%d"):format(event.session.handled_stanza_count); 43 sm_result = st.stanza("resumed", { xmlns = xmlns_sm,
41 previd = resumed.id; }); 44 h = ("%d"):format(event.session.handled_stanza_count);
42 end 45 previd = resumed.id; });
43 elseif sm_action.name == "enable" then
44 local enabled, err = mod_smacks.do_enable(session, sm_action);
45 if not enabled then
46 sm_result = st.stanza("failed", { xmlns = xmlns_sm })
47 :add_error(err);
48 else
49 event.sasl2_sm_finish = enabled.finish; -- To be called after sending final SASL response
50 sm_result = st.stanze("enabled", {
51 xmlns = xmlns_sm;
52 id = enabled.id;
53 resume = enabled.id and "1" or nil;
54 max = enabled.resume_max;
55 });
56 end
57 end 46 end
47
58 if sm_result then 48 if sm_result then
59 event.success:add_child(sm_result); 49 event.success:add_child(sm_result);
60 end 50 end
51 end, 110);
52
53 -- Bind 2 integration (for enable)
54
55 module:hook("advertise-bind-features", function (event)
56 event.features:tag("feature", { var = xmlns_sm }):up();
57 end);
58
59 module:hook("enable-bind-features", function (event)
60 local sm_enable = event.features:get_child("enable", xmlns_sm);
61 if not sm_enable then return; end
62
63 local sm_result;
64 local enabled, err = mod_smacks.do_enable(event.session, sm_enable);
65 if not enabled then
66 sm_result = st.stanza("failed", { xmlns = xmlns_sm })
67 :add_error(err);
68 else
69 event.sasl2_sm_success = enabled; -- To be called after sending final SASL response
70 sm_result = st.stanze("enabled", {
71 xmlns = xmlns_sm;
72 id = enabled.id;
73 resume = enabled.id and "1" or nil;
74 max = enabled.resume_max;
75 });
76 end
77 event.bind_result:add_child(sm_result);
61 end, 100); 78 end, 100);
79
80 -- Finish and/or clean up after SASL 2 completed
62 81
63 module:hook("sasl2/c2s/success", function (event) 82 module:hook("sasl2/c2s/success", function (event)
64 -- The authenticate response has already been sent at this point 83 -- The authenticate response has already been sent at this point
65 local finish = event.sasl2_sm_finish; 84 local success = event.sasl2_sm_success;
66 if finish then 85 if success then
67 finish(); -- Finish resume and sync stanzas 86 success.finish(); -- Finish enable/resume and sync stanzas
68 end 87 end
69 end, -1100); 88 end, -1100);
70 89
71 module:hook("sasl2/c2s/failure", function (event) 90 module:hook("sasl2/c2s/failure", function (event)
72 event.session.sasl2_sm_action = nil; 91 event.session.sasl2_sm_request = nil;
73 end); 92 end);
74