forked from Mirrorlandia_minetest/minetest
Refactor trusted mod checking code
This commit is contained in:
parent
f405459548
commit
b2409b14d0
@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
@ -604,6 +605,38 @@ bool ScriptApiSecurity::checkPath(lua_State *L, const char *path,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ScriptApiSecurity::checkWhitelisted(lua_State *L, const std::string &setting)
|
||||||
|
{
|
||||||
|
assert(str_starts_with(setting, "secure."));
|
||||||
|
|
||||||
|
// We have to make sure that this function is being called directly by
|
||||||
|
// a mod, otherwise a malicious mod could override this function and
|
||||||
|
// steal its return value.
|
||||||
|
lua_Debug info;
|
||||||
|
|
||||||
|
// Make sure there's only one item below this function on the stack...
|
||||||
|
if (lua_getstack(L, 2, &info))
|
||||||
|
return false;
|
||||||
|
FATAL_ERROR_IF(!lua_getstack(L, 1, &info), "lua_getstack() failed");
|
||||||
|
FATAL_ERROR_IF(!lua_getinfo(L, "S", &info), "lua_getinfo() failed");
|
||||||
|
|
||||||
|
// ...and that that item is the main file scope.
|
||||||
|
if (strcmp(info.what, "main") != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Mod must be listed in secure.http_mods or secure.trusted_mods
|
||||||
|
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
|
||||||
|
if (!lua_isstring(L, -1))
|
||||||
|
return false;
|
||||||
|
std::string mod_name = readParam<std::string>(L, -1);
|
||||||
|
|
||||||
|
std::string value = g_settings->get(setting);
|
||||||
|
value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
|
||||||
|
auto mod_list = str_split(value, ',');
|
||||||
|
|
||||||
|
return CONTAINS(mod_list, mod_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int ScriptApiSecurity::sl_g_dofile(lua_State *L)
|
int ScriptApiSecurity::sl_g_dofile(lua_State *L)
|
||||||
{
|
{
|
||||||
|
@ -40,11 +40,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
class ScriptApiSecurity : virtual public ScriptApiBase
|
class ScriptApiSecurity : virtual public ScriptApiBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int getThread(lua_State *L);
|
|
||||||
// creates an empty Lua environment
|
|
||||||
void createEmptyEnv(lua_State *L);
|
|
||||||
// sets the enviroment to the table thats on top of the stack
|
|
||||||
void setLuaEnv(lua_State *L, int thread);
|
|
||||||
// Sets up security on the ScriptApi's Lua state
|
// Sets up security on the ScriptApi's Lua state
|
||||||
void initializeSecurity();
|
void initializeSecurity();
|
||||||
void initializeSecurityClient();
|
void initializeSecurityClient();
|
||||||
@ -57,8 +52,17 @@ public:
|
|||||||
// Checks if mods are allowed to read (and optionally write) to the path
|
// Checks if mods are allowed to read (and optionally write) to the path
|
||||||
static bool checkPath(lua_State *L, const char *path, bool write_required,
|
static bool checkPath(lua_State *L, const char *path, bool write_required,
|
||||||
bool *write_allowed=NULL);
|
bool *write_allowed=NULL);
|
||||||
|
// Check if mod is whitelisted in the given setting
|
||||||
|
// This additionally checks that the mod's main file scope is executing.
|
||||||
|
static bool checkWhitelisted(lua_State *L, const std::string &setting);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int getThread(lua_State *L);
|
||||||
|
// sets the enviroment to the table thats on top of the stack
|
||||||
|
void setLuaEnv(lua_State *L, int thread);
|
||||||
|
// creates an empty Lua environment
|
||||||
|
void createEmptyEnv(lua_State *L);
|
||||||
|
|
||||||
// Syntax: "sl_" <Library name or 'g' (global)> '_' <Function name>
|
// Syntax: "sl_" <Library name or 'g' (global)> '_' <Function name>
|
||||||
// (sl stands for Secure Lua)
|
// (sl stands for Secure Lua)
|
||||||
|
|
||||||
|
@ -21,14 +21,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "common/c_converter.h"
|
#include "common/c_converter.h"
|
||||||
#include "common/c_content.h"
|
#include "common/c_content.h"
|
||||||
#include "lua_api/l_http.h"
|
#include "lua_api/l_http.h"
|
||||||
|
#include "cpp_api/s_security.h"
|
||||||
#include "httpfetch.h"
|
#include "httpfetch.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <cctype>
|
|
||||||
|
|
||||||
#define HTTP_API(name) \
|
#define HTTP_API(name) \
|
||||||
lua_pushstring(L, #name); \
|
lua_pushstring(L, #name); \
|
||||||
@ -181,40 +180,8 @@ int ModApiHttp::l_request_http_api(lua_State *L)
|
|||||||
{
|
{
|
||||||
NO_MAP_LOCK_REQUIRED;
|
NO_MAP_LOCK_REQUIRED;
|
||||||
|
|
||||||
// We have to make sure that this function is being called directly by
|
if (!ScriptApiSecurity::checkWhitelisted(L, "secure.http_mods") &&
|
||||||
// a mod, otherwise a malicious mod could override this function and
|
!ScriptApiSecurity::checkWhitelisted(L, "secure.trusted_mods")) {
|
||||||
// steal its return value.
|
|
||||||
lua_Debug info;
|
|
||||||
|
|
||||||
// Make sure there's only one item below this function on the stack...
|
|
||||||
if (lua_getstack(L, 2, &info)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
FATAL_ERROR_IF(!lua_getstack(L, 1, &info), "lua_getstack() failed");
|
|
||||||
FATAL_ERROR_IF(!lua_getinfo(L, "S", &info), "lua_getinfo() failed");
|
|
||||||
|
|
||||||
// ...and that that item is the main file scope.
|
|
||||||
if (strcmp(info.what, "main") != 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mod must be listed in secure.http_mods or secure.trusted_mods
|
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
|
|
||||||
if (!lua_isstring(L, -1)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string mod_name = readParam<std::string>(L, -1);
|
|
||||||
std::string http_mods = g_settings->get("secure.http_mods");
|
|
||||||
http_mods.erase(std::remove(http_mods.begin(), http_mods.end(), ' '), http_mods.end());
|
|
||||||
std::vector<std::string> mod_list_http = str_split(http_mods, ',');
|
|
||||||
|
|
||||||
std::string trusted_mods = g_settings->get("secure.trusted_mods");
|
|
||||||
trusted_mods.erase(std::remove(trusted_mods.begin(), trusted_mods.end(), ' '), trusted_mods.end());
|
|
||||||
std::vector<std::string> mod_list_trusted = str_split(trusted_mods, ',');
|
|
||||||
|
|
||||||
mod_list_http.insert(mod_list_http.end(), mod_list_trusted.begin(), mod_list_trusted.end());
|
|
||||||
if (std::find(mod_list_http.begin(), mod_list_http.end(), mod_name) == mod_list_http.end()) {
|
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "util/hex.h"
|
#include "util/hex.h"
|
||||||
#include "util/sha1.h"
|
#include "util/sha1.h"
|
||||||
#include "util/png.h"
|
#include "util/png.h"
|
||||||
#include <algorithm>
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
// log([level,] text)
|
// log([level,] text)
|
||||||
@ -444,36 +443,7 @@ int ModApiUtil::l_request_insecure_environment(lua_State *L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to make sure that this function is being called directly by
|
if (!ScriptApiSecurity::checkWhitelisted(L, "secure.trusted_mods")) {
|
||||||
// a mod, otherwise a malicious mod could override this function and
|
|
||||||
// steal its return value.
|
|
||||||
lua_Debug info;
|
|
||||||
// Make sure there's only one item below this function on the stack...
|
|
||||||
if (lua_getstack(L, 2, &info)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
FATAL_ERROR_IF(!lua_getstack(L, 1, &info), "lua_getstack() failed");
|
|
||||||
FATAL_ERROR_IF(!lua_getinfo(L, "S", &info), "lua_getinfo() failed");
|
|
||||||
// ...and that that item is the main file scope.
|
|
||||||
if (strcmp(info.what, "main") != 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mod name
|
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
|
|
||||||
if (!lua_isstring(L, -1)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check secure.trusted_mods
|
|
||||||
std::string mod_name = readParam<std::string>(L, -1);
|
|
||||||
std::string trusted_mods = g_settings->get("secure.trusted_mods");
|
|
||||||
trusted_mods.erase(std::remove_if(trusted_mods.begin(),
|
|
||||||
trusted_mods.end(), static_cast<int(*)(int)>(&std::isspace)),
|
|
||||||
trusted_mods.end());
|
|
||||||
std::vector<std::string> mod_list = str_split(trusted_mods, ',');
|
|
||||||
if (std::find(mod_list.begin(), mod_list.end(), mod_name) ==
|
|
||||||
mod_list.end()) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user