Multipassword and salts
SRB2Classic ports by Hanicef
This commit is contained in:
parent
6131cfd99d
commit
bc82e2564c
5 changed files with 156 additions and 45 deletions
136
src/d_clisrv.c
136
src/d_clisrv.c
|
|
@ -143,8 +143,11 @@ UINT8 hu_redownloadinggamestate = 0;
|
|||
// kart, true when a player is connecting or disconnecting so that the gameplay has stopped in its tracks
|
||||
boolean hu_stopped = false;
|
||||
|
||||
UINT8 (*adminpassmd5)[16];
|
||||
char *reqpass;
|
||||
char **adminpass;
|
||||
UINT32 adminpasscount = 0;
|
||||
char adminsalt[MAXPLAYERS][9];
|
||||
//I_StaticAssert(sizeof(netbuffer->u.salt) == sizeof(adminsalt[0]));
|
||||
|
||||
// Client specific
|
||||
static ticcmd_t localcmds[MAXSPLITSCREENPLAYERS][MAXGENTLEMENDELAY];
|
||||
|
|
@ -4276,6 +4279,97 @@ static void HandleShutdown(SINT8 node)
|
|||
M_StartMessage(M_GetText("Server has shutdown\n\nPress Esc\n"), NULL, MM_NOTHING);
|
||||
}
|
||||
|
||||
static void PT_Login(SINT8 node)
|
||||
{
|
||||
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
|
||||
|
||||
if (client)
|
||||
return;
|
||||
|
||||
#ifndef NOMD5
|
||||
// I_GetRandomBytes should get it's data from a CSPRNG, so it's safe to use it here.
|
||||
I_GetRandomBytes(adminsalt[node], sizeof(adminsalt[node]));
|
||||
adminsalt[node][8] = '\0'; // convenience
|
||||
netbuffer->packettype = PT_LOGINCHALLENGE;
|
||||
memcpy(netbuffer->u.salt, adminsalt[node], sizeof(adminsalt[node]));
|
||||
HSendPacket(node, true, 0, sizeof(adminsalt[node]));
|
||||
#else
|
||||
(void)node;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void PT_LoginChallenge(SINT8 node)
|
||||
{
|
||||
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
|
||||
|
||||
#ifndef NOMD5
|
||||
if (node != servernode)
|
||||
return;
|
||||
|
||||
if ((size_t)doomcom->datalength < sizeof(netbuffer->u.salt))/* ignore partial sends */
|
||||
return;
|
||||
|
||||
if (reqpass == NULL)
|
||||
return; // got PT_LOGINCHALLENGE but we didn't request a login
|
||||
|
||||
D_MD5PasswordPass((const UINT8 *)reqpass, strlen(reqpass), netbuffer->u.salt, &netbuffer->u.md5sum);
|
||||
Z_Free(reqpass);
|
||||
reqpass = NULL;
|
||||
|
||||
netbuffer->packettype = PT_LOGINAUTH;
|
||||
HSendPacket(servernode, true, 0, 16);
|
||||
#else
|
||||
(void)node;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void PT_LoginAuth(SINT8 node, INT32 netconsole)
|
||||
{
|
||||
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
|
||||
#ifndef NOMD5
|
||||
UINT8 finalmd5[16];/* Well, it's the cool thing to do? */
|
||||
UINT32 i;
|
||||
if (client)
|
||||
return;
|
||||
|
||||
if (doomcom->datalength < 16)/* ignore partial sends */
|
||||
return;
|
||||
|
||||
if (adminsalt[node][0] == 0)
|
||||
{
|
||||
CONS_Printf(M_GetText("Password from %s failed (no login request).\n"), player_names[netconsole]);
|
||||
return;
|
||||
}
|
||||
if (adminpasscount == 0)
|
||||
{
|
||||
adminsalt[node][0] = 0;
|
||||
CONS_Printf(M_GetText("Password from %s failed (no password set).\n"), player_names[netconsole]);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < adminpasscount; i++)
|
||||
{
|
||||
// Do the final pass to compare with the sent md5
|
||||
D_MD5PasswordPass((const UINT8 *)adminpass[i], strlen(adminpass[i]), adminsalt[node], finalmd5);
|
||||
|
||||
if (!memcmp(netbuffer->u.md5sum, finalmd5, 16))
|
||||
{
|
||||
adminsalt[node][0] = 0;
|
||||
CONS_Printf(M_GetText("%s passed authentication.\n"), player_names[netconsole]);
|
||||
COM_BufInsertText(va("promote %d\n", netconsole)); // do this immediately
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
adminsalt[node][0] = 0;
|
||||
CONS_Printf(M_GetText("Password from %s failed.\n"), player_names[netconsole]);
|
||||
#else
|
||||
(void)node;
|
||||
(void)netconsole;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** Called when a PT_NODETIMEOUT packet is received
|
||||
*
|
||||
* \param node The packet sender (should be the server)
|
||||
|
|
@ -4629,10 +4723,6 @@ static void HandlePacketFromPlayer(SINT8 node)
|
|||
INT32 netconsole;
|
||||
tic_t realend, realstart;
|
||||
UINT8 *pak, *txtpak, numtxtpak;
|
||||
UINT32 i;
|
||||
#ifndef NOMD5
|
||||
UINT8 finalmd5[16];/* Well, it's the cool thing to do? */
|
||||
#endif
|
||||
|
||||
txtpak = NULL;
|
||||
|
||||
|
|
@ -4868,34 +4958,10 @@ static void HandlePacketFromPlayer(SINT8 node)
|
|||
}
|
||||
break;
|
||||
case PT_LOGIN:
|
||||
if (client)
|
||||
break;
|
||||
|
||||
#ifndef NOMD5
|
||||
if (doomcom->datalength < 16)/* ignore partial sends */
|
||||
break;
|
||||
|
||||
if (adminpasscount == 0)
|
||||
{
|
||||
CONS_Printf(M_GetText("Password from %s failed (no password set).\n"), player_names[netconsole]);
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < adminpasscount; i++)
|
||||
{
|
||||
// Do the final pass to compare with the sent md5
|
||||
D_MD5PasswordPass(adminpassmd5[i], 16, va("PNUM%02d", netconsole), &finalmd5);
|
||||
|
||||
if (!memcmp(netbuffer->u.md5sum, finalmd5, 16))
|
||||
{
|
||||
CONS_Printf(M_GetText("%s passed authentication.\n"), player_names[netconsole]);
|
||||
COM_BufInsertText(va("promote %d\n", netconsole)); // do this immediately
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
CONS_Printf(M_GetText("Password from %s failed.\n"), player_names[netconsole]);
|
||||
#endif
|
||||
PT_Login(node);
|
||||
break;
|
||||
case PT_LOGINAUTH:
|
||||
PT_LoginAuth(node, netconsole);
|
||||
break;
|
||||
case PT_NODETIMEOUT:
|
||||
case PT_CLIENTQUIT:
|
||||
|
|
@ -5071,6 +5137,9 @@ static void HandlePacketFromPlayer(SINT8 node)
|
|||
if (server)
|
||||
PT_FileReceived();
|
||||
break;
|
||||
case PT_LOGINCHALLENGE:
|
||||
PT_LoginChallenge(node);
|
||||
break;
|
||||
case PT_WILLRESENDGAMESTATE:
|
||||
PT_WillResendGamestate();
|
||||
break;
|
||||
|
|
@ -6236,6 +6305,7 @@ rewind_t *CL_RewindToTime(tic_t time)
|
|||
|
||||
void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest)
|
||||
{
|
||||
// FIXME: replace with SHA-256, since MD5 is busted.
|
||||
#ifdef NOMD5
|
||||
(void)buffer;
|
||||
(void)len;
|
||||
|
|
|
|||
|
|
@ -117,6 +117,8 @@ typedef enum
|
|||
PT_MOREFILESNEEDED, // Server, to client: "you need these (+ more on top of those)"
|
||||
|
||||
PT_LOGIN, // Login attempt from the client.
|
||||
PT_LOGINCHALLENGE,// Challenge request sent to the client.
|
||||
PT_LOGINAUTH, // Challenge response from the client.
|
||||
|
||||
PT_PING, // Packet sent to tell clients the other client's latency to server.
|
||||
NUMPACKETTYPE
|
||||
|
|
@ -374,6 +376,7 @@ struct doomdata_t
|
|||
char fileack[sizeof (fileack_pak)];
|
||||
UINT8 filereceived;
|
||||
clientconfig_pak clientcfg; // 136 bytes
|
||||
char salt[9];
|
||||
UINT8 md5sum[16];
|
||||
serverinfo_pak serverinfo; // 1024 bytes
|
||||
serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...)
|
||||
|
|
@ -588,7 +591,8 @@ void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *
|
|||
|
||||
extern UINT8 hu_redownloadinggamestate;
|
||||
|
||||
extern UINT8 (*adminpassmd5)[16];
|
||||
extern char *reqpass;
|
||||
extern char **adminpass;
|
||||
extern UINT32 adminpasscount;
|
||||
|
||||
extern boolean hu_stopped;
|
||||
|
|
|
|||
|
|
@ -4067,14 +4067,17 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
|
|||
|
||||
void D_SetPassword(const char *pw)
|
||||
{
|
||||
adminpassmd5 = Z_Realloc(adminpassmd5, sizeof(*adminpassmd5) * ++adminpasscount, PU_STATIC, NULL);
|
||||
D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &adminpassmd5[adminpasscount-1]);
|
||||
adminpass = Z_Realloc(adminpass, sizeof(*adminpass) * ++adminpasscount, PU_STATIC, NULL);
|
||||
adminpass[adminpasscount-1] = Z_StrDup(pw);
|
||||
}
|
||||
|
||||
void D_ClearPassword(void)
|
||||
{
|
||||
Z_Free(adminpassmd5);
|
||||
adminpassmd5 = NULL;
|
||||
UINT32 i;
|
||||
for (i = 0; i < adminpasscount; i++)
|
||||
Z_Free(adminpass[i]);
|
||||
Z_Free(adminpass);
|
||||
adminpass = NULL;
|
||||
adminpasscount = 0;
|
||||
}
|
||||
|
||||
|
|
@ -4144,18 +4147,16 @@ static void Command_Login_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (reqpass)
|
||||
Z_Free(reqpass);
|
||||
|
||||
pw = COM_Argv(1);
|
||||
|
||||
// Do the base pass to get what the server has (or should?)
|
||||
D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &netbuffer->u.md5sum);
|
||||
|
||||
// Do the final pass to get the comparison the server will come up with
|
||||
D_MD5PasswordPass(netbuffer->u.md5sum, 16, va("PNUM%02d", consoleplayer), &netbuffer->u.md5sum);
|
||||
reqpass = Z_StrDup(pw);
|
||||
|
||||
CONS_Printf(M_GetText("Sending login... (Notice only given if password is correct.)\n"));
|
||||
|
||||
netbuffer->packettype = PT_LOGIN;
|
||||
HSendPacket(servernode, true, 0, 16);
|
||||
HSendPacket(servernode, true, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,10 @@ UINT32 I_GetFreeMem(UINT32 *total);
|
|||
*/
|
||||
precise_t I_GetPreciseTime(void);
|
||||
|
||||
/** \brief Fills a buffer with random data, returns amount of data obtained.
|
||||
*/
|
||||
size_t I_GetRandomBytes(char *destination, size_t count);
|
||||
|
||||
/** \brief Get the precision of precise_t in units per second. Invocations of
|
||||
this function for the program's duration MUST return the same value.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -2317,6 +2317,38 @@ char *I_GetEnv(const char *name)
|
|||
#endif
|
||||
}
|
||||
|
||||
size_t I_GetRandomBytes(char *destination, size_t count)
|
||||
{
|
||||
#if defined (__unix__) || defined (UNIXCOMMON) || defined(__APPLE__)
|
||||
FILE *rndsource;
|
||||
size_t actual_bytes = 0;
|
||||
|
||||
if (!(rndsource = fopen("/dev/urandom", "r")))
|
||||
if (!(rndsource = fopen("/dev/random", "r")))
|
||||
actual_bytes = 0;
|
||||
|
||||
if (rndsource)
|
||||
{
|
||||
actual_bytes = fread(destination, 1, count, rndsource);
|
||||
fclose(rndsource);
|
||||
}
|
||||
|
||||
if (actual_bytes == 0)
|
||||
I_OutputMsg("I_GetRandomBytes(): couldn't get any random bytes");
|
||||
|
||||
return actual_bytes;
|
||||
#elif defined (_WIN32)
|
||||
if (RtlGenRandom(destination, count))
|
||||
return count;
|
||||
|
||||
I_OutputMsg("I_GetRandomBytes(): couldn't get any random bytes");
|
||||
return 0;
|
||||
#else
|
||||
#warning SDL I_GetRandomBytes is not implemented on this platform.
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
INT32 I_PutEnv(char *variable)
|
||||
{
|
||||
#ifdef NEED_SDL_GETENV
|
||||
|
|
|
|||
Loading…
Reference in a new issue