Skip to content

Commit

Permalink
fix(ModPolicy): Make sure there are no workarounds possible.
Browse files Browse the repository at this point in the history
  • Loading branch information
Force67 committed Apr 16, 2022
1 parent 8cb1131 commit 7272ea4
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 20 deletions.
21 changes: 14 additions & 7 deletions Code/client/Services/Generic/TransportService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,18 +279,25 @@ void TransportService::HandleAuthenticationResponse(const AuthenticationResponse
case AuthenticationResponse::ResponseType::kAccepted:
{
m_connected = true;

// Dispatch the mods to anyone who needs it
m_dispatcher.trigger(acMessage.UserMods);

// Notify we are ready for action
m_dispatcher.trigger(ConnectedEvent());
break;
}
// TODO(Anyone): Handle this within the ui
case AuthenticationResponse::ResponseType::kWrongVersion:
spdlog::error("This server expects version {} but you are on version {}", acMessage.Version, BUILD_COMMIT);
break;
case AuthenticationResponse::ResponseType::kMissingMods: {
spdlog::error("This server has ModPolicy enabled. You were kicked because you have the following mods installed:");
for (const auto& m : acMessage.UserMods.ModList)
{
spdlog::error("{}:{}", m.Filename.c_str(), m.Id);
}
spdlog::error("Please remove them to join");
break;
}
default:
case AuthenticationResponse::ResponseType::kMissingMods:
// TODO: this message should be handeled elsewhere...
// (OR dispatched).
spdlog::error("The server refused connection without reason.");
break;
}
}
58 changes: 45 additions & 13 deletions Code/server/GameServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,17 @@ Console::StringSetting sServerIconURL{"GameServer:sIconUrl", "URL to the image t
Console::StringSetting sTagList{"GameServer:sTagList", "List of tags, separated by a comma (,)", ""};
Console::StringSetting sAdminPassword{"GameServer:sAdminPassword", "Admin authentication password", ""};
Console::StringSetting sToken{"GameServer:sToken", "Admin token", ""};

Console::Setting bBypassMoPo{"ModPolicy:bBypass", "Bypass the mod policy restrictions.", false,
Console::SettingsFlags::kHidden | Console::SettingsFlags::kLocked};
// -- Commands --
Console::Command<bool> TogglePremium("TogglePremium", "Toggle the premium mode",
[](Console::ArgStack& aStack) { bPremiumTickrate = aStack.Pop<bool>(); });

Console::Command<> ShowVersion("version", "Show the version the server was compiled with",
[](Console::ArgStack&) { spdlog::get("ConOut")->info("Server " BUILD_COMMIT); });

Console::Setting bBypassMoPo{"ModPolicy:bBypass", "Bypass the mod policy restrictions.", false,
Console::SettingsFlags::kHidden | Console::SettingsFlags::kLocked};
Console::Command<> ShowMoPoStatus("isMoPoActive", "Shows if the ModPolicy is active", [](Console::ArgStack&) {
spdlog::get("ConOut")->info("ModPolicy status: {}", bBypassMoPo ? "not active" : "active");
});

// -- Constants --
constexpr char kBypassMoPoWarning[]{
Expand All @@ -66,6 +67,11 @@ static uint16_t GetUserTickRate()
return bPremiumTickrate ? 60 : 30;
}

static bool IsMoPoActive()
{
return !bBypassMoPo;
}

GameServer* GameServer::s_pInstance = nullptr;

GameServer::GameServer(Console::ConsoleRegistry& aConsole) noexcept
Expand Down Expand Up @@ -469,26 +475,52 @@ void GameServer::HandleAuthenticationRequest(const ConnectionId_t aConnectionId,
Mods& responseList = serverResponse.UserMods;
auto& modsComponent = m_pWorld->ctx<ModsComponent>();

if (!bBypassMoPo)
if (IsMoPoActive())
{
Mods missingMods;
for (const Mods::Entry& mod : acRequest->UserMods.ModList)
// mods that exist on the client, but not on the server
// modscomponent contains a list filled in by the recordcollection
Mods modsToRemove;

const auto& userMods = acRequest->UserMods.ModList;
for (const Mods::Entry& mod : userMods)
{
// modscomponent contains a list filled in by the recordcollection
// if the client has more mods than the server..
if (!modsComponent.IsInstalled(mod.Filename))
{
missingMods.ModList.push_back(mod);
modsToRemove.ModList.push_back(mod);
}
}

// TODO(Vince): if you have a better to do this than two for loops
// let me know!
// Also, for the future, lets think about a mode that allows more than the server installed mods
// but requires essential mods?

// mods that may exist on the server, but not on the client
for (const auto& entry : modsComponent.GetServerMods())
{
const auto it = std::find_if(userMods.begin(), userMods.end(),
[&](const Mods::Entry& it) { return it.Filename == entry.first; });

if (it == userMods.end())
{
Mods::Entry removeEntry;
removeEntry.Filename = entry.first;
removeEntry.Id = 0;
modsToRemove.ModList.push_back(removeEntry);
}
}

if (missingMods.ModList.size() > 0)
if (modsToRemove.ModList.size() > 0)
{
String text = PrettyPrintModList(missingMods.ModList);
spdlog::info("Modpolicy: refusing connection {:x} because essential mods are missing: {}",
String text = PrettyPrintModList(modsToRemove.ModList);
// "ModPolicy: refusing connection {:x} because essential mods are missing: {}"
// for future reference ^
spdlog::info("ModPolicy: refusing connection {:x} because the following mods are installed on the client: {}",
aConnectionId, text.c_str());

serverResponse.Type = AuthenticationResponse::ResponseType::kMissingMods;
serverResponse.UserMods.ModList = std::move(missingMods.ModList);
serverResponse.UserMods.ModList = std::move(modsToRemove.ModList);
Send(aConnectionId, serverResponse);
// This is a lingering kick, so sending the response should still succeed.
Kick(aConnectionId);
Expand Down
2 changes: 2 additions & 0 deletions Code/server/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ void DediRunner::StartTerminalIO()

while (m_gameServer.IsRunning())
{
// should have a isDirty flag and flush if, every x seconds.

std::string s;
std::getline(std::cin, s);
if (!m_console.TryExecuteCommand(s))
Expand Down

0 comments on commit 7272ea4

Please sign in to comment.