plugins/mod_tombstones.lua
author Kim Alvefur <zash@zash.se>
Thu, 23 Dec 2021 14:08:20 +0100
changeset 12119 94de6b7596cc
child 12121 0c9b64178eda
permissions -rw-r--r--
mod_tombstones: Remember deleted accounts #1307 Presence subscriptions are normally revoked on account deletion, which informs the contact. Sometimes this notification gets lost e.g. due to s2s problems. The accounts JID may also be present e.g. in MUC affiliations, chat group member lists, pubsub subscriptions or other systems. These may grant privileges which would fall to someone who creates the same account again, which this module is meant to prevent.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
12119
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     1
-- TODO warn when trying to create an user before the tombstone expires
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     2
-- e.g. via telnet or other admin interface
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     3
local datetime = require "util.datetime";
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     4
local errors = require "util.error";
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     5
local jid_split = require"util.jid".split;
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     6
local st = require "util.stanza";
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     7
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     8
-- Using a map store as key-value store so that removal of all user data
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     9
-- does not also remove the tombstone, which would defeat the point
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    10
local graveyard = module:open_store(nil, "map");
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    11
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    12
local ttl = module:get_option_number("user_tombstone_expiry", nil);
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    13
-- Keep tombstones forever by default
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    14
--
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    15
-- Rationale:
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    16
-- There is no way to be completely sure when remote services have
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    17
-- forgotten and revoked all memberships.
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    18
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    19
module:hook_global("user-deleted", function(event)
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    20
	if event.host == module.host then
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    21
		local ok, err = graveyard:set(nil, event.username, os.time());
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    22
		if not ok then module:log("error", "Could store tombstone for %s: %s", event.username, err); end
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    23
	end
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    24
end);
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    25
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    26
-- Public API
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    27
function has_tombstone(username)
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    28
	local tombstone, err = graveyard:get(nil, username);
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    29
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    30
	if err or not tombstone then return tombstone, err; end
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    31
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    32
	if ttl and tombstone + ttl < os.time() then
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    33
		module:log("debug", "Tombstone for %s created at %s has expired", username, datetime.datetime(tombstone));
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    34
		graveyard:set(nil, username, nil);
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    35
		return nil;
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    36
	end
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    37
	return tombstone;
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    38
end
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    39
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    40
module:hook("user-registering", function(event)
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    41
	local tombstone, err = has_tombstone(event.username);
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    42
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    43
	if err then
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    44
		event.allowed, event.error = errors.coerce(false, err);
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    45
		return true;
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    46
	elseif not tombstone then
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    47
		-- Feel free
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    48
		return;
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    49
	end
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    50
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    51
	module:log("debug", "Tombstone for %s created at %s", event.username, datetime.datetime(tombstone));
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    52
	event.allowed = false;
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    53
	return true;
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    54
end);
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    55
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    56
module:hook("presence/bare", function(event)
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    57
	local origin, presence = event.origin, event.stanza;
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    58
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    59
	-- We want to undo any left-over presence subscriptions and notify the former
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    60
	-- contact that they're gone.
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    61
	--
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    62
	-- FIXME This leaks that the user once existed. Hard to avoid without keeping
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    63
	-- the contact list in some form, which we don't want to do for privacy
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    64
	-- reasons.  Bloom filter perhaps?
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    65
	if has_tombstone(jid_split(presence.attr.to)) then
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    66
		if presence.attr.type == "probe" then
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    67
			origin.send(st.error_reply(presence, "cancel", "gone", "User deleted"));
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    68
			origin.send(st.presence({ type = "unsubscribed"; to = presence.attr.from; from = presence.attr.to }));
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    69
		elseif presence.attr.type == nil or presence.attr.type == "unavailable" then
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    70
			origin.send(st.error_reply(presence, "cancel", "gone", "User deleted"));
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    71
			origin.send(st.presence({ type = "unsubscribe"; to = presence.attr.from; from = presence.attr.to }));
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    72
		end
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    73
		return true;
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    74
	end
94de6b7596cc mod_tombstones: Remember deleted accounts #1307
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    75
end, 1);