mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Merge pull request #160 from heinrich5991/pr_ddnet_random_windows
Make the secure random stuff platform-independent
This commit is contained in:
commit
1d061986d3
1
bam.lua
1
bam.lua
|
@ -240,6 +240,7 @@ function build(settings)
|
||||||
settings.link.libs:Add("ws2_32")
|
settings.link.libs:Add("ws2_32")
|
||||||
settings.link.libs:Add("ole32")
|
settings.link.libs:Add("ole32")
|
||||||
settings.link.libs:Add("shell32")
|
settings.link.libs:Add("shell32")
|
||||||
|
settings.link.libs:Add("advapi32")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- compile zlib if needed
|
-- compile zlib if needed
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
#include <wincrypt.h>
|
||||||
#else
|
#else
|
||||||
#error NOT IMPLEMENTED
|
#error NOT IMPLEMENTED
|
||||||
#endif
|
#endif
|
||||||
|
@ -2355,6 +2356,70 @@ void shell_execute(const char *file, const char *argv)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SECURE_RANDOM_DATA
|
||||||
|
{
|
||||||
|
int initialized;
|
||||||
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
|
HCRYPTPROV provider;
|
||||||
|
#else
|
||||||
|
IOHANDLE urandom;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct SECURE_RANDOM_DATA secure_random_data = { 0 };
|
||||||
|
|
||||||
|
int secure_random_init()
|
||||||
|
{
|
||||||
|
if(secure_random_data.initialized)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
|
if(CryptAcquireContext(&secure_random_data.provider, NULL, NULL, PROV_RSA_FULL, 0))
|
||||||
|
{
|
||||||
|
secure_random_data.initialized = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
secure_random_data.urandom = io_open("/dev/urandom", IOFLAG_READ);
|
||||||
|
if(secure_random_data.urandom)
|
||||||
|
{
|
||||||
|
secure_random_data.initialized = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void secure_random_fill(unsigned char *bytes, size_t length)
|
||||||
|
{
|
||||||
|
if(!secure_random_data.initialized)
|
||||||
|
{
|
||||||
|
dbg_msg("secure", "called secure_random_fill before secure_random_init");
|
||||||
|
dbg_break();
|
||||||
|
}
|
||||||
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
|
if(!CryptGenRandom(secure_random_data.provider, length, bytes))
|
||||||
|
{
|
||||||
|
dbg_msg("secure", "CryptGenRandom failed, last_error=%d", GetLastError());
|
||||||
|
dbg_break();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if(length != io_read(secure_random_data.urandom, bytes, length))
|
||||||
|
{
|
||||||
|
dbg_msg("secure", "io_read returned with a short read");
|
||||||
|
dbg_break();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1328,6 +1328,27 @@ int pid();
|
||||||
|
|
||||||
void shell_execute(const char *file, const char *argv);
|
void shell_execute(const char *file, const char *argv);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: secure_random_init
|
||||||
|
Initializes the secure random module.
|
||||||
|
You *MUST* check the return value of this function.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
0 - Initialization succeeded.
|
||||||
|
1 - Initialization failed.
|
||||||
|
*/
|
||||||
|
int secure_random_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: secure_random_fill
|
||||||
|
Fills the buffer with the specified amount of random bytes.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
buffer - Pointer to the start of the buffer.
|
||||||
|
length - Length of the buffer.
|
||||||
|
*/
|
||||||
|
void secure_random_fill(unsigned char *bytes, size_t length);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -101,7 +101,7 @@ void CNetBase::SendPacketConnless(NETSOCKET Socket, NETADDR *pAddr, const void *
|
||||||
net_udp_send(Socket, pAddr, aBuffer, 6+DataSize);
|
net_udp_send(Socket, pAddr, aBuffer, 6+DataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNetBase::SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct *pPacket)
|
void CNetBase::SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct *pPacket, SECURITY_TOKEN SecurityToken)
|
||||||
{
|
{
|
||||||
unsigned char aBuffer[NET_MAX_PACKETSIZE];
|
unsigned char aBuffer[NET_MAX_PACKETSIZE];
|
||||||
int CompressedSize = -1;
|
int CompressedSize = -1;
|
||||||
|
@ -117,6 +117,14 @@ void CNetBase::SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct
|
||||||
io_flush(ms_DataLogSent);
|
io_flush(ms_DataLogSent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SecurityToken != NET_SECURITY_TOKEN_UNSUPPORTED)
|
||||||
|
{
|
||||||
|
// append security token
|
||||||
|
// if SecurityToken is NET_SECURITY_TOKEN_UNKNOWN we will still append it hoping to negotiate it
|
||||||
|
mem_copy(&pPacket->m_aChunkData[pPacket->m_DataSize], &SecurityToken, sizeof(SecurityToken));
|
||||||
|
pPacket->m_DataSize += sizeof(SecurityToken);
|
||||||
|
}
|
||||||
|
|
||||||
// compress
|
// compress
|
||||||
CompressedSize = ms_Huffman.Compress(pPacket->m_aChunkData, pPacket->m_DataSize, &aBuffer[3], NET_MAX_PACKETSIZE-4);
|
CompressedSize = ms_Huffman.Compress(pPacket->m_aChunkData, pPacket->m_DataSize, &aBuffer[3], NET_MAX_PACKETSIZE-4);
|
||||||
|
|
||||||
|
@ -228,7 +236,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CNetBase::SendControlMsg(NETSOCKET Socket, NETADDR *pAddr, int Ack, int ControlMsg, const void *pExtra, int ExtraSize)
|
void CNetBase::SendControlMsg(NETSOCKET Socket, NETADDR *pAddr, int Ack, int ControlMsg, const void *pExtra, int ExtraSize, SECURITY_TOKEN SecurityToken)
|
||||||
{
|
{
|
||||||
CNetPacketConstruct Construct;
|
CNetPacketConstruct Construct;
|
||||||
Construct.m_Flags = NET_PACKETFLAG_CONTROL;
|
Construct.m_Flags = NET_PACKETFLAG_CONTROL;
|
||||||
|
@ -239,7 +247,7 @@ void CNetBase::SendControlMsg(NETSOCKET Socket, NETADDR *pAddr, int Ack, int Con
|
||||||
mem_copy(&Construct.m_aChunkData[1], pExtra, ExtraSize);
|
mem_copy(&Construct.m_aChunkData[1], pExtra, ExtraSize);
|
||||||
|
|
||||||
// send the control message
|
// send the control message
|
||||||
CNetBase::SendPacket(Socket, pAddr, &Construct);
|
CNetBase::SendPacket(Socket, pAddr, &Construct, SecurityToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,15 @@ enum
|
||||||
NET_ENUM_TERMINATOR
|
NET_ENUM_TERMINATOR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef int SECURITY_TOKEN;
|
||||||
|
|
||||||
|
static const unsigned char SECURITY_TOKEN_MAGIC[] = {'T', 'K', 'E', 'N'};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
NET_SECURITY_TOKEN_UNKNOWN = -1,
|
||||||
|
NET_SECURITY_TOKEN_UNSUPPORTED = 0,
|
||||||
|
};
|
||||||
|
|
||||||
typedef int (*NETFUNC_DELCLIENT)(int ClientID, const char* pReason, void *pUser);
|
typedef int (*NETFUNC_DELCLIENT)(int ClientID, const char* pReason, void *pUser);
|
||||||
typedef int (*NETFUNC_NEWCLIENT)(int ClientID, void *pUser);
|
typedef int (*NETFUNC_NEWCLIENT)(int ClientID, void *pUser);
|
||||||
|
@ -139,6 +148,7 @@ private:
|
||||||
unsigned m_State;
|
unsigned m_State;
|
||||||
|
|
||||||
int m_Token;
|
int m_Token;
|
||||||
|
SECURITY_TOKEN m_SecurityToken;
|
||||||
int m_RemoteClosed;
|
int m_RemoteClosed;
|
||||||
bool m_BlockCloseMsg;
|
bool m_BlockCloseMsg;
|
||||||
|
|
||||||
|
@ -178,7 +188,7 @@ public:
|
||||||
int Update();
|
int Update();
|
||||||
int Flush();
|
int Flush();
|
||||||
|
|
||||||
int Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr);
|
int Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr, SECURITY_TOKEN SecurityToken = NET_SECURITY_TOKEN_UNSUPPORTED);
|
||||||
int QueueChunk(int Flags, int DataSize, const void *pData);
|
int QueueChunk(int Flags, int DataSize, const void *pData);
|
||||||
|
|
||||||
const char *ErrorString();
|
const char *ErrorString();
|
||||||
|
@ -265,6 +275,8 @@ class CNetServer
|
||||||
NETFUNC_DELCLIENT m_pfnDelClient;
|
NETFUNC_DELCLIENT m_pfnDelClient;
|
||||||
void *m_UserPtr;
|
void *m_UserPtr;
|
||||||
|
|
||||||
|
unsigned char m_SecurityTokenSeed[16];
|
||||||
|
|
||||||
CNetRecvUnpacker m_RecvUnpacker;
|
CNetRecvUnpacker m_RecvUnpacker;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -386,9 +398,9 @@ public:
|
||||||
static int Compress(const void *pData, int DataSize, void *pOutput, int OutputSize);
|
static int Compress(const void *pData, int DataSize, void *pOutput, int OutputSize);
|
||||||
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, NETADDR *pAddr, int Ack, int ControlMsg, const void *pExtra, int ExtraSize);
|
static void SendControlMsg(NETSOCKET Socket, NETADDR *pAddr, int Ack, int ControlMsg, const void *pExtra, int ExtraSize, SECURITY_TOKEN SecurityToken);
|
||||||
static void SendPacketConnless(NETSOCKET Socket, NETADDR *pAddr, const void *pData, int DataSize);
|
static void SendPacketConnless(NETSOCKET Socket, NETADDR *pAddr, const void *pData, int DataSize);
|
||||||
static void SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct *pPacket);
|
static void SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct *pPacket, SECURITY_TOKEN SecurityToken);
|
||||||
static int UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct *pPacket);
|
static int UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct *pPacket);
|
||||||
|
|
||||||
// The backroom is ack-NET_MAX_SEQUENCE/2. Used for knowing if we acked a packet or not
|
// The backroom is ack-NET_MAX_SEQUENCE/2. Used for knowing if we acked a packet or not
|
||||||
|
|
|
@ -24,6 +24,7 @@ void CNetConnection::Reset()
|
||||||
m_LastRecvTime = 0;
|
m_LastRecvTime = 0;
|
||||||
//m_LastUpdateTime = 0;
|
//m_LastUpdateTime = 0;
|
||||||
m_Token = -1;
|
m_Token = -1;
|
||||||
|
m_SecurityToken = NET_SECURITY_TOKEN_UNKNOWN;
|
||||||
//mem_zero(&m_PeerAddr, sizeof(m_PeerAddr));
|
//mem_zero(&m_PeerAddr, sizeof(m_PeerAddr));
|
||||||
|
|
||||||
m_Buffer.Init();
|
m_Buffer.Init();
|
||||||
|
@ -79,7 +80,7 @@ int CNetConnection::Flush()
|
||||||
|
|
||||||
// send of the packets
|
// send of the packets
|
||||||
m_Construct.m_Ack = m_Ack;
|
m_Construct.m_Ack = m_Ack;
|
||||||
CNetBase::SendPacket(m_Socket, &m_PeerAddr, &m_Construct);
|
CNetBase::SendPacket(m_Socket, &m_PeerAddr, &m_Construct, m_SecurityToken);
|
||||||
|
|
||||||
// update send times
|
// update send times
|
||||||
m_LastSendTime = time_get();
|
m_LastSendTime = time_get();
|
||||||
|
@ -94,7 +95,7 @@ int CNetConnection::QueueChunkEx(int Flags, int DataSize, const void *pData, int
|
||||||
unsigned char *pChunkData;
|
unsigned char *pChunkData;
|
||||||
|
|
||||||
// check if we have space for it, if not, flush the connection
|
// check if we have space for it, if not, flush the connection
|
||||||
if(m_Construct.m_DataSize + DataSize + NET_MAX_CHUNKHEADERSIZE > (int)sizeof(m_Construct.m_aChunkData))
|
if(m_Construct.m_DataSize + DataSize + NET_MAX_CHUNKHEADERSIZE > (int)sizeof(m_Construct.m_aChunkData) - (int)sizeof(SECURITY_TOKEN))
|
||||||
Flush();
|
Flush();
|
||||||
|
|
||||||
// pack all the data
|
// pack all the data
|
||||||
|
@ -148,7 +149,7 @@ void CNetConnection::SendControl(int ControlMsg, const void *pExtra, int ExtraSi
|
||||||
{
|
{
|
||||||
// send the control message
|
// send the control message
|
||||||
m_LastSendTime = time_get();
|
m_LastSendTime = time_get();
|
||||||
CNetBase::SendControlMsg(m_Socket, &m_PeerAddr, m_Ack, ControlMsg, pExtra, ExtraSize);
|
CNetBase::SendControlMsg(m_Socket, &m_PeerAddr, m_Ack, ControlMsg, pExtra, ExtraSize, m_SecurityToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNetConnection::ResendChunk(CNetChunkResend *pResend)
|
void CNetConnection::ResendChunk(CNetChunkResend *pResend)
|
||||||
|
@ -173,7 +174,7 @@ int CNetConnection::Connect(NETADDR *pAddr)
|
||||||
m_PeerAddr = *pAddr;
|
m_PeerAddr = *pAddr;
|
||||||
mem_zero(m_ErrorString, sizeof(m_ErrorString));
|
mem_zero(m_ErrorString, sizeof(m_ErrorString));
|
||||||
m_State = NET_CONNSTATE_CONNECT;
|
m_State = NET_CONNSTATE_CONNECT;
|
||||||
SendControl(NET_CTRLMSG_CONNECT, 0, 0);
|
SendControl(NET_CTRLMSG_CONNECT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,8 +198,22 @@ void CNetConnection::Disconnect(const char *pReason)
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr)
|
int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr, SECURITY_TOKEN SecurityToken)
|
||||||
{
|
{
|
||||||
|
if (m_SecurityToken != NET_SECURITY_TOKEN_UNKNOWN && m_SecurityToken != NET_SECURITY_TOKEN_UNSUPPORTED)
|
||||||
|
{
|
||||||
|
// supposed to have a valid token in this packet, check it
|
||||||
|
if (pPacket->m_DataSize < sizeof(m_SecurityToken))
|
||||||
|
return -1;
|
||||||
|
pPacket->m_DataSize -= sizeof(m_SecurityToken);
|
||||||
|
if (m_SecurityToken != *(SECURITY_TOKEN*)&pPacket->m_aChunkData[pPacket->m_DataSize])
|
||||||
|
{
|
||||||
|
if(g_Config.m_Debug)
|
||||||
|
dbg_msg("security", "token mismatch, expected %d got %d", m_SecurityToken, *(SECURITY_TOKEN*)&pPacket->m_aChunkData[pPacket->m_DataSize]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int64 Now = time_get();
|
int64 Now = time_get();
|
||||||
|
|
||||||
// check if resend is requested
|
// check if resend is requested
|
||||||
|
@ -262,7 +277,21 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr)
|
||||||
m_LastSendTime = Now;
|
m_LastSendTime = Now;
|
||||||
m_LastRecvTime = Now;
|
m_LastRecvTime = Now;
|
||||||
m_LastUpdateTime = Now;
|
m_LastUpdateTime = Now;
|
||||||
SendControl(NET_CTRLMSG_CONNECTACCEPT, 0, 0);
|
if (m_SecurityToken == NET_SECURITY_TOKEN_UNKNOWN
|
||||||
|
&& pPacket->m_DataSize >= 1 + sizeof(SECURITY_TOKEN_MAGIC) + sizeof(m_SecurityToken)
|
||||||
|
&& !mem_comp(&pPacket->m_aChunkData[1], SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC)))
|
||||||
|
{
|
||||||
|
m_SecurityToken = SecurityToken;
|
||||||
|
if(g_Config.m_Debug)
|
||||||
|
dbg_msg("security", "generated token %d", m_SecurityToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(g_Config.m_Debug)
|
||||||
|
dbg_msg("security", "token not supported by client (packet size %d)", pPacket->m_DataSize);
|
||||||
|
m_SecurityToken = NET_SECURITY_TOKEN_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
SendControl(NET_CTRLMSG_CONNECTACCEPT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC));
|
||||||
if(g_Config.m_Debug)
|
if(g_Config.m_Debug)
|
||||||
dbg_msg("connection", "got connection, sending connect+accept");
|
dbg_msg("connection", "got connection, sending connect+accept");
|
||||||
}
|
}
|
||||||
|
@ -272,6 +301,20 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr)
|
||||||
// connection made
|
// connection made
|
||||||
if(CtrlMsg == NET_CTRLMSG_CONNECTACCEPT)
|
if(CtrlMsg == NET_CTRLMSG_CONNECTACCEPT)
|
||||||
{
|
{
|
||||||
|
if (m_SecurityToken == NET_SECURITY_TOKEN_UNKNOWN
|
||||||
|
&& pPacket->m_DataSize >= 1 + sizeof(SECURITY_TOKEN_MAGIC) + sizeof(m_SecurityToken)
|
||||||
|
&& !mem_comp(&pPacket->m_aChunkData[1], SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC)))
|
||||||
|
{
|
||||||
|
m_SecurityToken = *(SECURITY_TOKEN*)(&pPacket->m_aChunkData[1 + sizeof(SECURITY_TOKEN_MAGIC)]);
|
||||||
|
if(g_Config.m_Debug)
|
||||||
|
dbg_msg("security", "got token %d", m_SecurityToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_SecurityToken = NET_SECURITY_TOKEN_UNSUPPORTED;
|
||||||
|
if(g_Config.m_Debug)
|
||||||
|
dbg_msg("security", "token not supported by server");
|
||||||
|
}
|
||||||
m_LastRecvTime = Now;
|
m_LastRecvTime = Now;
|
||||||
SendControl(NET_CTRLMSG_ACCEPT, 0, 0);
|
SendControl(NET_CTRLMSG_ACCEPT, 0, 0);
|
||||||
m_State = NET_CONNSTATE_ONLINE;
|
m_State = NET_CONNSTATE_ONLINE;
|
||||||
|
@ -364,12 +407,12 @@ int CNetConnection::Update()
|
||||||
else if(State() == NET_CONNSTATE_CONNECT)
|
else if(State() == NET_CONNSTATE_CONNECT)
|
||||||
{
|
{
|
||||||
if(time_get()-m_LastSendTime > time_freq()/2) // send a new connect every 500ms
|
if(time_get()-m_LastSendTime > time_freq()/2) // send a new connect every 500ms
|
||||||
SendControl(NET_CTRLMSG_CONNECT, 0, 0);
|
SendControl(NET_CTRLMSG_CONNECT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC));
|
||||||
}
|
}
|
||||||
else if(State() == NET_CONNSTATE_PENDING)
|
else if(State() == NET_CONNSTATE_PENDING)
|
||||||
{
|
{
|
||||||
if(time_get()-m_LastSendTime > time_freq()/2) // send a new connect/accept every 500ms
|
if(time_get()-m_LastSendTime > time_freq()/2) // send a new connect/accept every 500ms
|
||||||
SendControl(NET_CTRLMSG_CONNECTACCEPT, 0, 0);
|
SendControl(NET_CTRLMSG_CONNECTACCEPT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -4,9 +4,10 @@
|
||||||
|
|
||||||
#include <engine/console.h>
|
#include <engine/console.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include "netban.h"
|
#include "netban.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
|
#include <engine/external/md5/md5.h>
|
||||||
|
|
||||||
bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int MaxClientsPerIP, int Flags)
|
bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int MaxClientsPerIP, int Flags)
|
||||||
{
|
{
|
||||||
|
@ -29,6 +30,14 @@ bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int Ma
|
||||||
|
|
||||||
m_MaxClientsPerIP = MaxClientsPerIP;
|
m_MaxClientsPerIP = MaxClientsPerIP;
|
||||||
|
|
||||||
|
if(secure_random_init() != 0)
|
||||||
|
{
|
||||||
|
dbg_msg("secure", "could not initialize secure RNG");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
secure_random_fill(m_SecurityTokenSeed, sizeof(m_SecurityTokenSeed));
|
||||||
|
|
||||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||||
m_aSlots[i].m_Connection.Init(m_Socket, true);
|
m_aSlots[i].m_Connection.Init(m_Socket, true);
|
||||||
|
|
||||||
|
@ -108,7 +117,7 @@ int CNetServer::Recv(CNetChunk *pChunk)
|
||||||
if(NetBan() && NetBan()->IsBanned(&Addr, aBuf, sizeof(aBuf)))
|
if(NetBan() && NetBan()->IsBanned(&Addr, aBuf, sizeof(aBuf)))
|
||||||
{
|
{
|
||||||
// banned, reply with a message
|
// banned, reply with a message
|
||||||
CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, aBuf, str_length(aBuf)+1);
|
CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, aBuf, str_length(aBuf)+1, NET_SECURITY_TOKEN_UNSUPPORTED);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +179,7 @@ int CNetServer::Recv(CNetChunk *pChunk)
|
||||||
{
|
{
|
||||||
char aBuf[128];
|
char aBuf[128];
|
||||||
str_format(aBuf, sizeof(aBuf), "Only %d players with the same IP are allowed", m_MaxClientsPerIP);
|
str_format(aBuf, sizeof(aBuf), "Only %d players with the same IP are allowed", m_MaxClientsPerIP);
|
||||||
CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, aBuf, sizeof(aBuf));
|
CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, aBuf, sizeof(aBuf), NET_SECURITY_TOKEN_UNSUPPORTED);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,7 +190,22 @@ int CNetServer::Recv(CNetChunk *pChunk)
|
||||||
if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE)
|
if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE)
|
||||||
{
|
{
|
||||||
Found = true;
|
Found = true;
|
||||||
m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr);
|
long timestamp = time_get();
|
||||||
|
md5_state_t md5;
|
||||||
|
md5_byte_t digest[16];
|
||||||
|
SECURITY_TOKEN securityToken;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
md5_init(&md5);
|
||||||
|
md5_append(&md5, (unsigned char*)m_SecurityTokenSeed, sizeof(m_SecurityTokenSeed));
|
||||||
|
md5_append(&md5, (unsigned char*)&Addr, sizeof(Addr));
|
||||||
|
md5_append(&md5, (unsigned char*)×tamp, sizeof(timestamp));
|
||||||
|
md5_finish(&md5, digest);
|
||||||
|
securityToken = *(SECURITY_TOKEN*)digest;
|
||||||
|
timestamp++;
|
||||||
|
}
|
||||||
|
while (securityToken == NET_SECURITY_TOKEN_UNKNOWN || securityToken == NET_SECURITY_TOKEN_UNSUPPORTED);
|
||||||
|
m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr, securityToken);
|
||||||
if(m_pfnNewClient)
|
if(m_pfnNewClient)
|
||||||
m_pfnNewClient(i, m_UserPtr);
|
m_pfnNewClient(i, m_UserPtr);
|
||||||
break;
|
break;
|
||||||
|
@ -191,7 +215,7 @@ int CNetServer::Recv(CNetChunk *pChunk)
|
||||||
if(!Found)
|
if(!Found)
|
||||||
{
|
{
|
||||||
const char FullMsg[] = "This server is full";
|
const char FullMsg[] = "This server is full";
|
||||||
CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, FullMsg, sizeof(FullMsg));
|
CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, FullMsg, sizeof(FullMsg), NET_SECURITY_TOKEN_UNSUPPORTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue