mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-19 22:48:18 +00:00
increased the token size to 32bit and set a minimum datasize of 512bytes for token request to counter reflection attacks. #1681
This commit is contained in:
parent
646d055a59
commit
27c6f8ae46
|
@ -97,14 +97,15 @@ void CNetBase::SendPacketConnless(NETSOCKET Socket, const NETADDR *pAddr, TOKEN
|
|||
dbg_assert((ResponseToken&~NET_TOKEN_MASK) == 0, "resp token out of range");
|
||||
|
||||
int i = 0;
|
||||
aBuffer[i++] = (Token>>12)&0xff; // token
|
||||
aBuffer[i++] = (Token>>4)&0xff;
|
||||
aBuffer[i++] = ((Token&0xf)<<4)
|
||||
| (NET_PACKETFLAG_CONNLESS&0xf); // connless flag
|
||||
aBuffer[i++] = ((NET_PACKETVERSION&0x0f)<<4) // version
|
||||
| ((ResponseToken>>16)&0xf); // response token
|
||||
aBuffer[i++] = (Token>>24)&0xff; // token
|
||||
aBuffer[i++] = (Token>>16)&0xff;
|
||||
aBuffer[i++] = (Token>>8)&0xff;
|
||||
aBuffer[i++] = (Token)&0xff;
|
||||
aBuffer[i++] = ((NET_PACKETFLAG_CONNLESS<<2)&0xfc) | (NET_PACKETVERSION&0x03); // connless flag and version
|
||||
aBuffer[i++] = (ResponseToken>>24)&0xff; // response token
|
||||
aBuffer[i++] = (ResponseToken>>16)&0xff;
|
||||
aBuffer[i++] = (ResponseToken>>8)&0xff;
|
||||
aBuffer[i++] = ResponseToken&0xff;
|
||||
aBuffer[i++] = (ResponseToken)&0xff;
|
||||
|
||||
dbg_assert(i == NET_PACKETHEADERSIZE_CONNLESS, "inconsistency");
|
||||
|
||||
|
@ -154,13 +155,13 @@ void CNetBase::SendPacket(NETSOCKET Socket, const NETADDR *pAddr, CNetPacketCons
|
|||
FinalSize += NET_PACKETHEADERSIZE;
|
||||
|
||||
int i = 0;
|
||||
aBuffer[i++] = (pPacket->m_Token>>12)&0xff; // token
|
||||
aBuffer[i++] = (pPacket->m_Token>>4)&0xff;
|
||||
aBuffer[i++] = ((pPacket->m_Token<<4)&0xf0)
|
||||
| ((pPacket->m_Flags)&0xf); // flags
|
||||
aBuffer[i++] = (pPacket->m_Ack>>2)&0xff; // ack
|
||||
aBuffer[i++] = ((pPacket->m_Ack<<6)&0xc0)
|
||||
| (pPacket->m_NumChunks&0x3f);
|
||||
aBuffer[i++] = (pPacket->m_Token>>24)&0xff; // token
|
||||
aBuffer[i++] = (pPacket->m_Token>>16)&0xff;
|
||||
aBuffer[i++] = (pPacket->m_Token>>8)&0xff;
|
||||
aBuffer[i++] = (pPacket->m_Token)&0xff;
|
||||
aBuffer[i++] = ((pPacket->m_Flags<<2)&0xfc) | ((pPacket->m_Ack>>8)&0x03); // flags and ack
|
||||
aBuffer[i++] = (pPacket->m_Ack)&0xff; // ack
|
||||
aBuffer[i++] = (pPacket->m_NumChunks)&0xff; // num chunks
|
||||
|
||||
dbg_assert(i == NET_PACKETHEADERSIZE, "inconsistency");
|
||||
|
||||
|
@ -200,11 +201,10 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct
|
|||
}
|
||||
|
||||
// read the packet
|
||||
pPacket->m_Token = (pBuffer[0]<<12) | (pBuffer[1]<<4) | (pBuffer[2]>>4);
|
||||
// TTTTTTTT TTTTTTTT TTTTxxxx
|
||||
pPacket->m_Flags = pBuffer[2]&0x0f;
|
||||
// xxxxFFFF
|
||||
|
||||
pPacket->m_Token = (pBuffer[0]<<24) | (pBuffer[1]<<16) | (pBuffer[2]<<8) | pBuffer[3];
|
||||
// TTTTTTTT TTTTTTTT TTTTTTTT TTTTTTTT
|
||||
pPacket->m_Flags = (pBuffer[4]&0xfc)>>2;
|
||||
// FFFFFFxx
|
||||
if(pPacket->m_Flags&NET_PACKETFLAG_CONNLESS)
|
||||
{
|
||||
if(Size < NET_PACKETHEADERSIZE_CONNLESS)
|
||||
|
@ -217,15 +217,15 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct
|
|||
pPacket->m_Flags = NET_PACKETFLAG_CONNLESS;
|
||||
pPacket->m_Ack = 0;
|
||||
pPacket->m_NumChunks = 0;
|
||||
int Version = (pBuffer[3]>>4);
|
||||
// VVVVxxxx
|
||||
int Version = pBuffer[4]&0x3;
|
||||
// xxxxxxVV
|
||||
|
||||
if(Version != NET_PACKETVERSION)
|
||||
return -1;
|
||||
|
||||
pPacket->m_DataSize = Size - NET_PACKETHEADERSIZE_CONNLESS;
|
||||
pPacket->m_ResponseToken = ((pBuffer[3]&0x0f)<<16) | (pBuffer[4]<<8) | pBuffer[5];
|
||||
// xxxxRRRR RRRRRRRR RRRRRRRR
|
||||
pPacket->m_ResponseToken = (pBuffer[5]<<24) | (pBuffer[6]<<16) | (pBuffer[7]<<8) | pBuffer[8];
|
||||
// RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR
|
||||
mem_copy(pPacket->m_aChunkData, &pBuffer[NET_PACKETHEADERSIZE_CONNLESS], pPacket->m_DataSize);
|
||||
}
|
||||
else
|
||||
|
@ -237,10 +237,10 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct
|
|||
return -1;
|
||||
}
|
||||
|
||||
pPacket->m_Ack = (pBuffer[3]<<2) | ((pBuffer[4]&0xc0)>>6);
|
||||
// AAAAAAAA AAxxxxxx
|
||||
pPacket->m_NumChunks = pBuffer[4]&0x3f;
|
||||
// xxNNNNNN
|
||||
pPacket->m_Ack = ((pBuffer[4]&0x3)<<2) | pBuffer[5];
|
||||
// xxxxxxAA AAAAAAAA
|
||||
pPacket->m_NumChunks = pBuffer[6];
|
||||
// NNNNNNNN
|
||||
|
||||
pPacket->m_DataSize = Size - NET_PACKETHEADERSIZE;
|
||||
pPacket->m_ResponseToken = NET_TOKEN_NONE;
|
||||
|
@ -262,13 +262,13 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct
|
|||
// set the response token (a bit hacky because this function shouldn't know about control packets)
|
||||
if(pPacket->m_Flags&NET_PACKETFLAG_CONTROL)
|
||||
{
|
||||
if(pPacket->m_DataSize >= 4) // control byte + token
|
||||
if(pPacket->m_DataSize >= 5) // control byte + token
|
||||
{
|
||||
if(pPacket->m_aChunkData[0] == NET_CTRLMSG_CONNECT
|
||||
|| pPacket->m_aChunkData[0] == NET_CTRLMSG_TOKEN)
|
||||
{
|
||||
pPacket->m_ResponseToken = ((pPacket->m_aChunkData[1]&0xf)<<16)
|
||||
| (pPacket->m_aChunkData[2]<<8) | pPacket->m_aChunkData[3];
|
||||
pPacket->m_ResponseToken = (pPacket->m_aChunkData[1]<<24) | (pPacket->m_aChunkData[2]<<16)
|
||||
| (pPacket->m_aChunkData[3]<<8) | pPacket->m_aChunkData[4];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -304,17 +304,17 @@ void CNetBase::SendControlMsg(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Toke
|
|||
}
|
||||
|
||||
|
||||
void CNetBase::SendControlMsgWithToken(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, TOKEN MyToken)
|
||||
void CNetBase::SendControlMsgWithToken(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, TOKEN MyToken, bool Extended)
|
||||
{
|
||||
dbg_assert((Token&~NET_TOKEN_MASK) == 0, "token out of range");
|
||||
dbg_assert((MyToken&~NET_TOKEN_MASK) == 0, "resp token out of range");
|
||||
|
||||
unsigned char aToken[3];
|
||||
aToken[0] = (MyToken>>16)&0xff;
|
||||
aToken[1] = (MyToken>>8)&0xff;
|
||||
aToken[2] = (MyToken)&0xff;
|
||||
|
||||
SendControlMsg(Socket, pAddr, Token, 0, ControlMsg, aToken, sizeof(aToken));
|
||||
static unsigned char aBuf[NET_TOKENREQUEST_DATASIZE] = { 0 };
|
||||
aBuf[0] = (MyToken>>24)&0xff;
|
||||
aBuf[1] = (MyToken>>16)&0xff;
|
||||
aBuf[2] = (MyToken>>8)&0xff;
|
||||
aBuf[3] = (MyToken)&0xff;
|
||||
SendControlMsg(Socket, pAddr, Token, 0, ControlMsg, aBuf, Extended ? sizeof(aBuf) : 4);
|
||||
}
|
||||
|
||||
unsigned char *CNetChunkHeader::Pack(unsigned char *pData)
|
||||
|
|
|
@ -9,32 +9,36 @@
|
|||
/*
|
||||
|
||||
CURRENT:
|
||||
packet header: 5 bytes (6 bytes for connless)
|
||||
unsigned char token[2]; // 16bit token
|
||||
unsigned char token_flags; // 4bit token, 4bit flags
|
||||
unsigned char ack; // 8bit ack
|
||||
unsigned char ack_numchunks; // 2bit ack, 6bit chunks
|
||||
packet header: 7 bytes (9 bytes for connless)
|
||||
unsigned char token[4]; // 32bit token
|
||||
unsigned char flags; // 6bit flags, 2bit ack
|
||||
unsigned char ack; // 8bit ack
|
||||
unsigned char numchunks; // 8bit chunks
|
||||
// TTTTTTTT
|
||||
// TTTTTTTT
|
||||
// TTTTffff
|
||||
// TTTTTTTT
|
||||
// TTTTTTTT
|
||||
// ffffffaa
|
||||
// aaaaaaaa
|
||||
// aaNNNNNN
|
||||
// NNNNNNNN
|
||||
|
||||
packet header (CONNLESS):
|
||||
unsigned char token[2]; // 16bit token
|
||||
unsigned char token_flag; // 4bit token, 4bit flags
|
||||
unsigned char version_responsetoken; // 4bit version, 4bit response token
|
||||
unsigned char responsetoken[2]; // 16bit response token
|
||||
unsigned char token[4]; // 32bit token
|
||||
unsigned char flag_version; // 6bit flags, 2bits version
|
||||
unsigned char responsetoken[4]; // 32bit response token
|
||||
|
||||
// TTTTTTTT
|
||||
// TTTTTTTT
|
||||
// TTTTffff
|
||||
// vvvvRRRR
|
||||
// TTTTTTTT
|
||||
// TTTTTTTT
|
||||
// ffffffvv
|
||||
// RRRRRRRR
|
||||
// RRRRRRRR
|
||||
// RRRRRRRR
|
||||
// RRRRRRRR
|
||||
|
||||
if the token isn't explicitely set by any means, it must be set to
|
||||
0xfffff
|
||||
0xffffffff
|
||||
|
||||
chunk header: 2-3 bytes
|
||||
unsigned char flags_size; // 2bit flags, 6 bit size
|
||||
|
@ -62,13 +66,11 @@ enum
|
|||
|
||||
enum
|
||||
{
|
||||
NET_VERSION = 2,
|
||||
|
||||
NET_MAX_CHUNKHEADERSIZE = 3,
|
||||
|
||||
// packets
|
||||
NET_PACKETHEADERSIZE = 5,
|
||||
NET_PACKETHEADERSIZE_CONNLESS = NET_PACKETHEADERSIZE + 1,
|
||||
NET_PACKETHEADERSIZE = 7,
|
||||
NET_PACKETHEADERSIZE_CONNLESS = NET_PACKETHEADERSIZE + 2,
|
||||
NET_MAX_PACKETHEADERSIZE = NET_PACKETHEADERSIZE_CONNLESS,
|
||||
|
||||
NET_MAX_PACKETSIZE = 1400,
|
||||
|
@ -88,13 +90,15 @@ enum
|
|||
NET_TOKENCACHE_ADDRESSEXPIRY = NET_SEEDTIME,
|
||||
NET_TOKENCACHE_PACKETEXPIRY = 5,
|
||||
|
||||
NET_TOKEN_MAX = 0xfffff,
|
||||
NET_TOKEN_MAX = 0xffffffff,
|
||||
NET_TOKEN_NONE = NET_TOKEN_MAX,
|
||||
NET_TOKEN_MASK = NET_TOKEN_MAX,
|
||||
|
||||
NET_TOKENFLAG_ALLOWBROADCAST = 1,
|
||||
NET_TOKENFLAG_RESPONSEONLY = 2,
|
||||
|
||||
NET_TOKENREQUEST_DATASIZE = 512,
|
||||
|
||||
//
|
||||
NET_MAX_CLIENTS = 16,
|
||||
NET_MAX_CONSOLE_CLIENTS = 4,
|
||||
|
@ -536,7 +540,7 @@ public:
|
|||
static int Decompress(const void *pData, int DataSize, void *pOutput, int OutputSize);
|
||||
|
||||
static void SendControlMsg(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, const void *pExtra, int ExtraSize);
|
||||
static void SendControlMsgWithToken(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, TOKEN MyToken);
|
||||
static void SendControlMsgWithToken(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, TOKEN MyToken, bool Extended);
|
||||
static void SendPacketConnless(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, TOKEN ResponseToken, const void *pData, int DataSize);
|
||||
static void SendPacket(NETSOCKET Socket, const NETADDR *pAddr, CNetPacketConstruct *pPacket);
|
||||
static int UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct *pPacket);
|
||||
|
|
|
@ -174,7 +174,7 @@ void CNetConnection::SendPacketConnless(const char *pData, int DataSize)
|
|||
void CNetConnection::SendControlWithToken(int ControlMsg)
|
||||
{
|
||||
m_LastSendTime = time_get();
|
||||
CNetBase::SendControlMsgWithToken(m_Socket, &m_PeerAddr, m_PeerToken, 0, ControlMsg, m_Token);
|
||||
CNetBase::SendControlMsgWithToken(m_Socket, &m_PeerAddr, m_PeerToken, 0, ControlMsg, m_Token, true);
|
||||
}
|
||||
|
||||
void CNetConnection::ResendChunk(CNetChunkResend *pResend)
|
||||
|
|
|
@ -63,9 +63,12 @@ int CNetTokenManager::ProcessMessage(const NETADDR *pAddr, const CNetPacketConst
|
|||
return BroadcastResponse ? -1 : 1; // everything is fine, token exchange complete
|
||||
|
||||
// client requesting token
|
||||
CNetBase::SendControlMsgWithToken(m_Socket, (NETADDR *)pAddr,
|
||||
pPacket->m_ResponseToken, 0, NET_CTRLMSG_TOKEN,
|
||||
GenerateToken(pAddr));
|
||||
if(pPacket->m_DataSize >= NET_TOKENREQUEST_DATASIZE)
|
||||
{
|
||||
CNetBase::SendControlMsgWithToken(m_Socket, (NETADDR *)pAddr,
|
||||
pPacket->m_ResponseToken, 0, NET_CTRLMSG_TOKEN,
|
||||
GenerateToken(pAddr), false);
|
||||
}
|
||||
return 0; // no need to process NET_CTRLMSG_TOKEN further
|
||||
}
|
||||
|
||||
|
@ -96,7 +99,7 @@ TOKEN CNetTokenManager::GenerateToken(const NETADDR *pAddr, int64 Seed)
|
|||
static const NETADDR NullAddr = { 0 };
|
||||
NETADDR Addr;
|
||||
char aBuf[sizeof(NETADDR) + sizeof(int64)];
|
||||
int Result;
|
||||
unsigned int Result;
|
||||
|
||||
if(pAddr->type & NETTYPE_LINK_BROADCAST)
|
||||
return GenerateToken(&NullAddr, Seed);
|
||||
|
@ -252,7 +255,7 @@ TOKEN CNetTokenCache::GetToken(const NETADDR *pAddr)
|
|||
void CNetTokenCache::FetchToken(const NETADDR *pAddr)
|
||||
{
|
||||
CNetBase::SendControlMsgWithToken(m_Socket, pAddr, NET_TOKEN_NONE, 0,
|
||||
NET_CTRLMSG_TOKEN, m_pTokenManager->GenerateToken(pAddr));
|
||||
NET_CTRLMSG_TOKEN, m_pTokenManager->GenerateToken(pAddr), true);
|
||||
}
|
||||
|
||||
void CNetTokenCache::AddToken(const NETADDR *pAddr, TOKEN Token, int TokenFLag)
|
||||
|
|
Loading…
Reference in a new issue