mod_sasl2_bind2/mod_sasl2_bind2.lua
author Matthew Wild <mwild1@gmail.com>
Fri, 02 Sep 2022 16:22:11 +0100
changeset 5033 56b9f0b1409f
child 5035 62cdd8170563
permissions -rw-r--r--
mod_sasl2_bind: Support for Bind 2.0 with SASL2 This is based on an experimental in-progress derivative of the current XEP-0386.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5033
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     1
local base64 = require "util.encodings".base64;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     2
local sha1 = require "util.hashes".sha1;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     3
local st = require "util.stanza";
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     4
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     5
local sm_bind_resource = require "core.sessionmanager".bind_resource;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     6
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     7
local xmlns_bind2 = "urn:xmpp:bind2:1";
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
local xmlns_sasl2 = "urn:xmpp:sasl2:1";
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     9
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    10
-- Advertise what we can do
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    11
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    12
module:hook("stream-features", function(event)
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    13
	local origin, features = event.origin, event.features;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    14
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    15
	if origin.type ~= "c2s_unauthed" then
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    16
		return;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    17
	end
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    18
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    19
	local inline = st.stanza("inline", { xmlns = xmlns_bind2 });
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    20
	module:fire_event("advertise-bind-features", { origin = origin, features = inline });
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    21
	features:add_direct_child(inline);
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    22
end, 1);
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    23
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    24
module:hook("advertise-sasl-features", function(event)
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    25
	event.features:tag("bind", { xmlns = xmlns_bind2 }):up();
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    26
end, 1);
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    27
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    28
-- Helper to actually bind a resource to a session
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    29
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    30
local function do_bind(session, bind_request)
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    31
	local resource;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    32
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    33
	local client_id_tag = bind_request:get_child("client-id");
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    34
	local client_id = client_id_tag and client_id_tag:text() or session.client_id;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    35
	if client_id and client_id ~= "" then
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    36
		local tag = client_id_tag and client_id_tag.attr.tag or "client";
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    37
		resource = ("%s~%s"):format(tag, base64.encode(sha1(client_id):sub(1, 9)));
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    38
	end
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    39
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    40
	local success, err_type, err, err_msg = sm_bind_resource(session, resource);
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    41
	if not success then
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    42
		session.log("debug", "Resource bind failed: %s", err_msg or err);
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    43
		return nil, { type = err_type, condition = err, text = err_msg };
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    44
	end
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    45
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    46
	session.log("debug", "Resource bound: %s", session.full_jid);
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    47
	return st.stanza("bound", { xmlns = xmlns_bind2 })
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    48
		:text_tag("jid", session.full_jid)
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    49
end
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    50
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    51
-- Enable inline features requested by the client
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    52
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    53
local function enable_features(session, bind_request, bind_result)
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    54
	local features = bind_request:get_child("features");
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    55
	if not features then return; end
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    56
	module:fire_event("process-bind-features", {
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    57
		session = session;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    58
		features = features;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    59
		result = bind_result;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    60
	});
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    61
end
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    62
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    63
-- SASL 2 integration
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    64
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    65
module:hook_tag(xmlns_sasl2, "authenticate", function (session, auth)
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    66
	-- Cache action for future processing (after auth success)
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    67
	session.sasl2_bind_request = auth:child_with_ns(xmlns_bind2);
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    68
end, 100);
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    69
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    70
module:hook("sasl2/c2s/success", function (event)
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    71
	local session = event.session;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    72
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    73
	local bind_request = session.sasl2_bind_request;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    74
	if not bind_request then return; end -- No bind requested
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    75
	session.sasl2_bind_request = nil;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    76
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    77
	local sm_success = event.sasl2_sm_success;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    78
	if sm_success and sm_success.type == "resumed" then
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    79
		return; -- No need to bind a resource
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    80
	end
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    81
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    82
	local bind_result, err = do_bind(session, bind_request);
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    83
	if not bind_result then
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    84
		bind_result = st.stanza("failed", { xmlns = xmlns_bind2 })
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    85
			:add_error(err);
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    86
	else
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    87
		enable_features(session, bind_request, bind_result);
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    88
	end
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    89
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    90
	event.success:add_child(bind_result);
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    91
end, 100);
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    92
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    93
-- Inline features
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    94
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    95
module:hook("advertise-bind-features", function (event)
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    96
	local features = event.features;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    97
	features:tag("feature", { var = "urn:xmpp:carbons:2" }):up();
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    98
	features:tag("feature", { var = "urn:xmpp:csi:0" }):up();
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    99
end);
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   100
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   101
module:hook("enable-bind-features", function (event)
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   102
	local session, features = event.session, event.features;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   103
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   104
	-- Carbons
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   105
	session.want_carbons = not not features:get_child("enable", "urn:xmpp:carbons:2");
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   106
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   107
	-- CSI
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   108
	local csi_state_tag = features:child_with_ns("urn:xmpp:csi:0");
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   109
	if csi_state_tag then
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   110
		session.state = csi_state_tag.name;
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   111
	end
56b9f0b1409f mod_sasl2_bind: Support for Bind 2.0 with SASL2
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   112
end, 10);