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");
|
dbg_assert((ResponseToken&~NET_TOKEN_MASK) == 0, "resp token out of range");
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
aBuffer[i++] = (Token>>12)&0xff; // token
|
aBuffer[i++] = (Token>>24)&0xff; // token
|
||||||
aBuffer[i++] = (Token>>4)&0xff;
|
aBuffer[i++] = (Token>>16)&0xff;
|
||||||
aBuffer[i++] = ((Token&0xf)<<4)
|
aBuffer[i++] = (Token>>8)&0xff;
|
||||||
| (NET_PACKETFLAG_CONNLESS&0xf); // connless flag
|
aBuffer[i++] = (Token)&0xff;
|
||||||
aBuffer[i++] = ((NET_PACKETVERSION&0x0f)<<4) // version
|
aBuffer[i++] = ((NET_PACKETFLAG_CONNLESS<<2)&0xfc) | (NET_PACKETVERSION&0x03); // connless flag and version
|
||||||
| ((ResponseToken>>16)&0xf); // response token
|
aBuffer[i++] = (ResponseToken>>24)&0xff; // response token
|
||||||
|
aBuffer[i++] = (ResponseToken>>16)&0xff;
|
||||||
aBuffer[i++] = (ResponseToken>>8)&0xff;
|
aBuffer[i++] = (ResponseToken>>8)&0xff;
|
||||||
aBuffer[i++] = ResponseToken&0xff;
|
aBuffer[i++] = (ResponseToken)&0xff;
|
||||||
|
|
||||||
dbg_assert(i == NET_PACKETHEADERSIZE_CONNLESS, "inconsistency");
|
dbg_assert(i == NET_PACKETHEADERSIZE_CONNLESS, "inconsistency");
|
||||||
|
|
||||||
|
@ -154,13 +155,13 @@ void CNetBase::SendPacket(NETSOCKET Socket, const NETADDR *pAddr, CNetPacketCons
|
||||||
FinalSize += NET_PACKETHEADERSIZE;
|
FinalSize += NET_PACKETHEADERSIZE;
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
aBuffer[i++] = (pPacket->m_Token>>12)&0xff; // token
|
aBuffer[i++] = (pPacket->m_Token>>24)&0xff; // token
|
||||||
aBuffer[i++] = (pPacket->m_Token>>4)&0xff;
|
aBuffer[i++] = (pPacket->m_Token>>16)&0xff;
|
||||||
aBuffer[i++] = ((pPacket->m_Token<<4)&0xf0)
|
aBuffer[i++] = (pPacket->m_Token>>8)&0xff;
|
||||||
| ((pPacket->m_Flags)&0xf); // flags
|
aBuffer[i++] = (pPacket->m_Token)&0xff;
|
||||||
aBuffer[i++] = (pPacket->m_Ack>>2)&0xff; // ack
|
aBuffer[i++] = ((pPacket->m_Flags<<2)&0xfc) | ((pPacket->m_Ack>>8)&0x03); // flags and ack
|
||||||
aBuffer[i++] = ((pPacket->m_Ack<<6)&0xc0)
|
aBuffer[i++] = (pPacket->m_Ack)&0xff; // ack
|
||||||
| (pPacket->m_NumChunks&0x3f);
|
aBuffer[i++] = (pPacket->m_NumChunks)&0xff; // num chunks
|
||||||
|
|
||||||
dbg_assert(i == NET_PACKETHEADERSIZE, "inconsistency");
|
dbg_assert(i == NET_PACKETHEADERSIZE, "inconsistency");
|
||||||
|
|
||||||
|
@ -200,11 +201,10 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct
|
||||||
}
|
}
|
||||||
|
|
||||||
// read the packet
|
// read the packet
|
||||||
pPacket->m_Token = (pBuffer[0]<<12) | (pBuffer[1]<<4) | (pBuffer[2]>>4);
|
pPacket->m_Token = (pBuffer[0]<<24) | (pBuffer[1]<<16) | (pBuffer[2]<<8) | pBuffer[3];
|
||||||
// TTTTTTTT TTTTTTTT TTTTxxxx
|
// TTTTTTTT TTTTTTTT TTTTTTTT TTTTTTTT
|
||||||
pPacket->m_Flags = pBuffer[2]&0x0f;
|
pPacket->m_Flags = (pBuffer[4]&0xfc)>>2;
|
||||||
// xxxxFFFF
|
// FFFFFFxx
|
||||||
|
|
||||||
if(pPacket->m_Flags&NET_PACKETFLAG_CONNLESS)
|
if(pPacket->m_Flags&NET_PACKETFLAG_CONNLESS)
|
||||||
{
|
{
|
||||||
if(Size < NET_PACKETHEADERSIZE_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_Flags = NET_PACKETFLAG_CONNLESS;
|
||||||
pPacket->m_Ack = 0;
|
pPacket->m_Ack = 0;
|
||||||
pPacket->m_NumChunks = 0;
|
pPacket->m_NumChunks = 0;
|
||||||
int Version = (pBuffer[3]>>4);
|
int Version = pBuffer[4]&0x3;
|
||||||
// VVVVxxxx
|
// xxxxxxVV
|
||||||
|
|
||||||
if(Version != NET_PACKETVERSION)
|
if(Version != NET_PACKETVERSION)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
pPacket->m_DataSize = Size - NET_PACKETHEADERSIZE_CONNLESS;
|
pPacket->m_DataSize = Size - NET_PACKETHEADERSIZE_CONNLESS;
|
||||||
pPacket->m_ResponseToken = ((pBuffer[3]&0x0f)<<16) | (pBuffer[4]<<8) | pBuffer[5];
|
pPacket->m_ResponseToken = (pBuffer[5]<<24) | (pBuffer[6]<<16) | (pBuffer[7]<<8) | pBuffer[8];
|
||||||
// xxxxRRRR RRRRRRRR RRRRRRRR
|
// RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR
|
||||||
mem_copy(pPacket->m_aChunkData, &pBuffer[NET_PACKETHEADERSIZE_CONNLESS], pPacket->m_DataSize);
|
mem_copy(pPacket->m_aChunkData, &pBuffer[NET_PACKETHEADERSIZE_CONNLESS], pPacket->m_DataSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -237,10 +237,10 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pPacket->m_Ack = (pBuffer[3]<<2) | ((pBuffer[4]&0xc0)>>6);
|
pPacket->m_Ack = ((pBuffer[4]&0x3)<<2) | pBuffer[5];
|
||||||
// AAAAAAAA AAxxxxxx
|
// xxxxxxAA AAAAAAAA
|
||||||
pPacket->m_NumChunks = pBuffer[4]&0x3f;
|
pPacket->m_NumChunks = pBuffer[6];
|
||||||
// xxNNNNNN
|
// NNNNNNNN
|
||||||
|
|
||||||
pPacket->m_DataSize = Size - NET_PACKETHEADERSIZE;
|
pPacket->m_DataSize = Size - NET_PACKETHEADERSIZE;
|
||||||
pPacket->m_ResponseToken = NET_TOKEN_NONE;
|
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)
|
// 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_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
|
if(pPacket->m_aChunkData[0] == NET_CTRLMSG_CONNECT
|
||||||
|| pPacket->m_aChunkData[0] == NET_CTRLMSG_TOKEN)
|
|| pPacket->m_aChunkData[0] == NET_CTRLMSG_TOKEN)
|
||||||
{
|
{
|
||||||
pPacket->m_ResponseToken = ((pPacket->m_aChunkData[1]&0xf)<<16)
|
pPacket->m_ResponseToken = (pPacket->m_aChunkData[1]<<24) | (pPacket->m_aChunkData[2]<<16)
|
||||||
| (pPacket->m_aChunkData[2]<<8) | pPacket->m_aChunkData[3];
|
| (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((Token&~NET_TOKEN_MASK) == 0, "token out of range");
|
||||||
dbg_assert((MyToken&~NET_TOKEN_MASK) == 0, "resp token out of range");
|
dbg_assert((MyToken&~NET_TOKEN_MASK) == 0, "resp token out of range");
|
||||||
|
|
||||||
unsigned char aToken[3];
|
static unsigned char aBuf[NET_TOKENREQUEST_DATASIZE] = { 0 };
|
||||||
aToken[0] = (MyToken>>16)&0xff;
|
aBuf[0] = (MyToken>>24)&0xff;
|
||||||
aToken[1] = (MyToken>>8)&0xff;
|
aBuf[1] = (MyToken>>16)&0xff;
|
||||||
aToken[2] = (MyToken)&0xff;
|
aBuf[2] = (MyToken>>8)&0xff;
|
||||||
|
aBuf[3] = (MyToken)&0xff;
|
||||||
SendControlMsg(Socket, pAddr, Token, 0, ControlMsg, aToken, sizeof(aToken));
|
SendControlMsg(Socket, pAddr, Token, 0, ControlMsg, aBuf, Extended ? sizeof(aBuf) : 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *CNetChunkHeader::Pack(unsigned char *pData)
|
unsigned char *CNetChunkHeader::Pack(unsigned char *pData)
|
||||||
|
|
|
@ -9,32 +9,36 @@
|
||||||
/*
|
/*
|
||||||
|
|
||||||
CURRENT:
|
CURRENT:
|
||||||
packet header: 5 bytes (6 bytes for connless)
|
packet header: 7 bytes (9 bytes for connless)
|
||||||
unsigned char token[2]; // 16bit token
|
unsigned char token[4]; // 32bit token
|
||||||
unsigned char token_flags; // 4bit token, 4bit flags
|
unsigned char flags; // 6bit flags, 2bit ack
|
||||||
unsigned char ack; // 8bit ack
|
unsigned char ack; // 8bit ack
|
||||||
unsigned char ack_numchunks; // 2bit ack, 6bit chunks
|
unsigned char numchunks; // 8bit chunks
|
||||||
// TTTTTTTT
|
// TTTTTTTT
|
||||||
// TTTTTTTT
|
// TTTTTTTT
|
||||||
// TTTTffff
|
// TTTTTTTT
|
||||||
|
// TTTTTTTT
|
||||||
|
// ffffffaa
|
||||||
// aaaaaaaa
|
// aaaaaaaa
|
||||||
// aaNNNNNN
|
// NNNNNNNN
|
||||||
|
|
||||||
packet header (CONNLESS):
|
packet header (CONNLESS):
|
||||||
unsigned char token[2]; // 16bit token
|
unsigned char token[4]; // 32bit token
|
||||||
unsigned char token_flag; // 4bit token, 4bit flags
|
unsigned char flag_version; // 6bit flags, 2bits version
|
||||||
unsigned char version_responsetoken; // 4bit version, 4bit response token
|
unsigned char responsetoken[4]; // 32bit response token
|
||||||
unsigned char responsetoken[2]; // 16bit response token
|
|
||||||
|
|
||||||
// TTTTTTTT
|
// TTTTTTTT
|
||||||
// TTTTTTTT
|
// TTTTTTTT
|
||||||
// TTTTffff
|
// TTTTTTTT
|
||||||
// vvvvRRRR
|
// TTTTTTTT
|
||||||
|
// ffffffvv
|
||||||
|
// RRRRRRRR
|
||||||
|
// RRRRRRRR
|
||||||
// RRRRRRRR
|
// RRRRRRRR
|
||||||
// RRRRRRRR
|
// RRRRRRRR
|
||||||
|
|
||||||
if the token isn't explicitely set by any means, it must be set to
|
if the token isn't explicitely set by any means, it must be set to
|
||||||
0xfffff
|
0xffffffff
|
||||||
|
|
||||||
chunk header: 2-3 bytes
|
chunk header: 2-3 bytes
|
||||||
unsigned char flags_size; // 2bit flags, 6 bit size
|
unsigned char flags_size; // 2bit flags, 6 bit size
|
||||||
|
@ -62,13 +66,11 @@ enum
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
NET_VERSION = 2,
|
|
||||||
|
|
||||||
NET_MAX_CHUNKHEADERSIZE = 3,
|
NET_MAX_CHUNKHEADERSIZE = 3,
|
||||||
|
|
||||||
// packets
|
// packets
|
||||||
NET_PACKETHEADERSIZE = 5,
|
NET_PACKETHEADERSIZE = 7,
|
||||||
NET_PACKETHEADERSIZE_CONNLESS = NET_PACKETHEADERSIZE + 1,
|
NET_PACKETHEADERSIZE_CONNLESS = NET_PACKETHEADERSIZE + 2,
|
||||||
NET_MAX_PACKETHEADERSIZE = NET_PACKETHEADERSIZE_CONNLESS,
|
NET_MAX_PACKETHEADERSIZE = NET_PACKETHEADERSIZE_CONNLESS,
|
||||||
|
|
||||||
NET_MAX_PACKETSIZE = 1400,
|
NET_MAX_PACKETSIZE = 1400,
|
||||||
|
@ -88,13 +90,15 @@ enum
|
||||||
NET_TOKENCACHE_ADDRESSEXPIRY = NET_SEEDTIME,
|
NET_TOKENCACHE_ADDRESSEXPIRY = NET_SEEDTIME,
|
||||||
NET_TOKENCACHE_PACKETEXPIRY = 5,
|
NET_TOKENCACHE_PACKETEXPIRY = 5,
|
||||||
|
|
||||||
NET_TOKEN_MAX = 0xfffff,
|
NET_TOKEN_MAX = 0xffffffff,
|
||||||
NET_TOKEN_NONE = NET_TOKEN_MAX,
|
NET_TOKEN_NONE = NET_TOKEN_MAX,
|
||||||
NET_TOKEN_MASK = NET_TOKEN_MAX,
|
NET_TOKEN_MASK = NET_TOKEN_MAX,
|
||||||
|
|
||||||
NET_TOKENFLAG_ALLOWBROADCAST = 1,
|
NET_TOKENFLAG_ALLOWBROADCAST = 1,
|
||||||
NET_TOKENFLAG_RESPONSEONLY = 2,
|
NET_TOKENFLAG_RESPONSEONLY = 2,
|
||||||
|
|
||||||
|
NET_TOKENREQUEST_DATASIZE = 512,
|
||||||
|
|
||||||
//
|
//
|
||||||
NET_MAX_CLIENTS = 16,
|
NET_MAX_CLIENTS = 16,
|
||||||
NET_MAX_CONSOLE_CLIENTS = 4,
|
NET_MAX_CONSOLE_CLIENTS = 4,
|
||||||
|
@ -536,7 +540,7 @@ public:
|
||||||
static int Decompress(const void *pData, int DataSize, void *pOutput, int OutputSize);
|
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 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 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 void SendPacket(NETSOCKET Socket, const NETADDR *pAddr, CNetPacketConstruct *pPacket);
|
||||||
static int UnpackPacket(unsigned char *pBuffer, int Size, 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)
|
void CNetConnection::SendControlWithToken(int ControlMsg)
|
||||||
{
|
{
|
||||||
m_LastSendTime = time_get();
|
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)
|
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
|
return BroadcastResponse ? -1 : 1; // everything is fine, token exchange complete
|
||||||
|
|
||||||
// client requesting token
|
// client requesting token
|
||||||
|
if(pPacket->m_DataSize >= NET_TOKENREQUEST_DATASIZE)
|
||||||
|
{
|
||||||
CNetBase::SendControlMsgWithToken(m_Socket, (NETADDR *)pAddr,
|
CNetBase::SendControlMsgWithToken(m_Socket, (NETADDR *)pAddr,
|
||||||
pPacket->m_ResponseToken, 0, NET_CTRLMSG_TOKEN,
|
pPacket->m_ResponseToken, 0, NET_CTRLMSG_TOKEN,
|
||||||
GenerateToken(pAddr));
|
GenerateToken(pAddr), false);
|
||||||
|
}
|
||||||
return 0; // no need to process NET_CTRLMSG_TOKEN further
|
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 };
|
static const NETADDR NullAddr = { 0 };
|
||||||
NETADDR Addr;
|
NETADDR Addr;
|
||||||
char aBuf[sizeof(NETADDR) + sizeof(int64)];
|
char aBuf[sizeof(NETADDR) + sizeof(int64)];
|
||||||
int Result;
|
unsigned int Result;
|
||||||
|
|
||||||
if(pAddr->type & NETTYPE_LINK_BROADCAST)
|
if(pAddr->type & NETTYPE_LINK_BROADCAST)
|
||||||
return GenerateToken(&NullAddr, Seed);
|
return GenerateToken(&NullAddr, Seed);
|
||||||
|
@ -252,7 +255,7 @@ TOKEN CNetTokenCache::GetToken(const NETADDR *pAddr)
|
||||||
void CNetTokenCache::FetchToken(const NETADDR *pAddr)
|
void CNetTokenCache::FetchToken(const NETADDR *pAddr)
|
||||||
{
|
{
|
||||||
CNetBase::SendControlMsgWithToken(m_Socket, pAddr, NET_TOKEN_NONE, 0,
|
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)
|
void CNetTokenCache::AddToken(const NETADDR *pAddr, TOKEN Token, int TokenFLag)
|
||||||
|
|
Loading…
Reference in a new issue