priv revoke overhaul

This commit is contained in:
BuckarooBanzay 2023-02-02 14:25:16 +01:00
parent 4cf38c997d
commit 0b6fc9269f
6 changed files with 84 additions and 61 deletions

View file

@ -1,5 +1,8 @@
globals = {
"otp"
"otp",
"minetest" = {
"registered_privileges"
}
}
read_globals = {

View file

@ -18,6 +18,7 @@ dofile(MP.."/functions.lua")
dofile(MP.."/onboard.lua")
dofile(MP.."/join.lua")
dofile(MP.."/privs.lua")
dofile(MP.."/priv_revoke.lua")
if minetest.get_modpath("mtt") and mtt.enabled then
dofile(MP.."/functions.spec.lua")

View file

@ -6,62 +6,6 @@ local otp_time = 300
-- playername => start_time
local otp_sessions = {}
-- privs to revoke until the verification code is validated
local temp_revoke_privs = {
-- builtin
"interact",
"shout",
"privs",
"basic_privs",
"server",
"ban",
"kick",
"settime",
"password",
"protection_bypass",
-- we
"worldedit",
-- areas
"areas"
}
-- moves all "temp_revoke_privs" to mod-storage
local function revoke_privs(playername)
local privs = minetest.get_player_privs(playername)
if otp.storage:get_string(playername .. "_privs") == "" then
local moved_privs = {}
for _, priv_name in ipairs(temp_revoke_privs) do
if privs[priv_name] then
privs[priv_name] = nil
moved_privs[priv_name] = true
end
end
minetest.log("action", "[otp] revoking privs of '" .. playername .. "' list: " .. dump(moved_privs))
minetest.set_player_privs(playername, privs)
otp.storage:set_string(playername .. "_privs", minetest.serialize(moved_privs))
end
end
-- moves all privs from mod-storage into the live privs
local function regrant_privs(playername)
local stored_priv_str = otp.storage:get_string(playername .. "_privs")
if stored_priv_str ~= "" then
local privs = minetest.get_player_privs(playername)
local stored_privs = minetest.deserialize(stored_priv_str)
-- merge stored privs into existing table
for priv_name in pairs(stored_privs) do
privs[priv_name] = true
end
minetest.log("action", "[otp] regranting privs of '" .. playername .. "' list: " .. dump(stored_privs))
minetest.set_player_privs(playername, privs)
otp.storage:set_string(playername .. "_privs", "")
end
end
-- Code formspec on join for otp enabled players
minetest.register_on_joinplayer(function(player)
local playername = player:get_player_name()
@ -72,7 +16,7 @@ minetest.register_on_joinplayer(function(player)
otp_sessions[player:get_player_name()] = os.time()
-- revoke important privs and re-grant again on code-verification
revoke_privs(playername)
otp.revoke_privs(playername)
-- send verification formspec
local formspec = "size[10,2]" ..
@ -115,8 +59,9 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if expected_code == fields.code then
minetest.chat_send_player(playername, "OTP Code validation succeeded")
otp_sessions[playername] = nil
regrant_privs(playername)
otp.regrant_privs(playername)
else
minetest.kick_player(playername, "OTP Code validation failed")
otp.regrant_privs(playername)
end
end)

58
priv_revoke.lua Normal file
View file

@ -0,0 +1,58 @@
-- privs to revoke until the verification code is validated
local temp_revoke_privs = {}
-- mark player health-related privs as "otp_keep" (they don't get removed while entering the otp code)
for _, name in ipairs({"fly", "noclip"}) do
local priv_def = minetest.registered_privileges[name]
if priv_def then
priv_def.otp_keep = true
end
end
minetest.register_on_mods_loaded(function()
-- collect all privs to revoke while entering the otp code
for name, priv_def in pairs(minetest.registered_privileges) do
if not priv_def.otp_keep then
-- not marked explicitly as "keep"
table.insert(temp_revoke_privs, name)
end
end
end)
-- moves all "temp_revoke_privs" to mod-storage
function otp.revoke_privs(playername)
local privs = minetest.get_player_privs(playername)
if otp.storage:get_string(playername .. "_privs") == "" then
local moved_privs = {}
for _, priv_name in ipairs(temp_revoke_privs) do
if privs[priv_name] then
privs[priv_name] = nil
moved_privs[priv_name] = true
end
end
minetest.log("action", "[otp] revoking privs of '" .. playername .. "' list: " .. dump(moved_privs))
minetest.set_player_privs(playername, privs)
otp.storage:set_string(playername .. "_privs", minetest.serialize(moved_privs))
end
end
-- moves all privs from mod-storage into the live privs
function otp.regrant_privs(playername)
local stored_priv_str = otp.storage:get_string(playername .. "_privs")
if stored_priv_str ~= "" then
local privs = minetest.get_player_privs(playername)
local stored_privs = minetest.deserialize(stored_priv_str)
-- merge stored privs into existing table
for priv_name in pairs(stored_privs) do
privs[priv_name] = true
end
minetest.log("action", "[otp] regranting privs of '" .. playername .. "' list: " .. dump(stored_privs))
minetest.set_player_privs(playername, privs)
otp.storage:set_string(playername .. "_privs", "")
end
end

View file

@ -1,5 +1,6 @@
minetest.register_privilege("otp_enabled", {
description = "otp enabled player",
give_to_singleplayer = false
})
give_to_singleplayer = false,
otp_keep = true
})

View file

@ -22,6 +22,21 @@ OTP verification form
OTP Setup form
![](./screenshot2.png)
# Temporary privilege revocation
All of the privileges get revoked when logging in with the otp enabled (until the proper code is entered).
Some exceptions:
* `fly` (otherwise the player would literally fall from the sky)
* `noclip`
To disable revokation on custom privs the field `otp_keep` can be set to true on the definition:
```lua
minetest.register_privilege("my_super_important_priv", {
description = "something something",
otp_keep = true
})
```
# Links / References
* https://en.wikipedia.org/wiki/Time-based_one-time_password