mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-19 14:38:18 +00:00
Added response token and CNetTokenManager
Conflicts: src/engine/shared/network_client.cpp
This commit is contained in:
parent
eaa036ed0f
commit
2ba3cf859f
|
@ -82,6 +82,7 @@ int CNetRecvUnpacker::FetchChunk(CNetChunk *pChunk)
|
|||
pChunk->m_Flags = Header.m_Flags;
|
||||
pChunk->m_DataSize = Header.m_Size;
|
||||
pChunk->m_pData = pData;
|
||||
pChunk->m_ResponseToken = NET_TOKEN_NONE;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,10 +103,11 @@ typedef int (*NETFUNC_NEWCLIENT)(int ClientID, void *pUser);
|
|||
|
||||
struct CNetChunk
|
||||
{
|
||||
// -1 means that it's a stateless packet
|
||||
// -1 means that it's a connless packet
|
||||
// 0 on the client means the server
|
||||
int m_ClientID;
|
||||
NETADDR m_Address; // only used when client_id == -1
|
||||
NETADDR m_Address; // only used when cid == -1
|
||||
unsigned int m_ResponseToken; // only used when cid == -1
|
||||
int m_Flags;
|
||||
int m_DataSize;
|
||||
const void *m_pData;
|
||||
|
@ -149,6 +150,28 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class CNetTokenManager
|
||||
{
|
||||
public:
|
||||
void Init(NETSOCKET Socket);
|
||||
|
||||
void GenerateSeed();
|
||||
|
||||
void ProcessTokenMessage(const NETADDR *pAddr, const CNetPacketConstruct *pPacket);
|
||||
|
||||
bool CheckToken(const NETADDR *pAddr, unsigned int Token, unsigned int ResponseToken);
|
||||
bool ConnectionToken(unsigned int Token);
|
||||
|
||||
static unsigned int GenerateToken(const NETADDR *pAddr, int64 Seed);
|
||||
|
||||
private:
|
||||
NETSOCKET m_Socket;
|
||||
|
||||
int64 m_Seed;
|
||||
int64 m_PrevSeed;
|
||||
};
|
||||
|
||||
|
||||
class CNetConnection
|
||||
{
|
||||
// TODO: is this needed because this needs to be aware of
|
||||
|
@ -292,6 +315,8 @@ class CNetServer
|
|||
|
||||
CNetRecvUnpacker m_RecvUnpacker;
|
||||
|
||||
CNetTokenManager m_TokenManager;
|
||||
|
||||
public:
|
||||
int SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser);
|
||||
|
||||
|
@ -335,6 +360,8 @@ class CNetConsole
|
|||
|
||||
CNetRecvUnpacker m_RecvUnpacker;
|
||||
|
||||
CNetTokenManager m_TokenManager;
|
||||
|
||||
public:
|
||||
void SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser);
|
||||
|
||||
|
|
|
@ -17,6 +17,9 @@ bool CNetClient::Open(NETADDR BindAddr, int Flags)
|
|||
// init
|
||||
m_Socket = Socket;
|
||||
m_Connection.Init(m_Socket, false);
|
||||
|
||||
m_TokenManager.Init(Socket);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int Ma
|
|||
if(!m_Socket.type)
|
||||
return false;
|
||||
|
||||
m_TokenManager.Init(m_Socket);
|
||||
|
||||
m_pNetBan = pNetBan;
|
||||
|
||||
// clamp clients
|
||||
|
@ -126,6 +128,7 @@ int CNetServer::Recv(CNetChunk *pChunk)
|
|||
pChunk->m_Address = Addr;
|
||||
pChunk->m_DataSize = m_RecvUnpacker.m_Data.m_DataSize;
|
||||
pChunk->m_pData = m_RecvUnpacker.m_Data.m_aChunkData;
|
||||
pChunk->m_ResponseToken = m_RecvUnpacker.m_Data.m_ResponseToken;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
|
106
src/engine/shared/network_token.cpp
Normal file
106
src/engine/shared/network_token.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||
|
||||
#include <stdlib.h> // rand
|
||||
|
||||
#include <base/system.h>
|
||||
|
||||
#include <engine/external/md5/md5.h>
|
||||
|
||||
#include "network.h"
|
||||
|
||||
static unsigned int Hash(char *pData, int Size)
|
||||
{
|
||||
md5_state_t State;
|
||||
unsigned int Result;
|
||||
md5_byte_t aDigest[sizeof(Result)];
|
||||
|
||||
md5_init(&State);
|
||||
md5_append(&State, (const md5_byte_t *)pData, Size);
|
||||
md5_finish(&State, aDigest);
|
||||
|
||||
mem_copy(&Result, aDigest, sizeof(Result));
|
||||
return Result;
|
||||
}
|
||||
|
||||
void CNetTokenManager::Init(NETSOCKET Socket)
|
||||
{
|
||||
m_Socket = Socket;
|
||||
GenerateSeed();
|
||||
}
|
||||
|
||||
int CNetTokenManager::ProcessMessage(const NETADDR *pAddr, const CNetPacketConstruct *pPacket)
|
||||
{
|
||||
if(pPacket->m_Token != NET_TOKEN_NONE && !CheckToken(pAddr, pPacket->m_Token))
|
||||
return 0; // wrong token, silent ignore
|
||||
|
||||
bool Verified = pPacket->m_Token != NET_TOKEN_NONE;
|
||||
bool TokenMessage = (pPacket->m_Flags & NET_PACKETFLAG_CONTROL)
|
||||
&& pPacket->m_aChunkData[0] == NET_CTRLMSG_TOKEN;
|
||||
|
||||
if(pPacket->m_Flags&NETSENDFLAG_CONNLESS)
|
||||
return (Verified) ? 1 : -1; // connless packets without token are allowed
|
||||
|
||||
if(!TokenMessage)
|
||||
if(Verified)
|
||||
return 1; // verified packet
|
||||
else
|
||||
// the only allowed not connless packet
|
||||
// without token is NET_CTRLMSG_TOKEN
|
||||
return 0;
|
||||
|
||||
if(Verified && TokenMessage)
|
||||
return 0; // everything is fine, token exchange complete
|
||||
|
||||
// client requesting token
|
||||
unsigned int RemoteToken = (pPacket->m_aChunkData[0]<<24)
|
||||
| (pPacket->m_aChunkData[1]<<16)
|
||||
| (pPacket->m_aChunkData[2]<<8)
|
||||
| (pPacket->m_aChunkData[3]);
|
||||
|
||||
CNetBase::SendToken(m_Socket, (NETADDR *)pAddr, GenerateToken(pAddr, m_Seed), RemoteToken);
|
||||
return 0; // no need to process NET_CTRLMSG_TOKEN further
|
||||
}
|
||||
|
||||
void CNetTokenManager::GenerateSeed()
|
||||
{
|
||||
m_PrevSeed = m_Seed;
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
// rand() returns a random integer between 0 and RAND_MAX
|
||||
// RAND_MAX is at least 1<<16 according to the standard
|
||||
m_Seed <<= 16;
|
||||
m_Seed ^= rand();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int CNetTokenManager::GenerateToken(const NETADDR *pAddr, int64 Seed)
|
||||
{
|
||||
char aBuf[sizeof(NETADDR) + sizeof(int64)];
|
||||
int Result;
|
||||
|
||||
mem_copy(aBuf, pAddr, sizeof(NETADDR));
|
||||
mem_copy(aBuf + sizeof(NETADDR), &Seed, sizeof(int64));
|
||||
|
||||
Result = Hash(aBuf, sizeof(aBuf));
|
||||
if(Result == NET_TOKEN_NONE)
|
||||
Result++;
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool CNetTokenManager::CheckToken(const NETADDR *pAddr, unsigned int Token, unsigned int ResponseToken)
|
||||
{
|
||||
unsigned int CurrentToken = GenerateToken(pAddr, m_Seed);
|
||||
if(CurrentToken == Token)
|
||||
return true;
|
||||
|
||||
if(GenerateToken(pAddr, m_PrevSeed) == Token)
|
||||
{
|
||||
CNetBase::SendToken(m_Socket, (NETADDR *)pAddr, CurrentToken, ResponseToken); // notify the peer about the new token
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in a new issue