1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Implement script sandboxing for main menu

This commit is contained in:
sfan5 2024-11-03 16:53:01 +01:00
parent 1fd4e0b82d
commit ea4ae55e24
10 changed files with 146 additions and 126 deletions

View file

@ -343,6 +343,8 @@ int ModApiMainMenu::l_get_content_info(lua_State *L)
{
std::string path = luaL_checkstring(L, 1);
CHECK_SECURE_PATH(L, path.c_str(), false)
ContentSpec spec;
spec.path = path;
parseContentInfo(spec);
@ -410,6 +412,8 @@ int ModApiMainMenu::l_check_mod_configuration(lua_State *L)
{
std::string worldpath = luaL_checkstring(L, 1);
CHECK_SECURE_PATH(L, worldpath.c_str(), false)
ModConfiguration modmgr;
// Add all game mods
@ -732,15 +736,13 @@ int ModApiMainMenu::l_get_temp_path(lua_State *L)
}
/******************************************************************************/
int ModApiMainMenu::l_create_dir(lua_State *L) {
int ModApiMainMenu::l_create_dir(lua_State *L)
{
const char *path = luaL_checkstring(L, 1);
if (ModApiMainMenu::mayModifyPath(path)) {
lua_pushboolean(L, fs::CreateAllDirs(path));
return 1;
}
CHECK_SECURE_PATH(L, path, true)
lua_pushboolean(L, false);
lua_pushboolean(L, fs::CreateAllDirs(path));
return 1;
}
@ -749,14 +751,9 @@ int ModApiMainMenu::l_delete_dir(lua_State *L)
{
const char *path = luaL_checkstring(L, 1);
std::string absolute_path = fs::RemoveRelativePathComponents(path);
CHECK_SECURE_PATH(L, path, true)
if (ModApiMainMenu::mayModifyPath(absolute_path)) {
lua_pushboolean(L, fs::RecursiveDelete(absolute_path));
return 1;
}
lua_pushboolean(L, false);
lua_pushboolean(L, fs::RecursiveDelete(path));
return 1;
}
@ -766,24 +763,16 @@ int ModApiMainMenu::l_copy_dir(lua_State *L)
const char *source = luaL_checkstring(L, 1);
const char *destination = luaL_checkstring(L, 2);
bool keep_source = true;
if (!lua_isnoneornil(L, 3))
keep_source = readParam<bool>(L, 3);
bool keep_source = readParam<bool>(L, 3, true);
std::string abs_destination = fs::RemoveRelativePathComponents(destination);
std::string abs_source = fs::RemoveRelativePathComponents(source);
if (!ModApiMainMenu::mayModifyPath(abs_destination) ||
(!keep_source && !ModApiMainMenu::mayModifyPath(abs_source))) {
lua_pushboolean(L, false);
return 1;
}
CHECK_SECURE_PATH(L, source, !keep_source)
CHECK_SECURE_PATH(L, destination, true)
bool retval;
if (keep_source)
retval = fs::CopyDir(abs_source, abs_destination);
retval = fs::CopyDir(source, destination);
else
retval = fs::MoveDir(abs_source, abs_destination);
retval = fs::MoveDir(source, destination);
lua_pushboolean(L, retval);
return 1;
}
@ -793,6 +782,8 @@ int ModApiMainMenu::l_is_dir(lua_State *L)
{
const char *path = luaL_checkstring(L, 1);
CHECK_SECURE_PATH(L, path, false)
lua_pushboolean(L, fs::IsDir(path));
return 1;
}
@ -803,16 +794,12 @@ int ModApiMainMenu::l_extract_zip(lua_State *L)
const char *zipfile = luaL_checkstring(L, 1);
const char *destination = luaL_checkstring(L, 2);
std::string absolute_destination = fs::RemoveRelativePathComponents(destination);
CHECK_SECURE_PATH(L, zipfile, false)
CHECK_SECURE_PATH(L, destination, true)
if (ModApiMainMenu::mayModifyPath(absolute_destination)) {
auto fs = RenderingEngine::get_raw_device()->getFileSystem();
bool ok = fs::extractZipFile(fs, zipfile, destination);
lua_pushboolean(L, ok);
return 1;
}
lua_pushboolean(L,false);
auto fs = RenderingEngine::get_raw_device()->getFileSystem();
bool ok = fs::extractZipFile(fs, zipfile, destination);
lua_pushboolean(L, ok);
return 1;
}
@ -826,40 +813,13 @@ int ModApiMainMenu::l_get_mainmenu_path(lua_State *L)
return 1;
}
/******************************************************************************/
bool ModApiMainMenu::mayModifyPath(std::string path)
{
path = fs::RemoveRelativePathComponents(path);
if (fs::PathStartsWith(path, fs::TempPath()))
return true;
std::string path_user = fs::RemoveRelativePathComponents(porting::path_user);
if (fs::PathStartsWith(path, path_user + DIR_DELIM "client"))
return true;
if (fs::PathStartsWith(path, path_user + DIR_DELIM "games"))
return true;
if (fs::PathStartsWith(path, path_user + DIR_DELIM "mods"))
return true;
if (fs::PathStartsWith(path, path_user + DIR_DELIM "textures"))
return true;
if (fs::PathStartsWith(path, path_user + DIR_DELIM "worlds"))
return true;
if (fs::PathStartsWith(path, fs::RemoveRelativePathComponents(porting::path_cache)))
return true;
return false;
}
/******************************************************************************/
int ModApiMainMenu::l_may_modify_path(lua_State *L)
{
const char *target = luaL_checkstring(L, 1);
std::string absolute_destination = fs::RemoveRelativePathComponents(target);
lua_pushboolean(L, ModApiMainMenu::mayModifyPath(absolute_destination));
bool write_allowed = false;
bool ok = ScriptApiSecurity::checkPath(L, target, false, &write_allowed);
lua_pushboolean(L, ok && write_allowed);
return 1;
}
@ -892,19 +852,9 @@ int ModApiMainMenu::l_download_file(lua_State *L)
const char *url = luaL_checkstring(L, 1);
const char *target = luaL_checkstring(L, 2);
//check path
std::string absolute_destination = fs::RemoveRelativePathComponents(target);
CHECK_SECURE_PATH(L, target, true)
if (ModApiMainMenu::mayModifyPath(absolute_destination)) {
if (GUIEngine::downloadFile(url,absolute_destination)) {
lua_pushboolean(L,true);
return 1;
}
} else {
errorstream << "DOWNLOAD denied: " << absolute_destination
<< " isn't an allowed path" << std::endl;
}
lua_pushboolean(L,false);
lua_pushboolean(L, GUIEngine::downloadFile(url, target));
return 1;
}
@ -1068,16 +1018,22 @@ int ModApiMainMenu::l_open_url_dialog(lua_State *L)
/******************************************************************************/
int ModApiMainMenu::l_open_dir(lua_State *L)
{
std::string path = luaL_checkstring(L, 1);
lua_pushboolean(L, porting::open_directory(path));
const char *target = luaL_checkstring(L, 1);
CHECK_SECURE_PATH(L, target, false)
lua_pushboolean(L, porting::open_directory(target));
return 1;
}
/******************************************************************************/
int ModApiMainMenu::l_share_file(lua_State *L)
{
const char *path = luaL_checkstring(L, 1);
CHECK_SECURE_PATH(L, path, false)
#ifdef __ANDROID__
std::string path = luaL_checkstring(L, 1);
porting::shareFileAndroid(path);
lua_pushboolean(L, true);
#else
@ -1091,19 +1047,20 @@ int ModApiMainMenu::l_do_async_callback(lua_State *L)
{
MainMenuScripting *script = getScriptApi<MainMenuScripting>(L);
size_t func_length, param_length;
const char* serialized_func_raw = luaL_checklstring(L, 1, &func_length);
const char* serialized_param_raw = luaL_checklstring(L, 2, &param_length);
luaL_checktype(L, 1, LUA_TFUNCTION);
call_string_dump(L, 1);
size_t func_length;
const char *serialized_func_raw = lua_tolstring(L, -1, &func_length);
sanity_check(serialized_func_raw != NULL);
sanity_check(serialized_param_raw != NULL);
size_t param_length;
const char* serialized_param_raw = luaL_checklstring(L, 2, &param_length);
u32 jobId = script->queueAsync(
std::string(serialized_func_raw, func_length),
std::string(serialized_param_raw, param_length));
lua_settop(L, 0);
lua_pushinteger(L, jobId);
return 1;
}