Add new runas mod

This commit is contained in:
Aaron Suen 2023-06-10 14:24:14 -04:00
parent bd5473c3b0
commit 9c1dcb41c7
5 changed files with 105 additions and 5 deletions

View File

@ -25,6 +25,7 @@ Each mod in the pack is effectively independent, with minimal or no dependencies
- `szutil_restart`: Externally-triggerable server restarts with countdown/warnings.
- `szutil_revokeme`: Fixes missing /revokeme admin command.
- `szutil_roles`: Manage privs via special privs that represent groups of other privs.
- `szutil_runas`: Run a command as another user with password auth.
- `szutil_stealth`: Make a player as close to completely invisble to players as possible, for moderation or spectation use.
- `szutil_suadmin`: Change admin access to be based on a /su (password) command, instead of by player name.
- `szutil_telecode`: Teleportation by opaque codes that can be shared, saved, and published.

5
TODO
View File

@ -62,11 +62,6 @@
- Make sure we can't create infinite alias loops
- Allow meta-aliases but only up to a certain depth?
- Run-command-as-user command
- /runas <user> <password> <command>
- spaces in password can be escaped with \
- can use to build a web moderator console
- /lua mod w/ specific priv
- Add zoom, aux control support to controlhud

24
szutil_runas/README Normal file
View File

@ -0,0 +1,24 @@
------------------------------------------------------------------------
WARNING: Chat commands (including the runas password) are transmitted
over the wire in plaintext and can be read by MITM or passive listeners.
Using normal player login (which uses Secure Remote Passwords) or
using szutil_consocket over SSH is safer.
This mod allows a user to "log in as" another user, using their
password, assuming their identity, privileges, and other limitations,
and executing a command as them. This is ideally meant to be used with
szutil_consocket, to allow e.g. attaching a web interface to allow
non-full-admin moderators to issue moderation commands via web when
they cannot access the game directly.
The "/runas" command takes parameters:
- the user to run as (no spaces allowed)
- that user's password (escape spaces with a backslash)
- the command to run (spaces allowed)
This mod only supports slash-commands, and will add a slash to the
beginning of any command missing one; it does not allow chat
impersonation (unless another mod adds a command for that).
------------------------------------------------------------------------

79
szutil_runas/init.lua Normal file
View File

@ -0,0 +1,79 @@
-- LUALOCALS < ---------------------------------------------------------
local ipairs, minetest, pcall, string, table
= ipairs, minetest, pcall, string, table
local string_sub, table_concat
= string.sub, table.concat
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
minetest.register_privilege(modname, {
description = "User may use the runas command",
give_to_admin = true,
give_to_singleplayer = false
})
minetest.register_privilege(modname .. "_protect", {
description = "No other users may run a command as this user",
give_to_admin = true,
give_to_singleplayer = false
})
-- Duplicate command reponses to the user actually issuing
-- the command, during the command's runtime.
local msgdupe
do
local old_chatsend = minetest.chat_send_player
function minetest.chat_send_player(who, text, ...)
if msgdupe and who == msgdupe.from then
old_chatsend(msgdupe.to, text, ...)
end
return old_chatsend(who, text, ...)
end
end
local function runas_core(runner, runee, password, command)
if not minetest.check_player_privs(runner, modname)
or minetest.check_player_privs(runee, modname .. "_protect")
then return false, "access denied" end
local authdata = minetest.get_auth_handler().get_auth(runee)
if not (authdata and authdata.password
and minetest.check_password_entry(runee, authdata.password, password))
then return false, "access denied" end
if string_sub(command, 1, 1) ~= "/" then command = "/" .. command end
msgdupe = {from = runee, to = runner}
for _, v in ipairs(minetest.registered_on_chat_messages) do
local ok, err = pcall(function() return v(runee, command) end)
if ok and err then return end
if not ok then
return minetest.chat_send_player(runee, err)
end
end
minetest.chat_send_player(runee, "unrecognized command")
end
minetest.register_chatcommand("runas", {
description = "Run a command as another user",
params = "<user> <password> <command> [params...]",
privs = {[modname] = true},
func = function(name, params)
params = params:split(" ")
local passwd = {}
for i = 2, #params do
if string_sub(params[i], -1) ~= "\\" then
passwd[#passwd + 1] = params[i]
local cmd = {}
for j = i + 1, #params do
cmd[#cmd + 1] = params[j]
end
return runas_core(name, params[1],
table_concat(passwd, " "),
table_concat(cmd, " "))
end
passwd[#passwd + 1] = string_sub(params[i], 1, -2)
end
return false, "syntax error"
end
})

1
szutil_runas/mod.conf Normal file
View File

@ -0,0 +1 @@
name = szutil_runas