# HG changeset patch # User Matthew Wild # Date 1662132151 -3600 # Node ID 3e79876d135bee491709ec269e42cedd8fb2fea7 # Parent 56b9f0b1409f867e5e58191eb52d4848c88a5c52 mod_sasl2_sm: Integration with mod_sasl2_bind2 diff -r 56b9f0b1409f -r 3e79876d135b mod_sasl2_sm/mod_sasl2_sm.lua --- a/mod_sasl2_sm/mod_sasl2_sm.lua Fri Sep 02 16:22:11 2022 +0100 +++ b/mod_sasl2_sm/mod_sasl2_sm.lua Fri Sep 02 16:22:31 2022 +0100 @@ -5,70 +5,88 @@ local xmlns_sasl2 = "urn:xmpp:sasl:1"; local xmlns_sm = "urn:xmpp:sm:3"; -module:hook("stream-features", function (event) - if event.origin.type ~= "c2s_unauthed" then return; end +-- Advertise what we can do + +module:hook("advertise-sasl-features", function (event) local features = event.features; - local inline = features:get_child("inline", xmlns_sasl2); - if not inline then - inline = st.stanza("inline", { xmlns = xmlns_sasl2 }); - features:add_child(inline); - end - inline:tag("sm", { xmlns = xmlns_sm }):up(); + features:tag("sm", { xmlns = xmlns_sm }):up(); +end); + +module:hook("advertise-bind-features", function (event) + local features = event.features; + features:tag("feature", { var = xmlns_sm }):up(); end); module:hook_tag(xmlns_sasl2, "authenticate", function (session, auth) -- Cache action for future processing (after auth success) - session.sasl2_sm_action = auth:child_with_ns(xmlns_sm); + session.sasl2_sm_request = auth:child_with_ns(xmlns_sm); end, 100); +-- SASL 2 integration (for resume) + module:hook("sasl2/c2s/success", function (event) local session = event.session; - local sm_action = session.sasl2_sm_action; - if not sm_action then return; end - session.sasl2_sm_action = nil; + local sm_request = session.sasl2_sm_request; + if not sm_request then return; end + session.sasl2_sm_request = nil; local sm_result; - if sm_action.name == "resume" then - local resumed, err = mod_smacks.do_resume(session, sm_action); - if not resumed then - local h = err.context and err.context.h; - sm_result = st.stanza("failed", { xmlns = xmlns_sm, h = h and ("%d"):format(h) or nil }) - :add_error(err); - else - event.session = resumed.session; -- Update to resumed session - event.sasl2_sm_finish = resumed.finish; -- To be called after sending final SASL response - sm_result = st.stanza("resumed", { xmlns = xmlns_sm, - h = ("%d"):format(event.session.handled_stanza_count); - previd = resumed.id; }); - end - elseif sm_action.name == "enable" then - local enabled, err = mod_smacks.do_enable(session, sm_action); - if not enabled then - sm_result = st.stanza("failed", { xmlns = xmlns_sm }) - :add_error(err); - else - event.sasl2_sm_finish = enabled.finish; -- To be called after sending final SASL response - sm_result = st.stanze("enabled", { - xmlns = xmlns_sm; - id = enabled.id; - resume = enabled.id and "1" or nil; - max = enabled.resume_max; - }); - end + if sm_request.name ~= "resume" then return; end + + local resumed, err = mod_smacks.do_resume(session, sm_request); + if not resumed then + local h = err.context and err.context.h; + sm_result = st.stanza("failed", { xmlns = xmlns_sm, h = h and ("%d"):format(h) or nil }) + :add_error(err); + else + event.session = resumed.session; -- Update to resumed session + event.sasl2_sm_success = resumed; -- To be called after sending final SASL response + sm_result = st.stanza("resumed", { xmlns = xmlns_sm, + h = ("%d"):format(event.session.handled_stanza_count); + previd = resumed.id; }); end + if sm_result then event.success:add_child(sm_result); end +end, 110); + +-- Bind 2 integration (for enable) + +module:hook("advertise-bind-features", function (event) + event.features:tag("feature", { var = xmlns_sm }):up(); +end); + +module:hook("enable-bind-features", function (event) + local sm_enable = event.features:get_child("enable", xmlns_sm); + if not sm_enable then return; end + + local sm_result; + local enabled, err = mod_smacks.do_enable(event.session, sm_enable); + if not enabled then + sm_result = st.stanza("failed", { xmlns = xmlns_sm }) + :add_error(err); + else + event.sasl2_sm_success = enabled; -- To be called after sending final SASL response + sm_result = st.stanze("enabled", { + xmlns = xmlns_sm; + id = enabled.id; + resume = enabled.id and "1" or nil; + max = enabled.resume_max; + }); + end + event.bind_result:add_child(sm_result); end, 100); +-- Finish and/or clean up after SASL 2 completed + module:hook("sasl2/c2s/success", function (event) -- The authenticate response has already been sent at this point - local finish = event.sasl2_sm_finish; - if finish then - finish(); -- Finish resume and sync stanzas + local success = event.sasl2_sm_success; + if success then + success.finish(); -- Finish enable/resume and sync stanzas end end, -1100); module:hook("sasl2/c2s/failure", function (event) - event.session.sasl2_sm_action = nil; + event.session.sasl2_sm_request = nil; end); -