mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Merge pull request #554 from heinrich5991/pr_ddnet_random_timeouttoken
Generate server-specific timeout codes
This commit is contained in:
commit
823e330a76
|
@ -2555,7 +2555,40 @@ int secure_random_init()
|
|||
#endif
|
||||
}
|
||||
|
||||
void secure_random_fill(void *bytes, size_t length)
|
||||
void generate_password(char *buffer, unsigned length, unsigned short *random, unsigned random_length)
|
||||
{
|
||||
static const char VALUES[] = "ABCDEFGHKLMNPRSTUVWXYZabcdefghjkmnopqt23456789";
|
||||
static const size_t NUM_VALUES = sizeof(VALUES) - 1; // Disregard the '\0'.
|
||||
unsigned i;
|
||||
dbg_assert(length >= random_length * 2 + 1, "too small buffer");
|
||||
dbg_assert(NUM_VALUES * NUM_VALUES >= 2048, "need at least 2048 possibilities for 2-character sequences");
|
||||
|
||||
buffer[random_length * 2] = 0;
|
||||
|
||||
for(i = 0; i < random_length; i++)
|
||||
{
|
||||
unsigned short random_number = random[i] % 2048;
|
||||
buffer[2 * i + 0] = VALUES[random_number / NUM_VALUES];
|
||||
buffer[2 * i + 1] = VALUES[random_number % NUM_VALUES];
|
||||
}
|
||||
}
|
||||
|
||||
void secure_random_password(char *buffer, unsigned length, unsigned pw_length)
|
||||
{
|
||||
static const size_t MAX_PASSWORD_LENGTH = 128;
|
||||
unsigned short random[MAX_PASSWORD_LENGTH / 2];
|
||||
// With 6 characters, we get a password entropy of log(2048) * 6/2 = 33bit.
|
||||
dbg_assert(length >= pw_length + 1, "too small buffer");
|
||||
dbg_assert(pw_length >= 6, "too small password length");
|
||||
dbg_assert(pw_length % 2 == 0, "need an even password length");
|
||||
dbg_assert(pw_length <= MAX_PASSWORD_LENGTH, "too large password length");
|
||||
|
||||
secure_random_fill(random, pw_length);
|
||||
|
||||
generate_password(buffer, length, random, pw_length / 2);
|
||||
}
|
||||
|
||||
void secure_random_fill(void *bytes, unsigned length)
|
||||
{
|
||||
if(!secure_random_data.initialized)
|
||||
{
|
||||
|
|
|
@ -1375,6 +1375,20 @@ void shell_execute(const char *file);
|
|||
*/
|
||||
int os_compare_version(int major, int minor);
|
||||
|
||||
/*
|
||||
Function: generate_password
|
||||
Generates a null-terminated password of length `2 *
|
||||
random_length`.
|
||||
|
||||
|
||||
Parameters:
|
||||
buffer - Pointer to the start of the output buffer.
|
||||
length - Length of the buffer.
|
||||
random - Pointer to a randomly-initialized array of shorts.
|
||||
random_length - Length of the short array.
|
||||
*/
|
||||
void generate_password(char *buffer, unsigned length, unsigned short *random, unsigned random_length);
|
||||
|
||||
/*
|
||||
Function: secure_random_init
|
||||
Initializes the secure random module.
|
||||
|
@ -1386,6 +1400,21 @@ int os_compare_version(int major, int minor);
|
|||
*/
|
||||
int secure_random_init();
|
||||
|
||||
/*
|
||||
Function: secure_random_password
|
||||
Fills the buffer with the specified amount of random password
|
||||
characters.
|
||||
|
||||
The desired password length must be greater or equal to 6, even
|
||||
and smaller or equal to 128.
|
||||
|
||||
Parameters:
|
||||
buffer - Pointer to the start of the buffer.
|
||||
length - Length of the buffer.
|
||||
pw_length - Length of the desired password.
|
||||
*/
|
||||
void secure_random_password(char *buffer, unsigned length, unsigned pw_length);
|
||||
|
||||
/*
|
||||
Function: secure_random_fill
|
||||
Fills the buffer with the specified amount of random bytes.
|
||||
|
@ -1394,7 +1423,7 @@ int secure_random_init();
|
|||
buffer - Pointer to the start of the buffer.
|
||||
length - Length of the buffer.
|
||||
*/
|
||||
void secure_random_fill(void *bytes, size_t length);
|
||||
void secure_random_fill(void *bytes, unsigned length);
|
||||
|
||||
/*
|
||||
Function: secure_rand
|
||||
|
|
|
@ -195,6 +195,8 @@ public:
|
|||
virtual void RequestDDNetSrvList() = 0;
|
||||
virtual bool EditorHasUnsavedData() = 0;
|
||||
|
||||
virtual void GenerateTimeoutSeed() = 0;
|
||||
|
||||
virtual IFriends* Foes() = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <engine/storage.h>
|
||||
#include <engine/textrender.h>
|
||||
|
||||
#include <engine/external/md5/md5.h>
|
||||
|
||||
#include <engine/shared/config.h>
|
||||
#include <engine/shared/compression.h>
|
||||
#include <engine/shared/datafile.h>
|
||||
|
@ -347,6 +349,8 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta)
|
|||
|
||||
m_DDNetSrvListTokenSet = false;
|
||||
m_ReconnectTime = 0;
|
||||
|
||||
m_GenerateTimeoutSeed = true;
|
||||
}
|
||||
|
||||
// ----- send functions -----
|
||||
|
@ -678,8 +682,51 @@ void CClient::EnterGame()
|
|||
OnEnterGame();
|
||||
|
||||
ServerInfoRequest(); // fresh one for timeout protection
|
||||
m_TimeoutCodeSent[0] = false;
|
||||
m_TimeoutCodeSent[1] = false;
|
||||
m_aTimeoutCodeSent[0] = false;
|
||||
m_aTimeoutCodeSent[1] = false;
|
||||
}
|
||||
|
||||
void GenerateTimeoutCode(char *pBuffer, unsigned Size, char *pSeed, const NETADDR &Addr, bool Dummy)
|
||||
{
|
||||
md5_state_t Md5;
|
||||
md5_byte_t aDigest[16];
|
||||
md5_init(&Md5);
|
||||
|
||||
const char *pDummy = Dummy ? "dummy" : "normal";
|
||||
|
||||
md5_append(&Md5, (unsigned char *)pDummy, str_length(pDummy) + 1);
|
||||
md5_append(&Md5, (unsigned char *)pSeed, str_length(pSeed) + 1);
|
||||
md5_append(&Md5, (unsigned char *)&Addr, sizeof(Addr));
|
||||
md5_finish(&Md5, aDigest);
|
||||
|
||||
unsigned short Random[8];
|
||||
mem_copy(Random, aDigest, sizeof(Random));
|
||||
generate_password(pBuffer, Size, Random, 8);
|
||||
}
|
||||
|
||||
void CClient::GenerateTimeoutSeed()
|
||||
{
|
||||
secure_random_password(g_Config.m_ClTimeoutSeed, sizeof(g_Config.m_ClTimeoutSeed), 16);
|
||||
}
|
||||
|
||||
void CClient::GenerateTimeoutCodes()
|
||||
{
|
||||
if(g_Config.m_ClTimeoutSeed[0])
|
||||
{
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
GenerateTimeoutCode(m_aTimeoutCodes[i], sizeof(m_aTimeoutCodes[i]), g_Config.m_ClTimeoutSeed, m_ServerAddress, i);
|
||||
|
||||
char aBuf[64];
|
||||
str_format(aBuf, sizeof(aBuf), "timeout code '%s' (%s)", m_aTimeoutCodes[i], i == 0 ? "normal" : "dummy");
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
str_copy(m_aTimeoutCodes[0], g_Config.m_ClTimeoutCode, sizeof(m_aTimeoutCodes[0]));
|
||||
str_copy(m_aTimeoutCodes[1], g_Config.m_ClDummyTimeoutCode, sizeof(m_aTimeoutCodes[1]));
|
||||
}
|
||||
}
|
||||
|
||||
void CClient::Connect(const char *pAddress)
|
||||
|
@ -715,6 +762,8 @@ void CClient::Connect(const char *pAddress)
|
|||
|
||||
m_InputtimeMarginGraph.Init(-150.0f, 150.0f);
|
||||
m_GametimeMarginGraph.Init(-150.0f, 150.0f);
|
||||
|
||||
GenerateTimeoutCodes();
|
||||
}
|
||||
|
||||
void CClient::DisconnectWithReason(const char *pReason)
|
||||
|
@ -1872,15 +1921,15 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
|||
m_GameTime[g_Config.m_ClDummy].Update(&m_GametimeMarginGraph, (GameTick-1)*time_freq()/50, TimeLeft, 0);
|
||||
}
|
||||
|
||||
if(m_ReceivedSnapshots[g_Config.m_ClDummy] > 50 && !m_TimeoutCodeSent[g_Config.m_ClDummy])
|
||||
if(m_ReceivedSnapshots[g_Config.m_ClDummy] > 50 && !m_aTimeoutCodeSent[g_Config.m_ClDummy])
|
||||
{
|
||||
if(IsDDNet(&m_CurrentServerInfo))
|
||||
{
|
||||
m_TimeoutCodeSent[g_Config.m_ClDummy] = true;
|
||||
m_aTimeoutCodeSent[g_Config.m_ClDummy] = true;
|
||||
CNetMsg_Cl_Say Msg;
|
||||
Msg.m_Team = 0;
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "/timeout %s", g_Config.m_ClDummy ? g_Config.m_ClDummyTimeoutCode : g_Config.m_ClTimeoutCode);
|
||||
str_format(aBuf, sizeof(aBuf), "/timeout %s", m_aTimeoutCodes[g_Config.m_ClDummy]);
|
||||
Msg.m_pMessage = aBuf;
|
||||
CMsgPacker Packer(Msg.MsgID());
|
||||
Msg.Pack(&Packer);
|
||||
|
@ -2577,7 +2626,14 @@ void CClient::Run()
|
|||
m_LocalStartTime = time_get();
|
||||
m_SnapshotParts = 0;
|
||||
|
||||
srand(time(NULL));
|
||||
if(m_GenerateTimeoutSeed)
|
||||
{
|
||||
GenerateTimeoutSeed();
|
||||
}
|
||||
|
||||
unsigned int Seed;
|
||||
secure_random_fill(&Seed, sizeof(Seed));
|
||||
srand(Seed);
|
||||
|
||||
// init SDL
|
||||
{
|
||||
|
@ -3278,6 +3334,14 @@ void CClient::ConchainWindowVSync(IConsole::IResult *pResult, void *pUserData, I
|
|||
pfnCallback(pResult, pCallbackUserData);
|
||||
}
|
||||
|
||||
void CClient::ConchainTimeoutSeed(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
|
||||
{
|
||||
CClient *pSelf = (CClient *)pUserData;
|
||||
pfnCallback(pResult, pCallbackUserData);
|
||||
if(pResult->NumArguments())
|
||||
pSelf->m_GenerateTimeoutSeed = false;
|
||||
}
|
||||
|
||||
void CClient::RegisterCommands()
|
||||
{
|
||||
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
||||
|
@ -3316,6 +3380,8 @@ void CClient::RegisterCommands()
|
|||
m_pConsole->Register("demo_speed", "i[speed]", CFGFLAG_CLIENT, Con_DemoSpeed, this, "Set demo speed");
|
||||
|
||||
// used for server browser update
|
||||
m_pConsole->Chain("cl_timeout_seed", ConchainTimeoutSeed, this);
|
||||
|
||||
m_pConsole->Chain("br_filter_string", ConchainServerBrowserUpdate, this);
|
||||
m_pConsole->Chain("br_filter_gametype", ConchainServerBrowserUpdate, this);
|
||||
m_pConsole->Chain("br_filter_serveraddress", ConchainServerBrowserUpdate, this);
|
||||
|
|
|
@ -119,7 +119,9 @@ class CClient : public IClient, public CDemoPlayer::IListener
|
|||
char m_aCurrentMapPath[CEditor::MAX_PATH_LENGTH];
|
||||
unsigned m_CurrentMapCrc;
|
||||
|
||||
bool m_TimeoutCodeSent[2];
|
||||
char m_aTimeoutCodes[2][32];
|
||||
bool m_aTimeoutCodeSent[2];
|
||||
bool m_GenerateTimeoutSeed;
|
||||
|
||||
//
|
||||
char m_aCmdConnect[256];
|
||||
|
@ -342,6 +344,7 @@ public:
|
|||
static void ConchainWindowBordered(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||
static void ConchainWindowScreen(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||
static void ConchainWindowVSync(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||
static void ConchainTimeoutSeed(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||
|
||||
static void Con_DemoSlice(IConsole::IResult *pResult, void *pUserData);
|
||||
static void Con_DemoSliceBegin(IConsole::IResult *pResult, void *pUserData);
|
||||
|
@ -371,6 +374,9 @@ public:
|
|||
|
||||
// DDRace
|
||||
|
||||
void GenerateTimeoutSeed();
|
||||
void GenerateTimeoutCodes();
|
||||
|
||||
virtual const char* GetCurrentMap();
|
||||
virtual int GetCurrentMapCrc();
|
||||
virtual const char* GetCurrentMapPath();
|
||||
|
|
|
@ -559,26 +559,7 @@ void CServer::InitRconPasswordIfEmpty()
|
|||
return;
|
||||
}
|
||||
|
||||
static const char VALUES[] = "ABCDEFGHKLMNPRSTUVWXYZabcdefghjkmnopqt23456789";
|
||||
static const size_t NUM_VALUES = sizeof(VALUES) - 1; // Disregard the '\0'.
|
||||
static const size_t PASSWORD_LENGTH = 6;
|
||||
dbg_assert(NUM_VALUES * NUM_VALUES >= 2048, "need at least 2048 possibilities for 2-character sequences");
|
||||
// With 6 characters, we get a password entropy of log(2048) * 6/2 = 33bit.
|
||||
|
||||
dbg_assert(PASSWORD_LENGTH % 2 == 0, "need an even password length");
|
||||
unsigned short aRandom[PASSWORD_LENGTH / 2];
|
||||
char aRandomPassword[PASSWORD_LENGTH+1];
|
||||
aRandomPassword[PASSWORD_LENGTH] = 0;
|
||||
|
||||
secure_random_fill(aRandom, sizeof(aRandom));
|
||||
for(size_t i = 0; i < PASSWORD_LENGTH / 2; i++)
|
||||
{
|
||||
unsigned short RandomNumber = aRandom[i] % 2048;
|
||||
aRandomPassword[2 * i + 0] = VALUES[RandomNumber / NUM_VALUES];
|
||||
aRandomPassword[2 * i + 1] = VALUES[RandomNumber % NUM_VALUES];
|
||||
}
|
||||
|
||||
str_copy(g_Config.m_SvRconPassword, aRandomPassword, sizeof(g_Config.m_SvRconPassword));
|
||||
secure_random_password(g_Config.m_SvRconPassword, sizeof(g_Config.m_SvRconPassword), 6);
|
||||
m_GeneratedRconPassword = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -363,6 +363,7 @@ MACRO_CONFIG_INT(ClOldGunPosition, cl_old_gun_position, 0, 0, 1, CFGFLAG_SAVE|CF
|
|||
MACRO_CONFIG_INT(ClConfirmDisconnect, cl_confirm_disconnect, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Confirmation popup before disconnecting")
|
||||
MACRO_CONFIG_STR(ClTimeoutCode, cl_timeout_code, 64, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Timeout code to use")
|
||||
MACRO_CONFIG_STR(ClDummyTimeoutCode, cl_dummy_timeout_code, 64, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Dummy Timeout code to use")
|
||||
MACRO_CONFIG_STR(ClTimeoutSeed, cl_timeout_seed, 64, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Timeout seed")
|
||||
MACRO_CONFIG_STR(ClInputFifo, cl_input_fifo, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Fifo file to use as input for client console")
|
||||
MACRO_CONFIG_INT(ClShowConsole, cl_show_console, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Show console window (Windows only)")
|
||||
#if defined(__ANDROID__)
|
||||
|
|
|
@ -2020,24 +2020,11 @@ void CMenus::RenderSettingsDDNet(CUIRect MainView)
|
|||
#endif
|
||||
|
||||
{
|
||||
static int s_ButtonTimeout = 0;
|
||||
Right.HSplitTop(20.0f, &Button, &Right);
|
||||
Button.VSplitLeft(190.0f, &Label, &Button);
|
||||
char aBuf[128];
|
||||
str_format(aBuf, sizeof(aBuf), "%s:", Localize("Timeout code"));
|
||||
UI()->DoLabelScaled(&Label, aBuf, 14.0, -1);
|
||||
static float s_OffsetCode = 0.0f;
|
||||
DoEditBox(g_Config.m_ClTimeoutCode, &Button, g_Config.m_ClTimeoutCode, sizeof(g_Config.m_ClTimeoutCode), 14.0f, &s_OffsetCode);
|
||||
}
|
||||
|
||||
Right.HSplitTop(5.0f, &Button, &Right);
|
||||
|
||||
{
|
||||
Right.HSplitTop(20.0f, &Button, &Right);
|
||||
Button.VSplitLeft(190.0f, &Label, &Button);
|
||||
char aBuf[128];
|
||||
str_format(aBuf, sizeof(aBuf), "%s:", Localize("Dummy Timeout code"));
|
||||
UI()->DoLabelScaled(&Label, aBuf, 14.0, -1);
|
||||
static float s_OffsetCode = 0.0f;
|
||||
DoEditBox(g_Config.m_ClDummyTimeoutCode, &Button, g_Config.m_ClDummyTimeoutCode, sizeof(g_Config.m_ClDummyTimeoutCode), 14.0f, &s_OffsetCode);
|
||||
if(DoButton_Menu(&s_ButtonTimeout, Localize("New random timeout code"), 0, &Button))
|
||||
{
|
||||
Client()->GenerateTimeoutSeed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue