mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-12-17 13:32:38 +00:00
I don't even know, unfuck everything
This commit is contained in:
parent
a1b0625f66
commit
33760dec51
6 changed files with 342 additions and 35 deletions
339
src/d_clisrv.c
339
src/d_clisrv.c
|
|
@ -48,6 +48,7 @@
|
||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
#include "m_perfstats.h"
|
#include "m_perfstats.h"
|
||||||
#include "monocypher/monocypher.h"
|
#include "monocypher/monocypher.h"
|
||||||
|
#include "stun.h"
|
||||||
|
|
||||||
// SRB2Kart
|
// SRB2Kart
|
||||||
#include "k_kart.h"
|
#include "k_kart.h"
|
||||||
|
|
@ -157,8 +158,18 @@ char connectedservername[MAXSERVERNAME];
|
||||||
/// \todo WORK!
|
/// \todo WORK!
|
||||||
boolean acceptnewnode = true;
|
boolean acceptnewnode = true;
|
||||||
|
|
||||||
uint8_t lastReceivedKey[MAXNETNODES][MAXSPLITSCREENPLAYERS][32];
|
// We give clients a chance to verify each other once per race.
|
||||||
uint8_t lastSentChallenge[MAXNETNODES][MAXSPLITSCREENPLAYERS][32];
|
// When is that challenge sent, and when should clients bail if they don't receive the responses?
|
||||||
|
#define CHALLENGEALL_START (TICRATE*10)
|
||||||
|
#define CHALLENGEALL_SERVERCUTOFF (TICRATE*12)
|
||||||
|
#define CHALLENGEALL_CLIENTCUTOFF (TICRATE*14)
|
||||||
|
|
||||||
|
uint8_t lastReceivedKey[MAXNETNODES][MAXSPLITSCREENPLAYERS][32]; // Player's public key (join process only! active players have it on player_t)
|
||||||
|
uint8_t lastSentChallenge[MAXNETNODES][MAXSPLITSCREENPLAYERS][32]; // The random message we asked them to sign in PT_SERVERCHALLENGE, check it in PT_CLIENTJOIN
|
||||||
|
uint8_t lastChallengeAll[32]; // The message we asked EVERYONE to sign for client-to-client identity proofs
|
||||||
|
uint8_t lastReceivedSignature[MAXPLAYERS][64]; // Everyone's response to lastChallengeAll
|
||||||
|
uint8_t involvedInChallenge[MAXPLAYERS][32];
|
||||||
|
uint8_t knownWhenChallenged[MAXPLAYERS][32];
|
||||||
|
|
||||||
boolean serverisfull = false; //lets us be aware if the server was full after we check files, but before downloading, so we can ask if the user still wants to download or not
|
boolean serverisfull = false; //lets us be aware if the server was full after we check files, but before downloading, so we can ask if the user still wants to download or not
|
||||||
tic_t firstconnectattempttime = 0;
|
tic_t firstconnectattempttime = 0;
|
||||||
|
|
@ -3695,6 +3706,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
||||||
newplayer->jointime = 0;
|
newplayer->jointime = 0;
|
||||||
|
|
||||||
READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME);
|
READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME);
|
||||||
|
READSTRINGN(*p, players[newplayernum].public_key, 32);
|
||||||
|
|
||||||
console = READUINT8(*p);
|
console = READUINT8(*p);
|
||||||
splitscreenplayer = READUINT8(*p);
|
splitscreenplayer = READUINT8(*p);
|
||||||
|
|
@ -3731,19 +3743,11 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
||||||
|
|
||||||
D_SendPlayerConfig(splitscreenplayer);
|
D_SendPlayerConfig(splitscreenplayer);
|
||||||
addedtogame = true;
|
addedtogame = true;
|
||||||
CONS_Printf("It's me, node %d, with ID %s! (This is uninitialized memory because Tyron is a dumbass!)\n", node, GetPrettyRRID(lastReceivedKey[node][splitscreenplayer], true));
|
|
||||||
memcpy(lastReceivedKey[node][splitscreenplayer], PR_GetLocalPlayerProfile(splitscreenplayer)->public_key, 32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
players[newplayernum].splitscreenindex = splitscreenplayer;
|
players[newplayernum].splitscreenindex = splitscreenplayer;
|
||||||
players[newplayernum].bot = false;
|
players[newplayernum].bot = false;
|
||||||
|
|
||||||
// player_t is the only place in the game that a key is null-terminated, for ease of Lua push.
|
|
||||||
memset(players[newplayernum].public_key, 0, 32 + 1);
|
|
||||||
CONS_Printf("Adding player from node %d with ID %s\n", node, GetPrettyRRID(lastReceivedKey[node][splitscreenplayer], true));
|
|
||||||
memcpy(players[newplayernum].public_key, lastReceivedKey[node][splitscreenplayer], 32);
|
|
||||||
CONS_Printf("Node %d now has ID %s\n", node, GetPrettyRRID(players[newplayernum].public_key, true));
|
|
||||||
|
|
||||||
playerconsole[newplayernum] = console;
|
playerconsole[newplayernum] = console;
|
||||||
splitscreen_original_party_size[console] =
|
splitscreen_original_party_size[console] =
|
||||||
++splitscreen_party_size[console];
|
++splitscreen_party_size[console];
|
||||||
|
|
@ -3862,7 +3866,9 @@ static void Got_AddBot(UINT8 **p, INT32 playernum)
|
||||||
LUA_HookInt(newplayernum, HOOK(PlayerJoin));
|
LUA_HookInt(newplayernum, HOOK(PlayerJoin));
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean SV_AddWaitingPlayers(SINT8 node, UINT8 *availabilities, const char *name, const char *name2, const char *name3, const char *name4)
|
static boolean SV_AddWaitingPlayers(SINT8 node, UINT8 *availabilities,
|
||||||
|
const char *name, uint8_t *key, const char *name2, uint8_t *key2,
|
||||||
|
const char *name3, uint8_t *key3, const char *name4, uint8_t *key4)
|
||||||
{
|
{
|
||||||
INT32 n, newplayernum, i;
|
INT32 n, newplayernum, i;
|
||||||
UINT8 buf[4 + MAXPLAYERNAME + MAXAVAILABILITY];
|
UINT8 buf[4 + MAXPLAYERNAME + MAXAVAILABILITY];
|
||||||
|
|
@ -3928,21 +3934,25 @@ static boolean SV_AddWaitingPlayers(SINT8 node, UINT8 *availabilities, const cha
|
||||||
{
|
{
|
||||||
nodetoplayer[node] = newplayernum;
|
nodetoplayer[node] = newplayernum;
|
||||||
WRITESTRINGN(buf_p, name, MAXPLAYERNAME);
|
WRITESTRINGN(buf_p, name, MAXPLAYERNAME);
|
||||||
|
WRITESTRINGN(buf_p, key, 32);
|
||||||
}
|
}
|
||||||
else if (playerpernode[node] < 2)
|
else if (playerpernode[node] < 2)
|
||||||
{
|
{
|
||||||
nodetoplayer2[node] = newplayernum;
|
nodetoplayer2[node] = newplayernum;
|
||||||
WRITESTRINGN(buf_p, name2, MAXPLAYERNAME);
|
WRITESTRINGN(buf_p, name2, MAXPLAYERNAME);
|
||||||
|
WRITESTRINGN(buf_p, key2, 32);
|
||||||
}
|
}
|
||||||
else if (playerpernode[node] < 3)
|
else if (playerpernode[node] < 3)
|
||||||
{
|
{
|
||||||
nodetoplayer3[node] = newplayernum;
|
nodetoplayer3[node] = newplayernum;
|
||||||
WRITESTRINGN(buf_p, name3, MAXPLAYERNAME);
|
WRITESTRINGN(buf_p, name3, MAXPLAYERNAME);
|
||||||
|
WRITESTRINGN(buf_p, key3, 32);
|
||||||
}
|
}
|
||||||
else if (playerpernode[node] < 4)
|
else if (playerpernode[node] < 4)
|
||||||
{
|
{
|
||||||
nodetoplayer4[node] = newplayernum;
|
nodetoplayer4[node] = newplayernum;
|
||||||
WRITESTRINGN(buf_p, name4, MAXPLAYERNAME);
|
WRITESTRINGN(buf_p, name4, MAXPLAYERNAME);
|
||||||
|
WRITESTRINGN(buf_p, key4, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITEUINT8(buf_p, nodetoplayer[node]); // consoleplayer
|
WRITEUINT8(buf_p, nodetoplayer[node]); // consoleplayer
|
||||||
|
|
@ -4019,7 +4029,8 @@ boolean SV_SpawnServer(void)
|
||||||
UINT8 *availabilitiesbuffer = R_GetSkinAvailabilities(false, false);
|
UINT8 *availabilitiesbuffer = R_GetSkinAvailabilities(false, false);
|
||||||
SINT8 node = 0;
|
SINT8 node = 0;
|
||||||
for (; node < MAXNETNODES; node++)
|
for (; node < MAXNETNODES; node++)
|
||||||
result |= SV_AddWaitingPlayers(node, availabilitiesbuffer, cv_playername[0].zstring, cv_playername[1].zstring, cv_playername[2].zstring, cv_playername[3].zstring);
|
result |= SV_AddWaitingPlayers(node, availabilitiesbuffer, cv_playername[0].zstring, &PR_GetLocalPlayerProfile(0)->public_key, cv_playername[1].zstring, &PR_GetLocalPlayerProfile(1)->public_key,
|
||||||
|
cv_playername[2].zstring, &PR_GetLocalPlayerProfile(2)->public_key, cv_playername[3].zstring, &PR_GetLocalPlayerProfile(3)->public_key);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -4093,6 +4104,32 @@ static size_t TotalTextCmdPerTic(tic_t tic)
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean IsSplitPlayerOnNodeGuest(int node, int split)
|
||||||
|
{
|
||||||
|
char allZero[32];
|
||||||
|
memset(allZero, 0, 32);
|
||||||
|
|
||||||
|
if (split == 0)
|
||||||
|
return (memcmp(players[nodetoplayer[node]].public_key, allZero, 32) == 0);
|
||||||
|
else if (split == 1)
|
||||||
|
return (memcmp(players[nodetoplayer2[node]].public_key, allZero, 32) == 0);
|
||||||
|
else if (split == 2)
|
||||||
|
return (memcmp(players[nodetoplayer3[node]].public_key, allZero, 32) == 0);
|
||||||
|
else if (split == 3)
|
||||||
|
return (memcmp(players[nodetoplayer4[node]].public_key, allZero, 32) == 0);
|
||||||
|
else
|
||||||
|
I_Error("IsSplitPlayerOnNodeGuest: Out of bounds");
|
||||||
|
return false; // unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean IsPlayerGuest(int player)
|
||||||
|
{
|
||||||
|
char allZero[32];
|
||||||
|
memset(allZero, 0, 32);
|
||||||
|
|
||||||
|
return (memcmp(players[player].public_key, allZero, 32) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
/** Called when a PT_CLIENTJOIN packet is received
|
/** Called when a PT_CLIENTJOIN packet is received
|
||||||
*
|
*
|
||||||
* \param node The packet sender
|
* \param node The packet sender
|
||||||
|
|
@ -4202,8 +4239,6 @@ static void HandleConnect(SINT8 node)
|
||||||
{
|
{
|
||||||
int sigcheck;
|
int sigcheck;
|
||||||
boolean newnode = false;
|
boolean newnode = false;
|
||||||
char allZero[32];
|
|
||||||
memset(allZero, 0, 32);
|
|
||||||
|
|
||||||
for (i = 0; i < netbuffer->u.clientcfg.localplayers - playerpernode[node]; i++)
|
for (i = 0; i < netbuffer->u.clientcfg.localplayers - playerpernode[node]; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -4214,15 +4249,14 @@ static void HandleConnect(SINT8 node)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node == 0) // Server
|
if (node == 0)
|
||||||
{
|
{
|
||||||
memcpy(lastReceivedKey[node][i], PR_GetLocalPlayerProfile(i)->public_key, sizeof(lastReceivedKey[node][i]));
|
memcpy(lastReceivedKey[node][i], PR_GetLocalPlayerProfile(i)->public_key, sizeof(lastReceivedKey[node][i]));
|
||||||
CONS_Printf("Adding SERVER. Setting lastReceivedKey on node %d to %s\n", node, GetPrettyRRID(lastReceivedKey[node][i], true));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CONS_Printf("Adding clients. Doing sigcheck for node %d, ID %s\n", node, GetPrettyRRID(lastReceivedKey[node][i], true));
|
CONS_Printf("Adding remote. Doing sigcheck for node %d, ID %s\n", node, GetPrettyRRID(lastReceivedKey[node][i], true));
|
||||||
if (memcmp(lastReceivedKey[node][i], allZero, 32) == 0) // We're a GUEST and the server throws out our keys anyway.
|
if (IsSplitPlayerOnNodeGuest(node, i)) // We're a GUEST and the server throws out our keys anyway.
|
||||||
{
|
{
|
||||||
sigcheck = 0; // Always succeeds. Yes, this is a success response. C R Y P T O
|
sigcheck = 0; // Always succeeds. Yes, this is a success response. C R Y P T O
|
||||||
if (!cv_allowguests.value)
|
if (!cv_allowguests.value)
|
||||||
|
|
@ -4234,7 +4268,6 @@ static void HandleConnect(SINT8 node)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sigcheck = crypto_eddsa_check(netbuffer->u.clientcfg.challengeResponse[i], lastReceivedKey[node][i], lastSentChallenge[node][i], 32);
|
sigcheck = crypto_eddsa_check(netbuffer->u.clientcfg.challengeResponse[i], lastReceivedKey[node][i], lastSentChallenge[node][i], 32);
|
||||||
CONS_Printf("Sigcheck result: %d\n", sigcheck);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -4283,7 +4316,8 @@ static void HandleConnect(SINT8 node)
|
||||||
DEBFILE("send savegame\n");
|
DEBFILE("send savegame\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
SV_AddWaitingPlayers(node, availabilitiesbuffer, names[0], names[1], names[2], names[3]);
|
SV_AddWaitingPlayers(node, availabilitiesbuffer, names[0], lastReceivedKey[node][0], names[1], lastReceivedKey[node][1],
|
||||||
|
names[2], lastReceivedKey[node][2], names[3], lastReceivedKey[node][3]);
|
||||||
joindelay += cv_joindelay.value * TICRATE;
|
joindelay += cv_joindelay.value * TICRATE;
|
||||||
player_joining = true;
|
player_joining = true;
|
||||||
}
|
}
|
||||||
|
|
@ -4661,6 +4695,19 @@ static boolean CheckForSpeedHacks(UINT8 p)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char NodeToSplitPlayer(int node, int split)
|
||||||
|
{
|
||||||
|
if (split == 0)
|
||||||
|
return nodetoplayer[node];
|
||||||
|
else if (split == 1)
|
||||||
|
return nodetoplayer2[node];
|
||||||
|
else if (split == 2)
|
||||||
|
return nodetoplayer3[node];
|
||||||
|
else if (split == 3)
|
||||||
|
return nodetoplayer4[node];
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/** Handles a packet received from a node that is in game
|
/** Handles a packet received from a node that is in game
|
||||||
*
|
*
|
||||||
* \param node The packet sender
|
* \param node The packet sender
|
||||||
|
|
@ -4691,39 +4738,35 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||||
|
|
||||||
if (server)
|
if (server)
|
||||||
{
|
{
|
||||||
uint8_t allzero[32];
|
|
||||||
memset(allzero, 0, sizeof(allzero));
|
|
||||||
|
|
||||||
int splitnodes;
|
int splitnodes;
|
||||||
if (IsPacketSigned(netbuffer->packettype))
|
if (IsPacketSigned(netbuffer->packettype))
|
||||||
{
|
{
|
||||||
for (splitnodes = 0; splitnodes < MAXSPLITSCREENPLAYERS; splitnodes++)
|
for (splitnodes = 0; splitnodes < MAXSPLITSCREENPLAYERS; splitnodes++)
|
||||||
{
|
{
|
||||||
// Don't try to enforce signatures for players that aren't present.
|
int targetplayer = NodeToSplitPlayer(node, splitnodes);
|
||||||
if (splitnodes > 0 && nodetoplayer2[node] <= 0)
|
if (targetplayer == -1)
|
||||||
break;
|
continue;
|
||||||
if (splitnodes > 1 && nodetoplayer3[node] <= 0)
|
|
||||||
break;
|
|
||||||
if (splitnodes > 2 && nodetoplayer4[node] <= 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
const void* message = &netbuffer->u;
|
const void* message = &netbuffer->u;
|
||||||
if (memcmp(allzero, lastReceivedKey[node][splitnodes], sizeof(allzero)) == 0)
|
if (IsSplitPlayerOnNodeGuest(node, splitnodes))
|
||||||
{
|
{
|
||||||
//CONS_Printf("Throwing out a guest signature from node %d player %d\n", node, splitnodes);
|
//CONS_Printf("Throwing out a guest signature from node %d player %d\n", node, splitnodes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (crypto_eddsa_check(netbuffer->signature[splitnodes], lastReceivedKey[node][splitnodes], message, doomcom->datalength - BASEPACKETSIZE))
|
if (crypto_eddsa_check(netbuffer->signature[splitnodes], players[targetplayer].public_key, message, doomcom->datalength - BASEPACKETSIZE))
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_ERROR, "SIGFAIL! Packet type %d from node %d player %d\nkey %s size %d netconsole %d\n",
|
CONS_Alert(CONS_ERROR, "SIGFAIL! Packet type %d from node %d player %d\nkey %s size %d netconsole %d\n",
|
||||||
netbuffer->packettype, node, splitnodes,
|
netbuffer->packettype, node, splitnodes,
|
||||||
GetPrettyRRID(lastReceivedKey[node][splitnodes], true), doomcom->datalength - BASEPACKETSIZE, netconsole);
|
GetPrettyRRID(players[targetplayer].public_key, true), doomcom->datalength - BASEPACKETSIZE, netconsole);
|
||||||
|
/*
|
||||||
if (netconsole != -1) // NO IDEA.
|
if (netconsole != -1) // NO IDEA.
|
||||||
SendKick(netconsole, KICK_MSG_SIGFAIL);
|
SendKick(netconsole, KICK_MSG_SIGFAIL);
|
||||||
// Net_CloseConnection(node);
|
// Net_CloseConnection(node);
|
||||||
// nodeingame[node] = false;
|
// nodeingame[node] = false;
|
||||||
return;
|
return;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5150,6 +5193,135 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||||
if (client)
|
if (client)
|
||||||
CL_PrepareDownloadLuaFile();
|
CL_PrepareDownloadLuaFile();
|
||||||
break;
|
break;
|
||||||
|
case PT_CHALLENGEALL: ; // -Wpedantic
|
||||||
|
int challengeplayers;
|
||||||
|
memcpy(lastChallengeAll, netbuffer->u.challengeall.secret, sizeof(lastChallengeAll));
|
||||||
|
|
||||||
|
//CONS_Printf("Got PT_CHALLENGEALL from node %d\n", node);
|
||||||
|
|
||||||
|
if (node != servernode)
|
||||||
|
break;
|
||||||
|
|
||||||
|
netbuffer->packettype = PT_RESPONSEALL;
|
||||||
|
|
||||||
|
memset(&netbuffer->u.responseall, 0, sizeof(netbuffer->u.responseall));
|
||||||
|
|
||||||
|
for (challengeplayers = 0; challengeplayers <= splitscreen; challengeplayers++)
|
||||||
|
{
|
||||||
|
uint8_t signature[64];
|
||||||
|
profile_t *localProfile = PR_GetLocalPlayerProfile(challengeplayers);
|
||||||
|
if (PR_IsLocalPlayerGuest(challengeplayers)) // GUESTS don't have keys
|
||||||
|
{
|
||||||
|
memset(signature, 0, 64);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CONS_Printf("signing %s pk %s\n", GetPrettyRRID(lastChallengeAll, true), GetPrettyRRID(localProfile->public_key, true));
|
||||||
|
crypto_eddsa_sign(signature, localProfile->secret_key, lastChallengeAll, sizeof(lastChallengeAll));
|
||||||
|
if (crypto_eddsa_check(signature, localProfile->public_key, lastChallengeAll, sizeof(lastChallengeAll)) != 0)
|
||||||
|
I_Error("Couldn't self-verify key associated with player %d, profile %d.\nProfile data may be corrupted.", challengeplayers, cv_lastprofile[challengeplayers].value); // I guess this is the most reasonable way to catch a malformed key.
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEVELOP
|
||||||
|
if (cv_sigfail.value)
|
||||||
|
{
|
||||||
|
CONS_Alert(CONS_WARNING, "SIGFAIL enabled, scrubbing signature from PT_RESPONSEALL\n");
|
||||||
|
memset(signature, 0, 64);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memcpy(netbuffer->u.responseall.signature[challengeplayers], signature, sizeof(signature));
|
||||||
|
}
|
||||||
|
|
||||||
|
HSendPacket(servernode, true, 0, sizeof(netbuffer->u.responseall));
|
||||||
|
break;
|
||||||
|
case PT_RESPONSEALL:
|
||||||
|
if (server)
|
||||||
|
{
|
||||||
|
int responseplayer;
|
||||||
|
//CONS_Printf("Got PT_RESPONSEALL from node %d, player %d\n", node, nodetoplayer[node]);
|
||||||
|
for (responseplayer = 0; responseplayer < MAXSPLITSCREENPLAYERS; responseplayer++)
|
||||||
|
{
|
||||||
|
int targetplayer = NodeToSplitPlayer(node, responseplayer);
|
||||||
|
if (targetplayer == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (IsSplitPlayerOnNodeGuest(node, responseplayer))
|
||||||
|
{
|
||||||
|
CONS_Printf("GUEST on node %d player %d split %d, leaving blank\n", node, targetplayer, responseplayer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CONS_Printf("receiving %s pk %s\n", GetPrettyRRID(lastChallengeAll, true), GetPrettyRRID(players[targetplayer].public_key, true));
|
||||||
|
if (crypto_eddsa_check(netbuffer->u.responseall.signature[responseplayer],
|
||||||
|
players[targetplayer].public_key, lastChallengeAll, sizeof(lastChallengeAll)))
|
||||||
|
{
|
||||||
|
CONS_Alert(CONS_WARNING, "Invalid PT_RESPONSEALL from node %d player %d split %d\n", node, targetplayer, responseplayer);
|
||||||
|
if (node != -1 && node != 0) // NO IDEA.
|
||||||
|
{
|
||||||
|
//SendKick(node, KICK_MSG_SIGFAIL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CONS_Printf("Writing signature for node %d player %d split %d\n", node, targetplayer, responseplayer);
|
||||||
|
memcpy(lastReceivedSignature[targetplayer], netbuffer->u.responseall.signature[responseplayer], sizeof(lastReceivedSignature[targetplayer]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PT_RESULTSALL: ; // -Wpedantic
|
||||||
|
int resultsplayer;
|
||||||
|
uint8_t allzero[64];
|
||||||
|
memset(allzero, 0, sizeof(allzero));
|
||||||
|
|
||||||
|
if (server)
|
||||||
|
{
|
||||||
|
CONS_Printf("Got PT_RESULTSALL, but what the fuck are you going to do with that?\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (resultsplayer = 0; resultsplayer < MAXPLAYERS; resultsplayer++)
|
||||||
|
{
|
||||||
|
if (!playeringame[resultsplayer])
|
||||||
|
{
|
||||||
|
//CONS_Printf("Player %d isn't in the game, excluded from checkall\n", resultsplayer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (IsPlayerGuest(resultsplayer))
|
||||||
|
{
|
||||||
|
//CONS_Printf("GUEST on node %d player %d split %d, not enforcing\n", playernode[resultsplayer], resultsplayer, players[resultsplayer].splitscreenindex);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (memcmp(knownWhenChallenged[resultsplayer], allzero, sizeof(allzero)) == 0)
|
||||||
|
{
|
||||||
|
CONS_Printf("That motherfucker wasn't here for the challenge - node %d player %d split %d, not enforcing\n", playernode[resultsplayer], resultsplayer, players[resultsplayer].splitscreenindex);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (memcmp(knownWhenChallenged[resultsplayer], players[resultsplayer].public_key, sizeof(knownWhenChallenged[resultsplayer])) != 0)
|
||||||
|
{
|
||||||
|
CONS_Printf("Has key %s but I remember key %s - node %d player %d split %d, not enforcing\n",
|
||||||
|
GetPrettyRRID(knownWhenChallenged[resultsplayer], true), GetPrettyRRID(players[resultsplayer].public_key, true),
|
||||||
|
playernode[resultsplayer], resultsplayer, players[resultsplayer].splitscreenindex);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (crypto_eddsa_check(netbuffer->u.resultsall.signature[resultsplayer],
|
||||||
|
knownWhenChallenged[resultsplayer], lastChallengeAll, sizeof(lastChallengeAll)))
|
||||||
|
{
|
||||||
|
CONS_Alert(CONS_WARNING, "PT_RESULTSALL had invalid signature for node %d player %d split %d, something doesn't add up!\nhas key %s, maybe fucked?\n",
|
||||||
|
playernode[resultsplayer], resultsplayer, players[resultsplayer].splitscreenindex, GetPrettyRRID(knownWhenChallenged[resultsplayer], true));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CONS_Printf("Checkall client-pass for node %d player %d split %d\n", playernode[resultsplayer], resultsplayer, players[resultsplayer].splitscreenindex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n",
|
DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n",
|
||||||
netbuffer->packettype, node));
|
netbuffer->packettype, node));
|
||||||
|
|
@ -5964,6 +6136,105 @@ static void UpdatePingTable(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void UpdateChallenges(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (server)
|
||||||
|
{
|
||||||
|
if (Playing() && (leveltime == CHALLENGEALL_START))
|
||||||
|
{
|
||||||
|
netbuffer->packettype = PT_CHALLENGEALL;
|
||||||
|
|
||||||
|
// Random noise so it's difficult to reuse the response
|
||||||
|
// Current time so that difficult to reuse the challenge (TODO: ACTUALLY DO THIS)
|
||||||
|
csprng(netbuffer->u.serverchallenge.secret, sizeof(netbuffer->u.serverchallenge.secret));
|
||||||
|
// Why the fuck doesn't this work
|
||||||
|
// memcpy(netbuffer->u.serverchallenge.secret, time(NULL), sizeof(int));
|
||||||
|
|
||||||
|
memcpy(lastChallengeAll, netbuffer->u.serverchallenge.secret, sizeof(lastChallengeAll));
|
||||||
|
|
||||||
|
memset(lastReceivedSignature, 0, sizeof(lastReceivedSignature));
|
||||||
|
|
||||||
|
for (i = 0; i < MAXNETNODES; i++)
|
||||||
|
{
|
||||||
|
if (nodeingame[i])
|
||||||
|
{
|
||||||
|
CONS_Printf("challenge to node %d, player %d\n", i, nodetoplayer[i]);
|
||||||
|
HSendPacket(i, true, 0, sizeof(serverchallenge_pak));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Playing() && (leveltime == CHALLENGEALL_SERVERCUTOFF))
|
||||||
|
{
|
||||||
|
netbuffer->packettype = PT_RESULTSALL;
|
||||||
|
|
||||||
|
uint8_t allZero[64];
|
||||||
|
memset(allZero, 0, sizeof(allZero));
|
||||||
|
memset(&netbuffer->u.resultsall, 0, sizeof(netbuffer->u.resultsall));
|
||||||
|
|
||||||
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
{
|
||||||
|
if (!playeringame[i])
|
||||||
|
continue;
|
||||||
|
if (memcmp(lastReceivedSignature[i], allZero, sizeof(allZero)) == 0) // We never got a response!
|
||||||
|
{
|
||||||
|
if (!IsPlayerGuest(i))
|
||||||
|
{
|
||||||
|
CONS_Printf("We never got a response from player %d, goodbye\n", i);
|
||||||
|
//SendKick(i, KICK_MSG_SIGFAIL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CONS_Printf("Player %d passed checkall and has key %s, adding...\n", i, GetPrettyRRID(players[i].public_key, true));
|
||||||
|
memcpy(netbuffer->u.resultsall.signature[i], lastReceivedSignature[i], sizeof(netbuffer->u.resultsall.signature[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < MAXNETNODES; i++)
|
||||||
|
{
|
||||||
|
if (nodeingame[i])
|
||||||
|
{
|
||||||
|
CONS_Printf("results to node %d, player %d\n", i, nodetoplayer[i]);
|
||||||
|
HSendPacket(i, true, 0, sizeof(resultsall_pak));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Playing() && (leveltime == CHALLENGEALL_START))
|
||||||
|
{
|
||||||
|
// Who should we try to verify when results come in?
|
||||||
|
// Store a public key for every active slot, so if players shuffle during challenge leniency,
|
||||||
|
// we don't incorrectly try to verify someone who didn't even get a challenge, throw a tantrum, and bail.
|
||||||
|
|
||||||
|
memset(knownWhenChallenged, 0, sizeof(knownWhenChallenged));
|
||||||
|
|
||||||
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
{
|
||||||
|
if (!playeringame[i])
|
||||||
|
{
|
||||||
|
//CONS_Printf("Player %i isn't present for checkall\n", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (IsPlayerGuest(i))
|
||||||
|
{
|
||||||
|
//CONS_Printf("Player %i is present for checkall, but is a guest\n", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CONS_Printf("Player %d (node %d split %d) is present for checkall, make a note of their key %s...\n", i, playernode[i], players[i].splitscreenindex,
|
||||||
|
GetPrettyRRID(players[i].public_key, true));
|
||||||
|
memcpy(knownWhenChallenged[i], players[i].public_key, sizeof(knownWhenChallenged[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void RenewHolePunch(void)
|
static void RenewHolePunch(void)
|
||||||
{
|
{
|
||||||
static time_t past;
|
static time_t past;
|
||||||
|
|
@ -6009,6 +6280,8 @@ void NetKeepAlive(void)
|
||||||
|
|
||||||
UpdatePingTable();
|
UpdatePingTable();
|
||||||
|
|
||||||
|
UpdateChallenges();
|
||||||
|
|
||||||
GetPackets();
|
GetPackets();
|
||||||
|
|
||||||
#ifdef MASTERSERVER
|
#ifdef MASTERSERVER
|
||||||
|
|
@ -6115,6 +6388,8 @@ void NetUpdate(void)
|
||||||
|
|
||||||
UpdatePingTable();
|
UpdatePingTable();
|
||||||
|
|
||||||
|
UpdateChallenges();
|
||||||
|
|
||||||
if (client)
|
if (client)
|
||||||
maketic = neededtic;
|
maketic = neededtic;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,10 @@ typedef enum
|
||||||
PT_CLIENTKEY, // "Here's my public key"
|
PT_CLIENTKEY, // "Here's my public key"
|
||||||
PT_SERVERCHALLENGE, // "Prove it"
|
PT_SERVERCHALLENGE, // "Prove it"
|
||||||
|
|
||||||
|
PT_CHALLENGEALL, // Prove to the other clients you are who you say you are, sign this random bullshit!
|
||||||
|
PT_RESPONSEALL, // OK, here is my signature on that random bullshit
|
||||||
|
PT_RESULTSALL, // Here's what everyone responded to PT_CHALLENGEALL with, if this is wrong or you don't receive it disconnect
|
||||||
|
|
||||||
NUMPACKETTYPE
|
NUMPACKETTYPE
|
||||||
} packettype_t;
|
} packettype_t;
|
||||||
|
|
||||||
|
|
@ -361,6 +365,21 @@ struct serverchallenge_pak
|
||||||
char secret[MAXSPLITSCREENPLAYERS][32];
|
char secret[MAXSPLITSCREENPLAYERS][32];
|
||||||
} ATTRPACK;
|
} ATTRPACK;
|
||||||
|
|
||||||
|
struct challengeall_pak
|
||||||
|
{
|
||||||
|
uint8_t secret[64];
|
||||||
|
} ATTRPACK;
|
||||||
|
|
||||||
|
struct responseall_pak
|
||||||
|
{
|
||||||
|
uint8_t signature[MAXSPLITSCREENPLAYERS][64];
|
||||||
|
} ATTRPACK;
|
||||||
|
|
||||||
|
struct resultsall_pak
|
||||||
|
{
|
||||||
|
uint8_t signature[MAXPLAYERS][64];
|
||||||
|
} ATTRPACK;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Network packet data
|
// Network packet data
|
||||||
//
|
//
|
||||||
|
|
@ -398,6 +417,9 @@ struct doomdata_t
|
||||||
UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes
|
UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes
|
||||||
clientkey_pak clientkey; // TODO: Tyron, does anyone take any of these sizes even remotely seriously
|
clientkey_pak clientkey; // TODO: Tyron, does anyone take any of these sizes even remotely seriously
|
||||||
serverchallenge_pak serverchallenge; // Are you even going to update this shit, are you even going to remove this comment
|
serverchallenge_pak serverchallenge; // Are you even going to update this shit, are you even going to remove this comment
|
||||||
|
challengeall_pak challengeall;
|
||||||
|
responseall_pak responseall;
|
||||||
|
resultsall_pak resultsall;
|
||||||
} u; // This is needed to pack diff packet types data together
|
} u; // This is needed to pack diff packet types data together
|
||||||
} ATTRPACK;
|
} ATTRPACK;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -813,7 +813,14 @@ static const char *packettypename[NUMPACKETTYPE] =
|
||||||
|
|
||||||
"LOGIN",
|
"LOGIN",
|
||||||
|
|
||||||
"PING"
|
"PING",
|
||||||
|
|
||||||
|
"CLIENTKEY",
|
||||||
|
"SERVERCHALLENGE",
|
||||||
|
|
||||||
|
"CHALLENGEALL",
|
||||||
|
"RESPONSEALL",
|
||||||
|
"RESULTSALL"
|
||||||
};
|
};
|
||||||
|
|
||||||
static void DebugPrintpacket(const char *header)
|
static void DebugPrintpacket(const char *header)
|
||||||
|
|
|
||||||
|
|
@ -713,7 +713,7 @@ struct player_t
|
||||||
mobj_t *stumbleIndicator;
|
mobj_t *stumbleIndicator;
|
||||||
mobj_t *sliptideZipIndicator;
|
mobj_t *sliptideZipIndicator;
|
||||||
|
|
||||||
uint8_t public_key[32 + 1];
|
uint8_t public_key[32];
|
||||||
|
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
fixed_t fovadd; // adjust FOV for hw rendering
|
fixed_t fovadd; // adjust FOV for hw rendering
|
||||||
|
|
|
||||||
|
|
@ -878,7 +878,7 @@ static int player_set(lua_State *L)
|
||||||
else if (fastcmp(field,"bot"))
|
else if (fastcmp(field,"bot"))
|
||||||
return NOSET;
|
return NOSET;
|
||||||
else if (fastcmp(field,"jointime"))
|
else if (fastcmp(field,"jointime"))
|
||||||
plr->jointime = (tic_t)luaL_checkinteger(L, 3);
|
return NOSET;
|
||||||
else if (fastcmp(field,"splitscreenindex"))
|
else if (fastcmp(field,"splitscreenindex"))
|
||||||
return NOSET;
|
return NOSET;
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,9 @@ TYPEDEF (serverelem_t);
|
||||||
TYPEDEF (rewind_t);
|
TYPEDEF (rewind_t);
|
||||||
TYPEDEF (clientkey_pak);
|
TYPEDEF (clientkey_pak);
|
||||||
TYPEDEF (serverchallenge_pak);
|
TYPEDEF (serverchallenge_pak);
|
||||||
|
TYPEDEF (challengeall_pak);
|
||||||
|
TYPEDEF (responseall_pak);
|
||||||
|
TYPEDEF (resultsall_pak);
|
||||||
|
|
||||||
// d_event.h
|
// d_event.h
|
||||||
TYPEDEF (event_t);
|
TYPEDEF (event_t);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue