aboutsummaryrefslogtreecommitdiffstats
path: root/code
diff options
context:
space:
mode:
Diffstat (limited to 'code')
-rw-r--r--code/qcommon/qcommon.h2
-rw-r--r--code/server/server.h3
-rw-r--r--code/server/sv_client.c121
-rw-r--r--code/server/sv_main.c2
4 files changed, 68 insertions, 60 deletions
diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h
index 58c376a..5282de5 100644
--- a/code/qcommon/qcommon.h
+++ b/code/qcommon/qcommon.h
@@ -132,8 +132,8 @@ NET
#define MAX_RELIABLE_COMMANDS 64 // max string commands buffered for restransmit
typedef enum {
+ NA_BAD = 0, // an address lookup failed
NA_BOT,
- NA_BAD, // an address lookup failed
NA_LOOPBACK,
NA_BROADCAST,
NA_IP,
diff --git a/code/server/server.h b/code/server/server.h
index a194e45..eab244b 100644
--- a/code/server/server.h
+++ b/code/server/server.h
@@ -204,6 +204,7 @@ typedef struct client_s {
typedef struct {
netadr_t adr;
int challenge;
+ int clientChallenge; // challenge number coming from the client
int time; // time the last packet was sent to the autherize server
int pingTime; // time the challenge response was sent to client
int firstTime; // time the adr was first used, for authorize timeout checks
@@ -326,7 +327,7 @@ void SV_SpawnServer( char *server, qboolean killBots );
//
// sv_client.c
//
-void SV_GetChallenge( netadr_t from );
+void SV_GetChallenge(netadr_t from);
void SV_DirectConnect( netadr_t from );
diff --git a/code/server/sv_client.c b/code/server/sv_client.c
index f3d547c..16a67ab 100644
--- a/code/server/sv_client.c
+++ b/code/server/sv_client.c
@@ -41,12 +41,21 @@ to be sent to the authorize server.
When an authorizeip is returned, a challenge response will be
sent to that ip.
+
+ioquake3: we added a possibility for clients to add a challenge
+to their packets, to make it more difficult for malicious servers
+to hi-jack client connections.
+Also, the auth stuff is completely disabled for com_standalone games
+as well as IPv6 connections, since there is no way to use the
+v4-only auth server for these new types of connections.
=================
*/
-void SV_GetChallenge( netadr_t from ) {
+void SV_GetChallenge(netadr_t from)
+{
int i;
int oldest;
int oldestTime;
+ const char *clientChallenge = Cmd_Argv(1);
challenge_t *challenge;
// ignore if we are in single player
@@ -69,62 +78,57 @@ void SV_GetChallenge( netadr_t from ) {
}
}
- if (i == MAX_CHALLENGES) {
+ if (i == MAX_CHALLENGES)
+ {
// this is the first time this client has asked for a challenge
challenge = &svs.challenges[oldest];
challenge->challenge = ( (rand() << 16) ^ rand() ) ^ svs.time;
+ challenge->clientChallenge = 0;
challenge->adr = from;
challenge->firstTime = svs.time;
challenge->time = svs.time;
challenge->connected = qfalse;
- i = oldest;
- }
-
-#ifdef STANDALONE
- challenge->pingTime = svs.time;
- NET_OutOfBandPrint( NS_SERVER, from, "challengeResponse %i", challenge->challenge );
-#else
- // if they are on a lan address, send the challengeResponse immediately
- if ( Sys_IsLANAddress( from ) ) {
- challenge->pingTime = svs.time;
- NET_OutOfBandPrint( NS_SERVER, from, "challengeResponse %i", challenge->challenge );
- return;
}
+#ifndef STANDALONE
// Drop the authorize stuff if this client is coming in via v6 as the auth server does not support ipv6.
- if(challenge->adr.type == NA_IP)
+ // Drop also for addresses coming in on local LAN and for stand-alone games independent from id's assets.
+ if(challenge->adr.type == NA_IP && !Cvar_VariableIntegerValue("com_standalone") && !Sys_IsLANAddress(from))
{
// look up the authorize server's IP
- if ( !svs.authorizeAddress.ip[0] && svs.authorizeAddress.type != NA_BAD ) {
+ if (svs.authorizeAddress.type == NA_BAD)
+ {
Com_Printf( "Resolving %s\n", AUTHORIZE_SERVER_NAME );
- if ( !NET_StringToAdr( AUTHORIZE_SERVER_NAME, &svs.authorizeAddress, NA_IP ) ) {
- Com_Printf( "Couldn't resolve address\n" );
- return;
+
+ if (NET_StringToAdr(AUTHORIZE_SERVER_NAME, &svs.authorizeAddress, NA_IP))
+ {
+ svs.authorizeAddress.port = BigShort( PORT_AUTHORIZE );
+ Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", AUTHORIZE_SERVER_NAME,
+ svs.authorizeAddress.ip[0], svs.authorizeAddress.ip[1],
+ svs.authorizeAddress.ip[2], svs.authorizeAddress.ip[3],
+ BigShort( svs.authorizeAddress.port ) );
}
- svs.authorizeAddress.port = BigShort( PORT_AUTHORIZE );
- Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", AUTHORIZE_SERVER_NAME,
- svs.authorizeAddress.ip[0], svs.authorizeAddress.ip[1],
- svs.authorizeAddress.ip[2], svs.authorizeAddress.ip[3],
- BigShort( svs.authorizeAddress.port ) );
}
+ // we couldn't contact the auth server, let them in.
+ if(svs.authorizeAddress.type == NA_BAD)
+ Com_Printf("Couldn't resolve auth server address\n");
+
// 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
- if ( svs.time - challenge->firstTime > AUTHORIZE_TIMEOUT ) {
+ else if(svs.time - challenge->firstTime > AUTHORIZE_TIMEOUT)
Com_DPrintf( "authorize server timed out\n" );
-
- challenge->pingTime = svs.time;
- NET_OutOfBandPrint( NS_SERVER, challenge->adr,
- "challengeResponse %i", challenge->challenge );
- return;
- }
-
- // otherwise send their ip to the authorize server
- if ( svs.authorizeAddress.type != NA_BAD ) {
+ else
+ {
+ // otherwise send their ip to the authorize server
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);
@@ -132,22 +136,20 @@ void SV_GetChallenge( netadr_t from ) {
if (fs && fs->string[0] != 0) {
strcpy(game, fs->string);
}
-
+
// the 0 is for backwards compatibility with obsolete sv_allowanonymous flags
// getIpAuthorize <challenge> <IP> <game> 0 <auth-flag>
NET_OutOfBandPrint( NS_SERVER, svs.authorizeAddress,
- "getIpAuthorize %i %i.%i.%i.%i %s 0 %s", svs.challenges[i].challenge,
+ "getIpAuthorize %i %i.%i.%i.%i %s 0 %s", challenge->challenge,
from.ip[0], from.ip[1], from.ip[2], from.ip[3], game, sv_strictAuth->string );
+
+ return;
}
}
- else
- {
- challenge->pingTime = svs.time;
-
- NET_OutOfBandPrint( NS_SERVER, challenge->adr,
- "challengeResponse %i", challenge->challenge );
- }
#endif
+
+ challenge->pingTime = svs.time;
+ NET_OutOfBandPrint( NS_SERVER, challenge->adr, "challengeResponse %i %s", challenge->challenge, clientChallenge);
}
#ifndef STANDALONE
@@ -165,6 +167,7 @@ void SV_AuthorizeIpPacket( netadr_t from ) {
int i;
char *s;
char *r;
+ challenge_t *challengeptr;
if ( !NET_CompareBaseAdr( from, svs.authorizeAddress ) ) {
Com_Printf( "SV_AuthorizeIpPacket: not from authorize server\n" );
@@ -182,44 +185,46 @@ void SV_AuthorizeIpPacket( netadr_t from ) {
Com_Printf( "SV_AuthorizeIpPacket: challenge not found\n" );
return;
}
+
+ challengeptr = &svs.challenges[i];
// send a packet back to the original client
- svs.challenges[i].pingTime = svs.time;
+ challengeptr->pingTime = svs.time;
s = Cmd_Argv( 2 );
r = Cmd_Argv( 3 ); // reason
if ( !Q_stricmp( s, "demo" ) ) {
// they are a demo client trying to connect to a real server
- NET_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, "print\nServer is not a demo server\n" );
+ NET_OutOfBandPrint( NS_SERVER, challengeptr->adr, "print\nServer is not a demo server\n" );
// clear the challenge record so it won't timeout and let them through
- Com_Memset( &svs.challenges[i], 0, sizeof( svs.challenges[i] ) );
+ Com_Memset( challengeptr, 0, sizeof( *challengeptr ) );
return;
}
if ( !Q_stricmp( s, "accept" ) ) {
- NET_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr,
- "challengeResponse %i", svs.challenges[i].challenge );
+ NET_OutOfBandPrint(NS_SERVER, challengeptr->adr,
+ "challengeResponse %d %d", challengeptr->challenge, challengeptr->clientChallenge);
return;
}
if ( !Q_stricmp( s, "unknown" ) ) {
if (!r) {
- NET_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, "print\nAwaiting CD key authorization\n" );
+ NET_OutOfBandPrint( NS_SERVER, challengeptr->adr, "print\nAwaiting CD key authorization\n" );
} else {
- NET_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, "print\n%s\n", r);
+ NET_OutOfBandPrint( NS_SERVER, challengeptr->adr, "print\n%s\n", r);
}
// clear the challenge record so it won't timeout and let them through
- Com_Memset( &svs.challenges[i], 0, sizeof( svs.challenges[i] ) );
+ Com_Memset( challengeptr, 0, sizeof( *challengeptr ) );
return;
}
// authorization failed
if (!r) {
- NET_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, "print\nSomeone is using this CD Key\n" );
+ NET_OutOfBandPrint( NS_SERVER, challengeptr->adr, "print\nSomeone is using this CD Key\n" );
} else {
- NET_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, "print\n%s\n", r );
+ NET_OutOfBandPrint( NS_SERVER, challengeptr->adr, "print\n%s\n", r );
}
// clear the challenge record so it won't timeout and let them through
- Com_Memset( &svs.challenges[i], 0, sizeof( svs.challenges[i] ) );
+ Com_Memset( challengeptr, 0, sizeof(*challengeptr) );
}
#endif
@@ -535,9 +540,11 @@ void SV_DropClient( client_t *drop, const char *reason ) {
// see if we already have a challenge for this ip
challenge = &svs.challenges[0];
- for (i = 0 ; i < MAX_CHALLENGES ; i++, challenge++) {
- if ( NET_CompareAdr( drop->netchan.remoteAddress, challenge->adr ) ) {
- challenge->connected = qfalse;
+ for (i = 0 ; i < MAX_CHALLENGES ; i++, challenge++)
+ {
+ if(NET_CompareAdr(drop->netchan.remoteAddress, challenge->adr))
+ {
+ Com_Memset(challenge, 0, sizeof(*challenge));
break;
}
}
diff --git a/code/server/sv_main.c b/code/server/sv_main.c
index bce9c3d..23dc50f 100644
--- a/code/server/sv_main.c
+++ b/code/server/sv_main.c
@@ -548,7 +548,7 @@ static void SV_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
} else if (!Q_stricmp(c, "getinfo")) {
SVC_Info( from );
} else if (!Q_stricmp(c, "getchallenge")) {
- SV_GetChallenge( from );
+ SV_GetChallenge(from);
} else if (!Q_stricmp(c, "connect")) {
SV_DirectConnect( from );
#ifndef STANDALONE