- Implement dual protocol support (#4962)

- Fix several UDP spoofing security issues
This commit is contained in:
Thilo Schulz 2011-07-12 11:59:48 +00:00
parent 309c322b80
commit e06c117e9e
13 changed files with 550 additions and 247 deletions

View file

@ -32,7 +32,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#endif
int demo_protocols[] =
{ 66, 67, 68, 0 };
{ 67, 66, 0 };
#define MAX_NUM_ARGVS 50
@ -87,6 +87,9 @@ cvar_t *com_maxfpsMinimized;
cvar_t *com_abnormalExit;
cvar_t *com_standalone;
cvar_t *com_protocol;
#ifdef LEGACY_PROTOCOL
cvar_t *com_legacyprotocol;
#endif
cvar_t *com_basegame;
cvar_t *com_homepath;
cvar_t *com_busyWait;
@ -2796,7 +2799,16 @@ void Com_Init( char *commandLine ) {
s = va("%s %s %s", Q3_VERSION, PLATFORM_STRING, __DATE__ );
com_version = Cvar_Get ("version", s, CVAR_ROM | CVAR_SERVERINFO );
com_protocol = Cvar_Get ("protocol", va("%i", PROTOCOL_VERSION), CVAR_SERVERINFO | CVAR_INIT);
com_protocol = Cvar_Get("com_protocol", va("%i", PROTOCOL_VERSION), CVAR_SERVERINFO | CVAR_INIT);
#ifdef LEGACY_PROTOCOL
com_legacyprotocol = Cvar_Get("com_legacyprotocol", va("%i", PROTOCOL_LEGACY_VERSION), CVAR_INIT);
// Keep for compatibility with old mods / mods that haven't updated yet.
if(com_legacyprotocol->integer > 0)
Cvar_Get("protocol", com_legacyprotocol->string, CVAR_ROM);
else
#endif
Cvar_Get("protocol", com_protocol->string, CVAR_ROM);
Sys_Init();

View file

@ -1056,6 +1056,11 @@ qboolean FS_IsDemoExt(const char *filename, int namelen)
if(protocol == com_protocol->integer)
return qtrue;
#ifdef LEGACY_PROTOCOL
if(protocol == com_legacyprotocol->integer)
return qtrue;
#endif
for(index = 0; demo_protocols[index]; index++)
{
if(demo_protocols[index] == protocol)

View file

@ -83,7 +83,8 @@ Netchan_Setup
called to open a channel to a remote system
==============
*/
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport ) {
void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int challenge, qboolean compat)
{
Com_Memset (chan, 0, sizeof(*chan));
chan->sock = sock;
@ -91,6 +92,11 @@ void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport ) {
chan->qport = qport;
chan->incomingSequence = 0;
chan->outgoingSequence = 1;
chan->challenge = challenge;
#ifdef LEGACY_PROTOCOL
chan->compat = compat;
#endif
}
// TTimo: unused, commenting out to make gcc happy
@ -190,17 +196,24 @@ void Netchan_TransmitNextFragment( netchan_t *chan ) {
msg_t send;
byte send_buf[MAX_PACKETLEN];
int fragmentLength;
int outgoingSequence;
// write the packet header
MSG_InitOOB (&send, send_buf, sizeof(send_buf)); // <-- only do the oob here
MSG_WriteLong( &send, chan->outgoingSequence | FRAGMENT_BIT );
outgoingSequence = chan->outgoingSequence | FRAGMENT_BIT;
MSG_WriteLong(&send, outgoingSequence);
// send the qport if we are a client
if ( chan->sock == NS_CLIENT ) {
MSG_WriteShort( &send, qport->integer );
}
#ifdef LEGACY_PROTOCOL
if(!chan->compat)
#endif
MSG_WriteLong(&send, NETCHAN_GENCHECKSUM(chan->challenge, chan->outgoingSequence));
// copy the reliable message to the packet first
fragmentLength = FRAGMENT_SIZE;
if ( chan->unsentFragmentStart + fragmentLength > chan->unsentLength ) {
@ -268,12 +281,17 @@ void Netchan_Transmit( netchan_t *chan, int length, const byte *data ) {
MSG_InitOOB (&send, send_buf, sizeof(send_buf));
MSG_WriteLong( &send, chan->outgoingSequence );
chan->outgoingSequence++;
// send the qport if we are a client
if ( chan->sock == NS_CLIENT ) {
MSG_WriteShort( &send, qport->integer );
}
if(chan->sock == NS_CLIENT)
MSG_WriteShort(&send, qport->integer);
#ifdef LEGACY_PROTOCOL
if(!chan->compat)
#endif
MSG_WriteLong(&send, NETCHAN_GENCHECKSUM(chan->challenge, chan->outgoingSequence));
chan->outgoingSequence++;
MSG_WriteData( &send, data, length );
@ -327,6 +345,17 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
qport = MSG_ReadShort( msg );
}
#ifdef LEGACY_PROTOCOL
if(!chan->compat)
#endif
{
int checksum = MSG_ReadLong(msg);
// UDP spoofing protection
if(NETCHAN_GENCHECKSUM(chan->challenge, sequence) != checksum)
return qfalse;
}
// read the fragment information
if ( fragmented ) {
fragmentStart = MSG_ReadShort( msg );

View file

@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define HOMEPATH_NAME_UNIX ".foo"
#define HOMEPATH_NAME_WIN "FooBar"
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
// #define LEGACY_PROTOCOL // You probably don't need this for your standalone game
#else
#define PRODUCT_NAME "ioq3"
#define BASEGAME "baseq3"
@ -48,6 +49,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define HOMEPATH_NAME_UNIX ".q3a"
#define HOMEPATH_NAME_WIN "Quake3"
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
#define LEGACY_PROTOCOL
#endif
#define BASETA "missionpack"

View file

@ -195,7 +195,8 @@ void NET_Sleep(int msec);
#define MAX_DOWNLOAD_WINDOW 48 // ACK window of 48 download chunks. Cannot set this higher, or clients
// will overflow the reliable commands buffer
#define MAX_DOWNLOAD_BLKSIZE 1024 // 896 byte block chunks
#define NETCHAN_GENCHECKSUM(challenge, sequence) ((challenge) ^ ((sequence) * (challenge)))
/*
Netchan handles packet fragmentation and out of order / duplicate suppression
@ -224,10 +225,16 @@ typedef struct {
int unsentFragmentStart;
int unsentLength;
byte unsentBuffer[MAX_MSGLEN];
int challenge;
#ifdef LEGACY_PROTOCOL
qboolean compat;
#endif
} netchan_t;
void Netchan_Init( int qport );
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport );
void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int challenge, qboolean compat);
void Netchan_Transmit( netchan_t *chan, int length, const byte *data );
void Netchan_TransmitNextFragment( netchan_t *chan );
@ -243,7 +250,8 @@ PROTOCOL
==============================================================
*/
#define PROTOCOL_VERSION 68
#define PROTOCOL_VERSION 69
#define PROTOCOL_LEGACY_VERSION 68
// 1.31 - 67
// maintain a list of compatible protocols for demo playing
@ -863,6 +871,9 @@ extern cvar_t *cl_packetdelay;
extern cvar_t *sv_packetdelay;
extern cvar_t *com_protocol;
#ifdef LEGACY_PROTOCOL
extern cvar_t *com_legacyprotocol;
#endif
// com_speeds times
extern int time_game;