3888: Send server info request for ping with different token r=Jupeyy a=heinrich5991

Thanks to @Jupeyy for figuring out this bug.

Previously, the client would send the request for server info and the
server info ping packet with the same token, making the answer
indistinguishable from each other. Fix this by generating a token that
won't collide.

Fixes #3862.

<!-- What is the motivation for the changes of this pull request -->

## Checklist

- [x] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test if it works standalone, system.c especially
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
This commit is contained in:
bors[bot] 2021-06-09 15:36:38 +00:00 committed by GitHub
commit b445862628
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 8 deletions

View file

@ -2805,7 +2805,7 @@ void CClient::Update()
m_CurrentServerInfoRequestTime >= 0 &&
time_get() > m_CurrentServerInfoRequestTime)
{
m_ServerBrowser.RequestCurrentServer(m_ServerAddress, nullptr, nullptr);
m_ServerBrowser.RequestCurrentServer(m_ServerAddress);
m_CurrentServerInfoRequestTime = time_get() + time_freq() * 2;
}
@ -2824,7 +2824,7 @@ void CClient::Update()
m_CurrentServerPingUuid = RandomUuid();
if(!m_ServerCapabilities.m_PingEx)
{
m_ServerBrowser.RequestCurrentServer(m_ServerAddress, &m_CurrentServerPingBasicToken, &m_CurrentServerPingToken);
m_ServerBrowser.RequestCurrentServerWithRandomToken(m_ServerAddress, &m_CurrentServerPingBasicToken, &m_CurrentServerPingToken);
}
else
{

View file

@ -822,7 +822,7 @@ void CServerBrowser::Refresh(int Type)
}
}
void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry, int *pBasicToken, int *pToken) const
void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry, int *pBasicToken, int *pToken, bool RandomToken) const
{
unsigned char Buffer[sizeof(SERVERBROWSE_GETINFO) + 1];
CNetChunk Packet;
@ -837,6 +837,15 @@ void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry, int
}
int Token = GenerateToken(Addr);
if(RandomToken)
{
int AvoidBasicToken = GetBasicToken(Token);
do
{
secure_random_fill(&Token, sizeof(Token));
Token &= 0xffffff;
} while(GetBasicToken(Token) == AvoidBasicToken);
}
if(pToken)
{
*pToken = Token;
@ -893,9 +902,14 @@ void CServerBrowser::RequestImpl64(const NETADDR &Addr, CServerEntry *pEntry) co
pEntry->m_RequestTime = time_get();
}
void CServerBrowser::RequestCurrentServer(const NETADDR &Addr, int *pBasicToken, int *pToken) const
void CServerBrowser::RequestCurrentServer(const NETADDR &Addr) const
{
RequestImpl(Addr, nullptr, pBasicToken, pToken);
RequestImpl(Addr, nullptr, nullptr, nullptr, false);
}
void CServerBrowser::RequestCurrentServerWithRandomToken(const NETADDR &Addr, int *pBasicToken, int *pToken) const
{
RequestImpl(Addr, nullptr, pBasicToken, pToken, true);
}
void CServerBrowser::SetCurrentServerPing(const NETADDR &Addr, int Ping)
@ -1189,7 +1203,7 @@ void CServerBrowser::Update(bool ForceResort)
if(pEntry->m_Request64Legacy)
RequestImpl64(pEntry->m_Addr, pEntry);
else
RequestImpl(pEntry->m_Addr, pEntry, nullptr, nullptr);
RequestImpl(pEntry->m_Addr, pEntry, nullptr, nullptr, false);
}
Count++;

View file

@ -132,7 +132,8 @@ public:
//
void Update(bool ForceResort);
void Set(const NETADDR &Addr, int Type, int Token, const CServerInfo *pInfo);
void RequestCurrentServer(const NETADDR &Addr, int *pBasicToken, int *pToken) const;
void RequestCurrentServer(const NETADDR &Addr) const;
void RequestCurrentServerWithRandomToken(const NETADDR &Addr, int *pBasicToken, int *pToken) const;
void SetCurrentServerPing(const NETADDR &Addr, int Ping);
void SetBaseInfo(class CNetClient *pClient, const char *pNetVersion);
@ -221,7 +222,7 @@ private:
void RemoveRequest(CServerEntry *pEntry);
void RequestImpl(const NETADDR &Addr, CServerEntry *pEntry, int *pBasicToken, int *pToken) const;
void RequestImpl(const NETADDR &Addr, CServerEntry *pEntry, int *pBasicToken, int *pToken, bool RandomToken) const;
void RegisterCommands();
static void Con_LeakIpAddress(IConsole::IResult *pResult, void *pUserData);