File

plugins/mod_admin_socket.lua @ 12694:26a004c96ef8

util.paseto: Implementation of PASETO v4.public tokens PASETO provides an alternative to JWT with the promise of fewer implementation pitfalls. The v4.public algorithm allows asymmetric cryptographically-verified token issuance and validation. In summary, such tokens can be issued by one party and securely verified by any other party independently using the public key of the issuer. This has a number of potential applications in a decentralized network and ecosystem such as XMPP. For example, such tokens could be combined with XEP-0317 to allow hats to be verified even in the context of a third-party MUC service.
author Matthew Wild <mwild1@gmail.com>
date Fri, 24 Jun 2022 17:03:28 +0100
parent 12418:dd47adf74e93
child 12852:c35afa353f8f
child 12887:68df46926c26
line wrap: on
line source

module:set_global();

local have_unix, unix = pcall(require, "socket.unix");

if have_unix and type(unix) == "function" then
	-- COMPAT #1717
	-- Before the introduction of datagram support, only the stream socket
	-- constructor was exported instead of a module table. Due to the lack of a
	-- proper release of LuaSocket, distros have settled on shipping either the
	-- last RC tag or some commit since then.
	-- Here we accomodate both variants.
	unix = { stream = unix };
end
if not have_unix or type(unix) ~= "table" then
	module:log_status("error", "LuaSocket unix socket support not available or incompatible, ensure it is up to date");
	return;
end

local server = require "net.server";

local adminstream = require "util.adminstream";

local socket_path = module:get_option_path("admin_socket", "prosody.sock", "data");

local sessions = module:shared("sessions");

local function fire_admin_event(session, stanza)
	local event_data = {
		origin = session, stanza = stanza;
	};
	local event_name;
	if stanza.attr.xmlns then
		event_name = "admin/"..stanza.attr.xmlns..":"..stanza.name;
	else
		event_name = "admin/"..stanza.name;
	end
	module:log("debug", "Firing %s", event_name);
	return module:fire_event(event_name, event_data);
end

module:hook("server-stopping", function ()
	for _, session in pairs(sessions) do
		session:close("system-shutdown");
	end
	os.remove(socket_path);
end);

--- Unix domain socket management

local conn, sock;

local listeners = adminstream.server(sessions, fire_admin_event).listeners;

local function accept_connection()
	module:log("debug", "accepting...");
	local client = sock:accept();
	if not client then return; end
	server.wrapclient(client, "unix", 0, listeners, "*a");
end

function module.load()
	sock = unix.stream();
	sock:settimeout(0);
	os.remove(socket_path);
	local ok, err = sock:bind(socket_path);
	if not ok then
		module:log_status("error", "Unable to bind admin socket %s: %s", socket_path, err);
		return;
	end
	local ok, err = sock:listen();
	if not ok then
		module:log_status("error", "Unable to listen on admin socket %s: %s", socket_path, err);
		return;
	end
	if server.wrapserver then
		conn = server.wrapserver(sock, socket_path, 0, listeners);
	else
		conn = server.watchfd(sock:getfd(), accept_connection);
	end
end

function module.unload()
	if conn then
		conn:close();
	end
	if sock then
		sock:close();
	end
	os.remove(socket_path);
end