Compare commits

...

2 Commits

Author SHA1 Message Date
dfeae6ac92 antihacks : Prevent players accessing inventories of other players
* this backported https://github.com/minetest/minetest/pull/10341
  Inventory: Protect Craft and Drop actions was implemented later
  as Inventory: Protect Craft and Drop actions commit
  backporting https://github.com/minetest/minetest/pull/10353
* also backported https://github.com/minetest/minetest/pull/11035
  Additional inventory access protections
2023-09-17 18:53:42 -04:00
d79506d076 load warning fix for lua src build in 2023-09-17 17:42:12 -04:00
2 changed files with 35 additions and 38 deletions

View File

@ -73,7 +73,7 @@ static void *ll_load (lua_State *L, const char *path) {
static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
lua_CFunction f = (lua_CFunction)dlsym(lib, sym); lua_CFunction f = __extension__(lua_CFunction)dlsym(lib, sym);
if (f == NULL) lua_pushstring(L, dlerror()); if (f == NULL) lua_pushstring(L, dlerror());
return f; return f;
} }

View File

@ -593,7 +593,7 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
<< std::endl; << std::endl;
std::istringstream is(datastring, std::ios_base::binary); std::istringstream is(datastring, std::ios_base::binary);
// Create an action // Create an action
InventoryAction *a = InventoryAction::deSerialize(is); std::unique_ptr<InventoryAction> a(InventoryAction::deSerialize(is));
if (!a) { if (!a) {
infostream << "TOSERVER_INVENTORY_ACTION: " infostream << "TOSERVER_INVENTORY_ACTION: "
<< "InventoryAction::deSerialize() returned NULL" << "InventoryAction::deSerialize() returned NULL"
@ -610,11 +610,29 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
where the client made a bad prediction. where the client made a bad prediction.
*/ */
const bool player_has_interact = checkPriv(player->getName(), "interact");
auto check_inv_access = [player, player_has_interact] (
const InventoryLocation &loc) -> bool {
if (loc.type == InventoryLocation::CURRENT_PLAYER)
return false; // Only used internally on the client, never sent
if (loc.type == InventoryLocation::PLAYER) {
// Allow access to own inventory in all cases
return loc.name == player->getName();
}
if (!player_has_interact) {
infostream << "Cannot modify foreign inventory: "
<< "No interact privilege" << std::endl;
return false;
}
return true;
};
/* /*
Handle restrictions and special cases of the move action Handle restrictions and special cases of the move action
*/ */
if (a->getType() == IAction::Move) { if (a->getType() == IAction::Move) {
IMoveAction *ma = (IMoveAction*)a; IMoveAction *ma = (IMoveAction*)a.get();
ma->from_inv.applyCurrentPlayer(player->getName()); ma->from_inv.applyCurrentPlayer(player->getName());
ma->to_inv.applyCurrentPlayer(player->getName()); ma->to_inv.applyCurrentPlayer(player->getName());
@ -623,15 +641,11 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
if (ma->from_inv != ma->to_inv) if (ma->from_inv != ma->to_inv)
setInventoryModified(ma->to_inv); setInventoryModified(ma->to_inv);
bool from_inv_is_current_player = if (!check_inv_access(ma->from_inv) ||
(ma->from_inv.type == InventoryLocation::PLAYER) && !check_inv_access(ma->to_inv))
(ma->from_inv.name == player->getName()); return;
bool to_inv_is_current_player = InventoryLocation *remote = ma->from_inv.type == InventoryLocation::PLAYER ?
(ma->to_inv.type == InventoryLocation::PLAYER) &&
(ma->to_inv.name == player->getName());
InventoryLocation *remote = from_inv_is_current_player ?
&ma->to_inv : &ma->from_inv; &ma->to_inv : &ma->from_inv;
// Check for out-of-range interaction // Check for out-of-range interaction
@ -651,7 +665,6 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
<< (ma->from_inv.dump()) << ":" << ma->from_list << (ma->from_inv.dump()) << ":" << ma->from_list
<< " to " << (ma->to_inv.dump()) << ":" << ma->to_list << " to " << (ma->to_inv.dump()) << ":" << ma->to_list
<< " because src is " << ma->from_list << std::endl; << " because src is " << ma->from_list << std::endl;
delete a;
return; return;
} }
@ -663,18 +676,6 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
<< (ma->from_inv.dump()) << ":" << ma->from_list << (ma->from_inv.dump()) << ":" << ma->from_list
<< " to " << (ma->to_inv.dump()) << ":" << ma->to_list << " to " << (ma->to_inv.dump()) << ":" << ma->to_list
<< " because dst is " << ma->to_list << std::endl; << " because dst is " << ma->to_list << std::endl;
delete a;
return;
}
// Disallow moving items in elsewhere than player's inventory
// if not allowed to interact
if (!checkPriv(player->getName(), "interact") &&
(!from_inv_is_current_player ||
!to_inv_is_current_player)) {
infostream << "Cannot move outside of player's inventory: "
<< "No interact privilege" << std::endl;
delete a;
return; return;
} }
} }
@ -682,7 +683,7 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
Handle restrictions and special cases of the drop action Handle restrictions and special cases of the drop action
*/ */
else if (a->getType() == IAction::Drop) { else if (a->getType() == IAction::Drop) {
IDropAction *da = (IDropAction*)a; IDropAction *da = (IDropAction*)a.get();
da->from_inv.applyCurrentPlayer(player->getName()); da->from_inv.applyCurrentPlayer(player->getName());
@ -695,13 +696,11 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
infostream << "Ignoring IDropAction from " infostream << "Ignoring IDropAction from "
<< (da->from_inv.dump()) << ":" << da->from_list << (da->from_inv.dump()) << ":" << da->from_list
<< " because src is " << da->from_list << std::endl; << " because src is " << da->from_list << std::endl;
delete a;
return; return;
} }
// Disallow dropping items if not allowed to interact // Disallow dropping items if not allowed to interact
if (!checkPriv(player->getName(), "interact")) { if (!player_has_interact || !check_inv_access(da->from_inv)) {
delete a;
return; return;
} }
@ -710,7 +709,6 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
infostream << "Ignoring IDropAction from " infostream << "Ignoring IDropAction from "
<< (da->from_inv.dump()) << ":" << da->from_list << (da->from_inv.dump()) << ":" << da->from_list
<< " because player is dead." << std::endl; << " because player is dead." << std::endl;
delete a;
return; return;
} }
} }
@ -718,29 +716,28 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
Handle restrictions and special cases of the craft action Handle restrictions and special cases of the craft action
*/ */
else if (a->getType() == IAction::Craft) { else if (a->getType() == IAction::Craft) {
ICraftAction *ca = (ICraftAction*)a; ICraftAction *ca = (ICraftAction*)a.get();
ca->craft_inv.applyCurrentPlayer(player->getName()); ca->craft_inv.applyCurrentPlayer(player->getName());
setInventoryModified(ca->craft_inv); setInventoryModified(ca->craft_inv);
//bool craft_inv_is_current_player =
// (ca->craft_inv.type == InventoryLocation::PLAYER) &&
// (ca->craft_inv.name == player->getName());
// Disallow crafting if not allowed to interact // Disallow crafting if not allowed to interact
if (!checkPriv(player->getName(), "interact")) { if (!player_has_interact) {
infostream << "Cannot craft: " infostream << "Cannot craft: "
<< "No interact privilege" << std::endl; << "No interact privilege" << std::endl;
delete a;
return; return;
} }
if (!check_inv_access(ca->craft_inv))
return;
} else {
// Unknown action. Ignored.
return;
} }
// Do the action // Do the action
a->apply(this, playersao, this); a->apply(this, playersao, this);
// Eat the action
delete a;
} }
void Server::handleCommand_ChatMessage(NetworkPacket* pkt) void Server::handleCommand_ChatMessage(NetworkPacket* pkt)