- Harden the client and server protocol against UDP spoofing attacks. This will defend ioquake3 against http://aluigi.altervista.org/papers/q3noclient.txt (#3041)
- Retains full compatibility to the old but unsecure protocol between clients and servers - Harden the connection process against DoS attacks, possibly connected to UDP spoofing
This commit is contained in:
parent
06d12f6085
commit
a5580d8974
11 changed files with 296 additions and 75 deletions
|
@ -55,8 +55,10 @@ void SV_GetChallenge(netadr_t from)
|
|||
int i;
|
||||
int oldest;
|
||||
int oldestTime;
|
||||
const char *clientChallenge = Cmd_Argv(1);
|
||||
int oldestClientTime;
|
||||
int clientChallenge;
|
||||
challenge_t *challenge;
|
||||
qboolean wasfound = qfalse;
|
||||
|
||||
// ignore if we are in single player
|
||||
if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive")) {
|
||||
|
@ -64,15 +66,30 @@ void SV_GetChallenge(netadr_t from)
|
|||
}
|
||||
|
||||
oldest = 0;
|
||||
oldestTime = 0x7fffffff;
|
||||
oldestClientTime = oldestTime = 0x7fffffff;
|
||||
|
||||
// see if we already have a challenge for this ip
|
||||
challenge = &svs.challenges[0];
|
||||
for (i = 0 ; i < MAX_CHALLENGES ; i++, challenge++) {
|
||||
if (!challenge->connected && NET_CompareAdr( from, challenge->adr ) ) {
|
||||
clientChallenge = atoi(Cmd_Argv(1));
|
||||
|
||||
for(i = 0 ; i < MAX_CHALLENGES ; i++, challenge++)
|
||||
{
|
||||
if(!challenge->connected && NET_CompareAdr(from, challenge->adr))
|
||||
{
|
||||
wasfound = qtrue;
|
||||
|
||||
if(challenge->time < oldestClientTime)
|
||||
oldestClientTime = challenge->time;
|
||||
}
|
||||
|
||||
if(wasfound && i >= MAX_CHALLENGES_MULTI)
|
||||
{
|
||||
i = MAX_CHALLENGES;
|
||||
break;
|
||||
}
|
||||
if ( challenge->time < oldestTime ) {
|
||||
|
||||
if(challenge->time < oldestTime)
|
||||
{
|
||||
oldestTime = challenge->time;
|
||||
oldest = i;
|
||||
}
|
||||
|
@ -82,17 +99,16 @@ void SV_GetChallenge(netadr_t from)
|
|||
{
|
||||
// this is the first time this client has asked for a challenge
|
||||
challenge = &svs.challenges[oldest];
|
||||
challenge->clientChallenge = 0;
|
||||
challenge->clientChallenge = clientChallenge;
|
||||
challenge->adr = from;
|
||||
challenge->firstTime = svs.time;
|
||||
challenge->time = svs.time;
|
||||
challenge->connected = qfalse;
|
||||
}
|
||||
|
||||
// always generate a new challenge number, so the client cannot circumvent sv_maxping
|
||||
challenge->challenge = ( (rand() << 16) ^ rand() ) ^ svs.time;
|
||||
challenge->wasrefused = qfalse;
|
||||
|
||||
challenge->time = svs.time;
|
||||
|
||||
#ifndef STANDALONE
|
||||
// Drop the authorize stuff if this client is coming in via v6 as the auth server does not support ipv6.
|
||||
|
@ -121,7 +137,7 @@ void SV_GetChallenge(netadr_t from)
|
|||
// if they have been challenging for a long time and we
|
||||
// haven't heard anything from the authorize server, go ahead and
|
||||
// let them in, assuming the id server is down
|
||||
else if(svs.time - challenge->firstTime > AUTHORIZE_TIMEOUT)
|
||||
else if(svs.time - oldestClientTime > AUTHORIZE_TIMEOUT)
|
||||
Com_DPrintf( "authorize server timed out\n" );
|
||||
else
|
||||
{
|
||||
|
@ -129,10 +145,6 @@ void SV_GetChallenge(netadr_t from)
|
|||
cvar_t *fs;
|
||||
char game[1024];
|
||||
|
||||
// If the client provided us with a client challenge, store it...
|
||||
if(*clientChallenge)
|
||||
challenge->clientChallenge = atoi(clientChallenge);
|
||||
|
||||
Com_DPrintf( "sending getIpAuthorize for %s\n", NET_AdrToString( from ));
|
||||
|
||||
strcpy(game, BASEGAME);
|
||||
|
@ -153,7 +165,7 @@ void SV_GetChallenge(netadr_t from)
|
|||
#endif
|
||||
|
||||
challenge->pingTime = svs.time;
|
||||
NET_OutOfBandPrint( NS_SERVER, challenge->adr, "challengeResponse %i %s", challenge->challenge, clientChallenge);
|
||||
NET_OutOfBandPrint( NS_SERVER, challenge->adr, "challengeResponse %i %d", challenge->challenge, clientChallenge);
|
||||
}
|
||||
|
||||
#ifndef STANDALONE
|
||||
|
@ -289,6 +301,9 @@ void SV_DirectConnect( netadr_t from ) {
|
|||
intptr_t denied;
|
||||
int count;
|
||||
char *ip;
|
||||
#ifdef PROTOCOL_SUPPORT_OLD
|
||||
qboolean compat = qfalse;
|
||||
#endif
|
||||
|
||||
Com_DPrintf ("SVC_DirectConnect ()\n");
|
||||
|
||||
|
@ -301,11 +316,21 @@ void SV_DirectConnect( netadr_t from ) {
|
|||
|
||||
Q_strncpyz( userinfo, Cmd_Argv(1), sizeof(userinfo) );
|
||||
|
||||
version = atoi( Info_ValueForKey( userinfo, "protocol" ) );
|
||||
if ( version != com_protocol->integer ) {
|
||||
NET_OutOfBandPrint( NS_SERVER, from, "print\nServer uses protocol version %i (yours is %i).\n", com_protocol->integer, version );
|
||||
Com_DPrintf (" rejected connect from version %i\n", version);
|
||||
return;
|
||||
version = atoi(Info_ValueForKey(userinfo, "protocol"));
|
||||
|
||||
#ifdef PROTOCOL_SUPPORT_OLD
|
||||
if(version > 0 && com_oldprotocol->integer == version)
|
||||
compat = qtrue;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if(version != com_protocol->integer)
|
||||
{
|
||||
NET_OutOfBandPrint(NS_SERVER, from, "print\nServer uses protocol version %i "
|
||||
"(yours is %i).\n", com_protocol->integer, version);
|
||||
Com_DPrintf(" rejected connect from version %i\n", version);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
challenge = atoi( Info_ValueForKey( userinfo, "challenge" ) );
|
||||
|
@ -487,7 +512,12 @@ gotnewcl:
|
|||
newcl->challenge = challenge;
|
||||
|
||||
// save the address
|
||||
Netchan_Setup (NS_SERVER, &newcl->netchan , from, qport);
|
||||
#ifdef PROTOCOL_SUPPORT_OLD
|
||||
newcl->compat = compat;
|
||||
Netchan_Setup(NS_SERVER, &newcl->netchan, from, qport, challenge, compat);
|
||||
#else
|
||||
Netchan_Setup(NS_SERVER, &newcl->netchan, from, qport, challenge);
|
||||
#endif
|
||||
// init the netchan queue
|
||||
newcl->netchan_end_queue = &newcl->netchan_start_queue;
|
||||
|
||||
|
@ -508,7 +538,7 @@ gotnewcl:
|
|||
SV_UserinfoChanged( newcl );
|
||||
|
||||
// send the connect packet to the client
|
||||
NET_OutOfBandPrint( NS_SERVER, from, "connectResponse" );
|
||||
NET_OutOfBandPrint(NS_SERVER, from, "connectResponse %d", challenge);
|
||||
|
||||
Com_DPrintf( "Going from CS_FREE to CS_CONNECTED for %s\n", newcl->name );
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue