- Implement dual protocol support (#4962)
- Fix several UDP spoofing security issues
This commit is contained in:
parent
309c322b80
commit
e06c117e9e
13 changed files with 550 additions and 247 deletions
|
@ -533,7 +533,6 @@ void CL_WriteDemoMessage ( msg_t *msg, int headerBytes ) {
|
|||
len = clc.serverMessageSequence;
|
||||
swlen = LittleLong( len );
|
||||
FS_Write (&swlen, 4, clc.demofile);
|
||||
|
||||
// skip the packet sequencing information
|
||||
len = msg->cursize - headerBytes;
|
||||
swlen = LittleLong(len);
|
||||
|
@ -636,14 +635,24 @@ void CL_Record_f( void ) {
|
|||
if ( Cmd_Argc() == 2 ) {
|
||||
s = Cmd_Argv(1);
|
||||
Q_strncpyz( demoName, s, sizeof( demoName ) );
|
||||
Com_sprintf (name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer );
|
||||
#ifdef LEGACY_PROTOCOL
|
||||
if(clc.compat)
|
||||
Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_legacyprotocol->integer);
|
||||
else
|
||||
#endif
|
||||
Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer);
|
||||
} else {
|
||||
int number;
|
||||
|
||||
// scan for a free demo name
|
||||
for ( number = 0 ; number <= 9999 ; number++ ) {
|
||||
CL_DemoFilename( number, demoName );
|
||||
Com_sprintf (name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer );
|
||||
#ifdef LEGACY_PROTOCOL
|
||||
if(clc.compat)
|
||||
Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_legacyprotocol->integer);
|
||||
else
|
||||
#endif
|
||||
Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer);
|
||||
|
||||
if (!FS_FileExists(name))
|
||||
break; // file doesn't exist
|
||||
|
@ -665,7 +674,6 @@ void CL_Record_f( void ) {
|
|||
clc.spDemoRecording = qfalse;
|
||||
}
|
||||
|
||||
|
||||
Q_strncpyz( clc.demoName, demoName, sizeof( clc.demoName ) );
|
||||
|
||||
// don't start saving messages until a non-delta compressed message is received
|
||||
|
@ -889,36 +897,62 @@ void CL_ReadDemoMessage( void ) {
|
|||
CL_WalkDemoExt
|
||||
====================
|
||||
*/
|
||||
static void CL_WalkDemoExt(char *arg, char *name, int *demofile)
|
||||
static int CL_WalkDemoExt(char *arg, char *name, int *demofile)
|
||||
{
|
||||
int i = 0;
|
||||
*demofile = 0;
|
||||
|
||||
Com_sprintf (name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, com_protocol->integer);
|
||||
|
||||
FS_FOpenFileRead( name, demofile, qtrue );
|
||||
|
||||
if (*demofile)
|
||||
#ifdef LEGACY_PROTOCOL
|
||||
if(com_legacyprotocol->integer > 0)
|
||||
{
|
||||
Com_Printf("Demo file: %s\n", name);
|
||||
return;
|
||||
Com_sprintf(name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, com_legacyprotocol->integer);
|
||||
FS_FOpenFileRead(name, demofile, qtrue);
|
||||
|
||||
if (*demofile)
|
||||
{
|
||||
Com_Printf("Demo file: %s\n", name);
|
||||
return com_legacyprotocol->integer;
|
||||
}
|
||||
}
|
||||
|
||||
if(com_protocol->integer != com_legacyprotocol->integer)
|
||||
#endif
|
||||
{
|
||||
Com_sprintf(name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, com_protocol->integer);
|
||||
FS_FOpenFileRead(name, demofile, qtrue);
|
||||
|
||||
if (*demofile)
|
||||
{
|
||||
Com_Printf("Demo file: %s\n", name);
|
||||
return com_protocol->integer;
|
||||
}
|
||||
}
|
||||
|
||||
Com_Printf("Not found: %s\n", name);
|
||||
|
||||
while(demo_protocols[i])
|
||||
{
|
||||
#ifdef LEGACY_PROTOCOL
|
||||
if(demo_protocols[i] == com_legacyprotocol->integer)
|
||||
continue;
|
||||
#endif
|
||||
if(demo_protocols[i] == com_protocol->integer)
|
||||
continue;
|
||||
|
||||
Com_sprintf (name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, demo_protocols[i]);
|
||||
FS_FOpenFileRead( name, demofile, qtrue );
|
||||
if (*demofile)
|
||||
{
|
||||
Com_Printf("Demo file: %s\n", name);
|
||||
break;
|
||||
|
||||
return demo_protocols[i];
|
||||
}
|
||||
else
|
||||
Com_Printf("Not found: %s\n", name);
|
||||
i++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -978,7 +1012,11 @@ void CL_PlayDemo_f( void ) {
|
|||
break;
|
||||
}
|
||||
|
||||
if(demo_protocols[i] || protocol == com_protocol->integer)
|
||||
if(demo_protocols[i] || protocol == com_protocol->integer
|
||||
#ifdef LEGACY_PROTOCOL
|
||||
|| protocol == com_legacyprotocol->integer
|
||||
#endif
|
||||
)
|
||||
{
|
||||
Com_sprintf(name, sizeof(name), "demos/%s", arg);
|
||||
FS_FOpenFileRead(name, &clc.demofile, qtrue);
|
||||
|
@ -995,11 +1033,11 @@ void CL_PlayDemo_f( void ) {
|
|||
|
||||
Q_strncpyz(retry, arg, len + 1);
|
||||
retry[len] = '\0';
|
||||
CL_WalkDemoExt(retry, name, &clc.demofile);
|
||||
protocol = CL_WalkDemoExt(retry, name, &clc.demofile);
|
||||
}
|
||||
}
|
||||
else
|
||||
CL_WalkDemoExt(arg, name, &clc.demofile);
|
||||
protocol = CL_WalkDemoExt(arg, name, &clc.demofile);
|
||||
|
||||
if (!clc.demofile) {
|
||||
Com_Error( ERR_DROP, "couldn't open %s", name);
|
||||
|
@ -1013,6 +1051,13 @@ void CL_PlayDemo_f( void ) {
|
|||
clc.demoplaying = qtrue;
|
||||
Q_strncpyz( clc.servername, Cmd_Argv(1), sizeof( clc.servername ) );
|
||||
|
||||
#ifdef LEGACY_PROTOCOL
|
||||
if(protocol <= com_legacyprotocol->integer)
|
||||
clc.compat = qtrue;
|
||||
else
|
||||
clc.compat = qfalse;
|
||||
#endif
|
||||
|
||||
// read demo messages until connected
|
||||
while ( clc.state >= CA_CONNECTED && clc.state < CA_PRIMED ) {
|
||||
CL_ReadDemoMessage();
|
||||
|
@ -2180,7 +2225,9 @@ void CL_CheckForResend( void ) {
|
|||
#endif
|
||||
|
||||
// The challenge request shall be followed by a client challenge so no malicious server can hijack this connection.
|
||||
Com_sprintf(data, sizeof(data), "getchallenge %d", clc.challenge);
|
||||
// Add the heartbeat gamename so the server knows we're running the correct game and can reject the client
|
||||
// with a meaningful message
|
||||
Com_sprintf(data, sizeof(data), "getchallenge %d %s", clc.challenge, Cvar_VariableString("sv_heartbeat"));
|
||||
|
||||
NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "%s", data);
|
||||
break;
|
||||
|
@ -2190,7 +2237,16 @@ void CL_CheckForResend( void ) {
|
|||
port = Cvar_VariableValue ("net_qport");
|
||||
|
||||
Q_strncpyz( info, Cvar_InfoString( CVAR_USERINFO ), sizeof( info ) );
|
||||
Info_SetValueForKey( info, "protocol", va("%i", com_protocol->integer ) );
|
||||
|
||||
#ifdef LEGACY_PROTOCOL
|
||||
if(com_legacyprotocol->integer == com_protocol->integer)
|
||||
clc.compat = qtrue;
|
||||
|
||||
if(clc.compat)
|
||||
Info_SetValueForKey(info, "protocol", va("%i", com_legacyprotocol->integer));
|
||||
else
|
||||
#endif
|
||||
Info_SetValueForKey(info, "protocol", va("%i", com_protocol->integer));
|
||||
Info_SetValueForKey( info, "qport", va("%i", port ) );
|
||||
Info_SetValueForKey( info, "challenge", va("%i", clc.challenge ) );
|
||||
|
||||
|
@ -2431,6 +2487,7 @@ Responses to broadcasts, etc
|
|||
void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
|
||||
char *s;
|
||||
char *c;
|
||||
int challenge;
|
||||
|
||||
MSG_BeginReadingOOB( msg );
|
||||
MSG_ReadLong( msg ); // skip the -1
|
||||
|
@ -2446,23 +2503,70 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
|
|||
// challenge from the server we are connecting to
|
||||
if (!Q_stricmp(c, "challengeResponse"))
|
||||
{
|
||||
char *strver;
|
||||
int ver;
|
||||
|
||||
if (clc.state != CA_CONNECTING)
|
||||
{
|
||||
Com_DPrintf("Unwanted challenge response received. Ignored.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!NET_CompareAdr(from, clc.serverAddress))
|
||||
c = Cmd_Argv(2);
|
||||
if(*c)
|
||||
challenge = atoi(c);
|
||||
|
||||
strver = Cmd_Argv(3);
|
||||
if(*strver)
|
||||
{
|
||||
// This challenge response is not coming from the expected address.
|
||||
// Check whether we have a matching client challenge to prevent
|
||||
// connection hi-jacking.
|
||||
ver = atoi(strver);
|
||||
|
||||
c = Cmd_Argv(2);
|
||||
|
||||
if(!*c || atoi(c) != clc.challenge)
|
||||
if(ver != com_protocol->integer)
|
||||
{
|
||||
Com_DPrintf("Challenge response received from unexpected source. Ignored.\n");
|
||||
#ifdef LEGACY_PROTOCOL
|
||||
if(com_legacyprotocol->integer > 0)
|
||||
{
|
||||
// Server is ioq3 but has a different protocol than we do.
|
||||
// Fall back to idq3 protocol.
|
||||
clc.compat = qtrue;
|
||||
|
||||
Com_Printf(S_COLOR_YELLOW "Warning: Server reports protocol version %d, "
|
||||
"we have %d. Trying legacy protocol %d.\n",
|
||||
ver, com_protocol->integer, com_legacyprotocol->integer);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Com_Printf(S_COLOR_YELLOW "Warning: Server reports protocol version %d, we have %d. "
|
||||
"Trying anyways.\n", ver, com_protocol->integer);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef LEGACY_PROTOCOL
|
||||
else
|
||||
clc.compat = qtrue;
|
||||
|
||||
if(clc.compat)
|
||||
{
|
||||
if(!NET_CompareAdr(from, clc.serverAddress))
|
||||
{
|
||||
// This challenge response is not coming from the expected address.
|
||||
// Check whether we have a matching client challenge to prevent
|
||||
// connection hi-jacking.
|
||||
|
||||
if(!*c || challenge != clc.challenge)
|
||||
{
|
||||
Com_DPrintf("Challenge response received from unexpected source. Ignored.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if(!*c || challenge != clc.challenge)
|
||||
{
|
||||
Com_Printf("Bad challenge for challengeResponse. Ignored.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2494,7 +2598,36 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
|
|||
Com_Printf( "connectResponse from wrong address. Ignored.\n" );
|
||||
return;
|
||||
}
|
||||
Netchan_Setup (NS_CLIENT, &clc.netchan, from, Cvar_VariableValue( "net_qport" ) );
|
||||
|
||||
#ifdef LEGACY_PROTOCOL
|
||||
if(!clc.compat)
|
||||
#endif
|
||||
{
|
||||
c = Cmd_Argv(1);
|
||||
|
||||
if(*c)
|
||||
challenge = atoi(c);
|
||||
else
|
||||
{
|
||||
Com_Printf("Bad connectResponse received. Ignored.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(challenge != clc.challenge)
|
||||
{
|
||||
Com_Printf("ConnectResponse with bad challenge received. Ignored.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LEGACY_PROTOCOL
|
||||
Netchan_Setup(NS_CLIENT, &clc.netchan, from, Cvar_VariableValue("net_qport"),
|
||||
clc.challenge, clc.compat);
|
||||
#else
|
||||
Netchan_Setup(NS_CLIENT, &clc.netchan, from, Cvar_VariableValue("net_qport"),
|
||||
clc.challenge, qfalse);
|
||||
#endif
|
||||
|
||||
clc.state = CA_CONNECTED;
|
||||
clc.lastPacketSentTime = -9999; // send first packet immediately
|
||||
return;
|
||||
|
@ -2512,13 +2645,6 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
|
|||
return;
|
||||
}
|
||||
|
||||
// a disconnect message from the server, which will happen if the server
|
||||
// dropped the connection but it is still getting packets from us
|
||||
if (!Q_stricmp(c, "disconnect")) {
|
||||
CL_DisconnectPacket( from );
|
||||
return;
|
||||
}
|
||||
|
||||
// echo request from server
|
||||
if ( !Q_stricmp(c, "echo") ) {
|
||||
NET_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv(1) );
|
||||
|
@ -2538,10 +2664,12 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
|
|||
}
|
||||
|
||||
// echo request from server
|
||||
if ( !Q_stricmp(c, "print") ) {
|
||||
if(!Q_stricmp(c, "print")){
|
||||
s = MSG_ReadString( msg );
|
||||
|
||||
Q_strncpyz( clc.serverMessage, s, sizeof( clc.serverMessage ) );
|
||||
Com_Printf( "%s", s );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3492,7 +3620,13 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) {
|
|||
|
||||
// if this isn't the correct protocol version, ignore it
|
||||
prot = atoi( Info_ValueForKey( infoString, "protocol" ) );
|
||||
if ( prot != com_protocol->integer ) {
|
||||
|
||||
if(prot != com_protocol->integer
|
||||
#ifdef LEGACY_PROTOCOL
|
||||
&& prot != com_legacyprotocol->integer
|
||||
#endif
|
||||
)
|
||||
{
|
||||
Com_DPrintf( "Different protocol info packet: %s\n", infoString );
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue