Skip to content

Commit

Permalink
Request an authentication token only at join, and using the GETTOKEN …
Browse files Browse the repository at this point in the history
…action instead of the LIST action. (#351)

Requesting an authentication token no longer fetches the entire server list. The GETTOKEN action is used to fetch a token when connecting to a server, and the server host/port are passed along. This also instructs the list server to not generate a token for the LIST action, since we're now trying to restrict tokens to a specific server instead of the player IP in order to  handle CGNAT.
  • Loading branch information
blast007 authored Nov 26, 2024
1 parent f2bd82f commit 30ce141
Show file tree
Hide file tree
Showing 13 changed files with 210 additions and 70 deletions.
2 changes: 2 additions & 0 deletions MSVC/build/game.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@
<ClCompile Include="..\..\src\game\PhysicsDriver.cxx" />
<ClCompile Include="..\..\src\game\PlayerInfo.cxx" />
<ClCompile Include="..\..\src\game\Ray.cxx" />
<ClCompile Include="..\..\src\game\ServerAuth.cxx" />
<ClCompile Include="..\..\src\game\ServerItem.cxx" />
<ClCompile Include="..\..\src\game\ServerList.cxx" />
<ClCompile Include="..\..\src\game\ServerListCache.cxx" />
Expand All @@ -184,6 +185,7 @@
<ClInclude Include="..\..\include\PhysicsDriver.h" />
<ClInclude Include="..\..\include\PlayerInfo.h" />
<ClInclude Include="..\..\include\Ray.h" />
<ClInclude Include="..\..\include\ServerAuth.h" />
<ClInclude Include="..\..\include\ServerItem.h" />
<ClInclude Include="..\..\include\ServerList.h" />
<ClInclude Include="..\..\include\ServerListCache.h" />
Expand Down
6 changes: 6 additions & 0 deletions MSVC/build/game.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@
<ClCompile Include="..\..\src\game\Frustum.cxx">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\game\ServerAuth.cxx">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\BzMaterial.h">
Expand Down Expand Up @@ -114,6 +117,9 @@
<ClInclude Include="..\..\include\StartupInfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\ServerAuth.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
Expand Down
6 changes: 6 additions & 0 deletions Xcode/BZFlag.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@
C38E766527F9062B00EC312C /* CustomZoneSample.bzw in Copy Files (1 item) */ = {isa = PBXBuildFile; fileRef = C353B1E81AE2489900C5AED5 /* CustomZoneSample.bzw */; };
C39F69371E3D3E8100132C55 /* customPollTypeSample.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = C333EFC91E2B9F0800B4B182 /* customPollTypeSample.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
C3DE232E21E2FBDD0081B64E /* libplugin_utils.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0394E895167B2513007F4035 /* libplugin_utils.a */; };
D21A35892BFAA6BD001A28EB /* ServerAuth.cxx in Sources */ = {isa = PBXBuildFile; fileRef = D21A35882BFAA6BD001A28EB /* ServerAuth.cxx */; };
D2B721C92BFAA226007126EE /* mathRoutine.cxx in Sources */ = {isa = PBXBuildFile; fileRef = D2B721C82BFAA225007126EE /* mathRoutine.cxx */; };
DF28982B16B4F5AE006C78AC /* ShotManager.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DF28982916B4F5AE006C78AC /* ShotManager.cxx */; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -1814,6 +1815,8 @@
C353B1E01AE23C8100C5AED5 /* CustomZoneSample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CustomZoneSample.cpp; sourceTree = "<group>"; };
C353B1E81AE2489900C5AED5 /* CustomZoneSample.bzw */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CustomZoneSample.bzw; sourceTree = "<group>"; };
C353B1E91AE2490D00C5AED5 /* flagStay.bzw */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = flagStay.bzw; sourceTree = "<group>"; };
D21A35872BFAA6AE001A28EB /* ServerAuth.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ServerAuth.h; sourceTree = "<group>"; };
D21A35882BFAA6BD001A28EB /* ServerAuth.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ServerAuth.cxx; sourceTree = "<group>"; };
D2B721C72BFAA1E1007126EE /* mathRoutine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mathRoutine.h; sourceTree = "<group>"; };
D2B721C82BFAA225007126EE /* mathRoutine.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mathRoutine.cxx; sourceTree = "<group>"; };
DF28982916B4F5AE006C78AC /* ShotManager.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShotManager.cxx; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2347,6 +2350,7 @@
0305D5D9166C9DAE00557FC4 /* SceneDatabase.h */,
0305D5DA166C9DAE00557FC4 /* SceneNode.h */,
0305D5DB166C9DAE00557FC4 /* SceneRenderer.h */,
D21A35872BFAA6AE001A28EB /* ServerAuth.h */,
0305D5DC166C9DAE00557FC4 /* ServerItem.h */,
0305D5DD166C9DAE00557FC4 /* ServerList.h */,
0305D5DE166C9DAE00557FC4 /* ServerListCache.h */,
Expand Down Expand Up @@ -2858,6 +2862,7 @@
0355447B166C846F008806E9 /* PlayerInfo.cxx */,
0355447C166C846F008806E9 /* Ray.cxx */,
0355447D166C846F008806E9 /* README */,
D21A35882BFAA6BD001A28EB /* ServerAuth.cxx */,
0355447E166C846F008806E9 /* ServerItem.cxx */,
0355447F166C846F008806E9 /* ServerList.cxx */,
03554480166C846F008806E9 /* ServerListCache.cxx */,
Expand Down Expand Up @@ -5070,6 +5075,7 @@
0357A80E1670B2090056C938 /* PhysicsDriver.cxx in Sources */,
0357A80F1670B2090056C938 /* PlayerInfo.cxx in Sources */,
0357A8101670B2090056C938 /* Ray.cxx in Sources */,
D21A35892BFAA6BD001A28EB /* ServerAuth.cxx in Sources */,
0357A8111670B2090056C938 /* ServerItem.cxx in Sources */,
0357A8121670B2090056C938 /* ServerList.cxx in Sources */,
0357A8131670B2090056C938 /* ServerListCache.cxx in Sources */,
Expand Down
1 change: 1 addition & 0 deletions include/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ noinst_HEADERS = \
SceneDatabase.h \
SceneNode.h \
SceneRenderer.h \
ServerAuth.h \
ServerItem.h \
ServerList.h \
ServerListCache.h \
Expand Down
38 changes: 38 additions & 0 deletions include/ServerAuth.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* bzflag
* Copyright (c) 1993-2024 Tim Riker
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#ifndef BZF_SERVERAUTH_H
#define BZF_SERVERAUTH_H

#include "common.h"

/* system interface headers */
#include <vector>

/* common interface headers */
#include "StartupInfo.h"
#include "cURLManager.h"

class ServerAuth : cURLManager
{
public:
ServerAuth();
virtual ~ServerAuth();

void requestToken(StartupInfo *info);
void finalization(char *data, unsigned int length, bool good);

private:
StartupInfo *startupInfo;
};

#endif // BZF_SERVERAUTH_H
1 change: 0 additions & 1 deletion include/cURLManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ class cURLManager
void setPostMode(std::string postData);
void setRequestFileTime(bool request);
void setURL(const std::string &url);
void setURLwithNonce(const std::string &url);
void setProgressFunction(curl_xferinfo_callback func, const void* data);
void setTimeCondition(timeCondition condition, time_t &t);
void setInterface(const std::string &interfaceIP);
Expand Down
22 changes: 19 additions & 3 deletions src/bzadmin/BZAdminClient.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "TextUtils.h"
#include "version.h"
#include "Team.h"
#include "ServerAuth.h"
#include "ServerList.h"
#include "ErrorHandler.h"
#include "cURLManager.h"
Expand Down Expand Up @@ -73,10 +74,25 @@ BZAdminClient::BZAdminClient(BZAdminUI* bzInterface)
std::cout << std::endl;
return;
}
if ((startupInfo.token[0] == '\0') && (startupInfo.password[0] != '\0'))

// If a password was provided, get a token
if (startupInfo.password[0] != '\0')
{
// won't really output anything, just gets token
outputServerList();
ServerAuth* serverAuth = new ServerAuth;
serverAuth->requestToken(&startupInfo);
// wait no more than 10 seconds for a token
for (int j = 0; j < 40; j++)
{
cURLManager::perform();
if (startupInfo.token[0] != '\0') break;
TimeKeeper::sleep(0.25f);
}
delete serverAuth;

// don't let the bad token specifier slip through to the server,
// just erase it
if (strcmp(startupInfo.token, "badtoken") == 0)
startupInfo.token[0] = '\0';
}
sLink.sendEnter(TankPlayer, myTeam, startupInfo.callsign, "bzadmin", startupInfo.token);
if (sLink.getState() != ServerLink::Okay)
Expand Down
26 changes: 14 additions & 12 deletions src/bzflag/playing.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
#include "PhysicsDriver.h"
#include "PlatformFactory.h"
#include "QuadWallSceneNode.h"
#include "ServerList.h"
#include "ServerAuth.h"
#include "SphereSceneNode.h"
#include "TankGeometryMgr.h"
#include "Team.h"
Expand Down Expand Up @@ -7010,26 +7010,28 @@ static void playingLoop()
// if already connected to a game then first sign off
if (myTank) leaveGame();

// get token if we need to (have a password but no token)
if ((startupInfo.token[0] == '\0')
&& (startupInfo.password[0] != '\0'))
// Erase any existing token
startupInfo.token[0] = '\0';

// get token if we have a password
if (startupInfo.password[0] != '\0')
{
ServerList* serverList = new ServerList;
serverList->startServerPings(&startupInfo);
ServerAuth* serverAuth = new ServerAuth;
serverAuth->requestToken(&startupInfo);
// wait no more than 10 seconds for a token
for (int j = 0; j < 40; j++)
{
serverList->checkEchos(getStartupInfo());
cURLManager::perform();
if (startupInfo.token[0] != '\0') break;
TimeKeeper::sleep(0.25f);
}
delete serverList;
delete serverAuth;

// don't let the bad token specifier slip through to the server,
// just erase it
if (strcmp(startupInfo.token, "badtoken") == 0)
startupInfo.token[0] = '\0';
}
// don't let the bad token specifier slip through to the server,
// just erase it
if (strcmp(startupInfo.token, "badtoken") == 0)
startupInfo.token[0] = '\0';

ares->queryHost(startupInfo.serverName);
waitingDNS = true;
Expand Down
2 changes: 1 addition & 1 deletion src/bzfs/ListServerConnection.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ ListServerLink::ListServerLink(std::string listServerURL,
std::string bzfsUserAgent = "bzfs ";
bzfsUserAgent += getAppVersion();

setURLwithNonce(listServerURL);
setURL(listServerURL);
setUserAgent(bzfsUserAgent);
setTimeout(10);

Expand Down
8 changes: 0 additions & 8 deletions src/common/cURLManager.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,6 @@ void cURLManager::setURL(const std::string &url)
logDebugMessage(1,"CURLOPT_URL error %d : %s\n", result, errorBuffer);
}

void cURLManager::setURLwithNonce(const std::string &url)
{
// only the default list server is known to support the nonce parameter
const std::string nonce = (strcasecmp(url.c_str(), DefaultListServerURL) == 0) ? TextUtils::format("?nocache=%lu",
time(0)) : "";
setURL(url + nonce);
}

void cURLManager::setProgressFunction(curl_xferinfo_callback func, const void* data)
{
CURLcode result;
Expand Down
1 change: 1 addition & 0 deletions src/game/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ libGame_la_SOURCES = \
PlayerInfo.cxx \
Ray.cxx \
ServerItem.cxx \
ServerAuth.cxx \
ServerList.cxx \
ServerListCache.cxx \
StartupInfo.cxx \
Expand Down
111 changes: 111 additions & 0 deletions src/game/ServerAuth.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/* bzflag
* Copyright (c) 1993-2024 Tim Riker
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

/* interface header */
#include "ServerAuth.h"

/* system headers */
#include <cstring>

/* common implementation headers */
#include "TextUtils.h"
#include "ErrorHandler.h"

ServerAuth::ServerAuth()
{
}

ServerAuth::~ServerAuth()
{
}

void ServerAuth::requestToken(StartupInfo *info)
{
startupInfo = info;

std::string url = info->listServerURL;

std::string msg = "action=GETTOKEN&callsign=";
msg += TextUtils::url_encode(info->callsign);
msg += "&password=";
msg += TextUtils::url_encode(info->password);
if (info->serverName[0] != '\0')
{
msg += "&nameport=";
msg += info->serverName;
msg += ':';
msg += std::to_string(info->serverPort);
}
setPostMode(msg);
setURL(url);
addHandle();
}

void ServerAuth::finalization(char *_data, unsigned int length, bool good)
{
if (good)
{
char *base = (char *)_data;
char *endS = base + length;
const char tokenIdentifier[] = "TOKEN: ";
const char noTokenIdentifier[] = "NOTOK: ";
const char errorIdentifier[] = "ERROR: ";
const char noticeIdentifier[] = "NOTICE: ";

while (base < endS)
{
// find next newline
char* scan = base;
while (scan < endS && *scan != '\n')
scan++;

// if no newline then no more complete replies
if (scan >= endS)
break;
*scan++ = '\0';

// look for TOKEN: and save token if found also look for NOTOK:
// and record "badtoken" into the token string and print an
// error
if (strncmp(base, tokenIdentifier, strlen(tokenIdentifier)) == 0)
{
strncpy(startupInfo->token, (char *)(base + strlen(tokenIdentifier)),
TokenLen - 1);
startupInfo->token[TokenLen - 1] = '\0';
#ifdef DEBUG
std::vector<std::string> args;
args.push_back(startupInfo->token);
printError("got token: {1}", &args);
#endif
}
else if (!strncmp(base, noTokenIdentifier,
strlen(noTokenIdentifier)))
{
printError("ERROR: did not get token:");
printError(base);
strcpy(startupInfo->token, "badtoken\0");
}
else if (!strncmp(base, errorIdentifier, strlen(errorIdentifier)))
{
printError(base);
strcpy(startupInfo->token, "badtoken\0");
}
else if (!strncmp(base, noticeIdentifier, strlen(noticeIdentifier)))
printError(base);

// next reply
base = scan;
}
}
else
strcpy(startupInfo->token, "badtoken\0");
}
Loading

0 comments on commit 30ce141

Please sign in to comment.