diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg
index 717e73bd65..9a09010e25 100644
--- a/binaries/data/config/default.cfg
+++ b/binaries/data/config/default.cfg
@@ -421,7 +421,6 @@ xpartamupp = "wfgbot23" ; Name of the server-side XMPP-account that
echelon = "echelon23" ; Name of the server-side XMPP-account that manages ratings
buddies = "," ; Comma separated list of playernames that the current user has marked as buddies
rememberpassword = true ; Whether to store the encrypted password in the user config
-secureauth = true ; Secure Lobby Authentication: This prevents the impersonation of other players. The lobby server confirms the identity of the player before they join.
[lobby.columns]
gamerating = false ; Show the average rating of the participating players in a column of the gamelist
diff --git a/binaries/data/mods/public/gui/gamesetup_mp/gamesetup_mp.js b/binaries/data/mods/public/gui/gamesetup_mp/gamesetup_mp.js
index 2ee2cb0197..63e6d200e0 100644
--- a/binaries/data/mods/public/gui/gamesetup_mp/gamesetup_mp.js
+++ b/binaries/data/mods/public/gui/gamesetup_mp/gamesetup_mp.js
@@ -48,7 +48,6 @@ function init(attribs)
case "host":
{
Engine.GetGUIObjectByName("hostSTUNWrapper").hidden = !Engine.HasXmppClient();
- Engine.GetGUIObjectByName("hostLobbyAuthWrapper").hidden = !Engine.HasXmppClient();
if (Engine.HasXmppClient())
{
Engine.GetGUIObjectByName("hostPlayerName").caption = attribs.name;
@@ -56,7 +55,6 @@ function init(attribs)
sprintf(translate("%(name)s's game"), { "name": attribs.name });
Engine.GetGUIObjectByName("useSTUN").checked = Engine.ConfigDB_GetValue("user", "lobby.stun.enabled") == "true";
- Engine.GetGUIObjectByName("useLobbyAuth").checked = Engine.ConfigDB_GetValue("user", "lobby.secureauth") == "true";
}
switchSetupPage("pageHost");
@@ -269,7 +267,7 @@ function switchSetupPage(newPage)
if (newPage == "pageJoin" || newPage == "pageHost")
{
let pageSize = multiplayerPages.size;
- let halfHeight = newPage == "pageJoin" ? 130 : Engine.HasXmppClient() ? 145 : 110;
+ let halfHeight = newPage == "pageJoin" ? 130 : Engine.HasXmppClient() ? 125 : 110;
pageSize.top = -halfHeight;
pageSize.bottom = halfHeight;
multiplayerPages.size = pageSize;
@@ -313,10 +311,9 @@ function startHost(playername, servername, port)
}
}
- let useLobbyAuth = Engine.HasXmppClient() && Engine.GetGUIObjectByName("useLobbyAuth").checked;
try
{
- Engine.StartNetworkHost(playername + (g_UserRating ? " (" + g_UserRating + ")" : ""), port, playername, useLobbyAuth);
+ Engine.StartNetworkHost(playername + (g_UserRating ? " (" + g_UserRating + ")" : ""), port, playername);
}
catch (e)
{
diff --git a/binaries/data/mods/public/gui/gamesetup_mp/gamesetup_mp.xml b/binaries/data/mods/public/gui/gamesetup_mp/gamesetup_mp.xml
index 4515dc2321..b37a17c56e 100644
--- a/binaries/data/mods/public/gui/gamesetup_mp/gamesetup_mp.xml
+++ b/binaries/data/mods/public/gui/gamesetup_mp/gamesetup_mp.xml
@@ -114,16 +114,6 @@
Use STUN to work around firewalls
-
-
diff --git a/source/lobby/scripting/JSInterface_Lobby.cpp b/source/lobby/scripting/JSInterface_Lobby.cpp
index b932946e2f..e3a90f2ad9 100644
--- a/source/lobby/scripting/JSInterface_Lobby.cpp
+++ b/source/lobby/scripting/JSInterface_Lobby.cpp
@@ -22,13 +22,17 @@
#include "gui/GUIManager.h"
#include "lib/utf8.h"
#include "lobby/IXmppClient.h"
+#include "network/NetServer.h"
+#include "ps/CLogger.h"
#include "ps/CStr.h"
-#include "ps/Profile.h"
#include "ps/Util.h"
#include "scriptinterface/ScriptInterface.h"
+#include "scriptinterface/ScriptVal.h"
#include "third_party/encryption/pkcs5_pbkdf2.h"
+#include
+
void JSI_Lobby::RegisterScriptFunctions(const ScriptInterface& scriptInterface)
{
// Lobby functions
@@ -154,6 +158,13 @@ void JSI_Lobby::SendRegisterGame(ScriptInterface::CxPrivate* pCxPrivate, JS::Han
if (!g_XmppClient)
return;
+ // Prevent JS mods to register matches in the lobby that were started with lobby authentication disabled
+ if (!g_NetServer || !g_NetServer->UseLobbyAuth())
+ {
+ LOGERROR("Registering games in the lobby requires lobby authentication to be enabled!");
+ return;
+ }
+
g_XmppClient->SendIqRegisterGame(*(pCxPrivate->pScriptInterface), data);
}
diff --git a/source/lobby/scripting/JSInterface_Lobby.h b/source/lobby/scripting/JSInterface_Lobby.h
index f6bd2ca804..9e5c4faf22 100644
--- a/source/lobby/scripting/JSInterface_Lobby.h
+++ b/source/lobby/scripting/JSInterface_Lobby.h
@@ -20,7 +20,8 @@
#include "lib/config2.h"
#include "scriptinterface/ScriptInterface.h"
-#include "scriptinterface/ScriptVal.h"
+
+#include
namespace JSI_Lobby
{
diff --git a/source/network/NetServer.cpp b/source/network/NetServer.cpp
index 3fbf328228..08d2fd8b07 100644
--- a/source/network/NetServer.cpp
+++ b/source/network/NetServer.cpp
@@ -26,11 +26,13 @@
#include "NetStats.h"
#include "lib/external_libraries/enet.h"
+#include "lib/types.h"
#include "network/StunClient.h"
#include "ps/CLogger.h"
#include "ps/ConfigDB.h"
#include "ps/GUID.h"
#include "ps/Profile.h"
+#include "ps/ThreadUtil.h"
#include "scriptinterface/ScriptInterface.h"
#include "scriptinterface/ScriptRuntime.h"
#include "simulation2/Simulation2.h"
@@ -43,6 +45,8 @@
#include
#endif
+#include
+
/**
* Number of peers to allocate for the enet host.
* Limited by ENET_PROTOCOL_MAXIMUM_PEER_ID (4096).
@@ -1556,7 +1560,8 @@ void CNetServerWorker::SendHolePunchingMessage(const CStr& ipStr, u16 port)
CNetServer::CNetServer(bool useLobbyAuth, int autostartPlayers) :
- m_Worker(new CNetServerWorker(useLobbyAuth, autostartPlayers))
+ m_Worker(new CNetServerWorker(useLobbyAuth, autostartPlayers)),
+ m_LobbyAuth(useLobbyAuth)
{
}
@@ -1565,6 +1570,11 @@ CNetServer::~CNetServer()
delete m_Worker;
}
+bool CNetServer::UseLobbyAuth() const
+{
+ return m_LobbyAuth;
+}
+
bool CNetServer::SetupConnection(const u16 port)
{
return m_Worker->SetupConnection(port);
diff --git a/source/network/NetServer.h b/source/network/NetServer.h
index da6fbb6bbc..f17aebecc7 100644
--- a/source/network/NetServer.h
+++ b/source/network/NetServer.h
@@ -20,11 +20,13 @@
#include "NetFileTransfer.h"
#include "NetHost.h"
-
#include "lib/config2.h"
+#include "lib/types.h"
#include "ps/ThreadUtil.h"
#include "scriptinterface/ScriptTypes.h"
+#include
+#include
#include
class CNetServerSession;
@@ -137,12 +139,15 @@ public:
*/
void SetTurnLength(u32 msecs);
+ bool UseLobbyAuth() const;
+
void OnLobbyAuth(const CStr& name, const CStr& token);
void SendHolePunchingMessage(const CStr& ip, u16 port);
private:
CNetServerWorker* m_Worker;
+ const bool m_LobbyAuth;
};
/**
@@ -298,7 +303,11 @@ private:
JS::PersistentRootedValue m_GameAttributes;
int m_AutostartPlayers;
- bool m_LobbyAuth;
+
+ /**
+ * Whether this match requires lobby authentication.
+ */
+ const bool m_LobbyAuth;
ENetHost* m_Host;
std::vector m_Sessions;
diff --git a/source/network/scripting/JSInterface_Network.cpp b/source/network/scripting/JSInterface_Network.cpp
index 8436532eb5..9b7fd7136a 100644
--- a/source/network/scripting/JSInterface_Network.cpp
+++ b/source/network/scripting/JSInterface_Network.cpp
@@ -21,6 +21,7 @@
#include "lib/external_libraries/enet.h"
#include "lib/external_libraries/libsdl.h"
+#include "lib/types.h"
#include "lobby/IXmppClient.h"
#include "network/NetClient.h"
#include "network/NetMessage.h"
@@ -50,13 +51,14 @@ JS::Value JSI_Network::FindStunEndpoint(ScriptInterface::CxPrivate* pCxPrivate,
return StunClient::FindStunEndpointHost(*(pCxPrivate->pScriptInterface), port);
}
-void JSI_Network::StartNetworkHost(ScriptInterface::CxPrivate* pCxPrivate, const CStrW& playerName, const u16 serverPort, const CStr& hostLobbyName, bool useLobbyAuth)
+void JSI_Network::StartNetworkHost(ScriptInterface::CxPrivate* pCxPrivate, const CStrW& playerName, const u16 serverPort, const CStr& hostLobbyName)
{
ENSURE(!g_NetClient);
ENSURE(!g_NetServer);
ENSURE(!g_Game);
- g_NetServer = new CNetServer(useLobbyAuth);
+ // Always use lobby authentication for lobby matches to prevent impersonation and smurfing, in particular through mods that implemented an UI for arbitrary or other players nicknames.
+ g_NetServer = new CNetServer(static_cast(g_XmppClient));
if (!g_NetServer->SetupConnection(serverPort))
{
pCxPrivate->pScriptInterface->ReportError("Failed to start server");
@@ -228,7 +230,7 @@ void JSI_Network::RegisterScriptFunctions(const ScriptInterface& scriptInterface
scriptInterface.RegisterFunction("HasNetServer");
scriptInterface.RegisterFunction("HasNetClient");
scriptInterface.RegisterFunction("FindStunEndpoint");
- scriptInterface.RegisterFunction("StartNetworkHost");
+ scriptInterface.RegisterFunction("StartNetworkHost");
scriptInterface.RegisterFunction("StartNetworkJoin");
scriptInterface.RegisterFunction("DisconnectNetworkGame");
scriptInterface.RegisterFunction("GetPlayerGUID");
diff --git a/source/network/scripting/JSInterface_Network.h b/source/network/scripting/JSInterface_Network.h
index 1e74df5059..852bc47ace 100644
--- a/source/network/scripting/JSInterface_Network.h
+++ b/source/network/scripting/JSInterface_Network.h
@@ -18,6 +18,7 @@
#ifndef INCLUDED_JSI_NETWORK
#define INCLUDED_JSI_NETWORK
+#include "lib/types.h"
#include "ps/CStr.h"
#include "scriptinterface/ScriptInterface.h"
@@ -28,7 +29,7 @@ namespace JSI_Network
bool HasNetClient(ScriptInterface::CxPrivate* pCxPrivate);
void StartNetworkGame(ScriptInterface::CxPrivate* pCxPrivate);
void SetNetworkGameAttributes(ScriptInterface::CxPrivate* pCxPrivate, JS::HandleValue attribs1);
- void StartNetworkHost(ScriptInterface::CxPrivate* pCxPrivate, const CStrW& playerName, const u16 serverPort, const CStr& hostLobbyName, bool useLobbyAuth);
+ void StartNetworkHost(ScriptInterface::CxPrivate* pCxPrivate, const CStrW& playerName, const u16 serverPort, const CStr& hostLobbyName);
void StartNetworkJoin(ScriptInterface::CxPrivate* pCxPrivate, const CStrW& playerName, const CStr& serverAddress, u16 serverPort, bool useSTUN, const CStr& hostJID);
JS::Value FindStunEndpoint(ScriptInterface::CxPrivate* pCxPrivate, int port);
void DisconnectNetworkGame(ScriptInterface::CxPrivate* pCxPrivate);