mirror of
https://github.com/UberGames/lilium-voyager.git
synced 2024-12-14 06:01:10 +00:00
Make servers echo challenge codes from client getchallenge commands
This commit is contained in:
parent
eaaaa6f5fc
commit
18cc7c1ed3
4 changed files with 68 additions and 60 deletions
|
@ -132,8 +132,8 @@ NET
|
||||||
#define MAX_RELIABLE_COMMANDS 64 // max string commands buffered for restransmit
|
#define MAX_RELIABLE_COMMANDS 64 // max string commands buffered for restransmit
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
NA_BAD = 0, // an address lookup failed
|
||||||
NA_BOT,
|
NA_BOT,
|
||||||
NA_BAD, // an address lookup failed
|
|
||||||
NA_LOOPBACK,
|
NA_LOOPBACK,
|
||||||
NA_BROADCAST,
|
NA_BROADCAST,
|
||||||
NA_IP,
|
NA_IP,
|
||||||
|
|
|
@ -204,6 +204,7 @@ typedef struct client_s {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
netadr_t adr;
|
netadr_t adr;
|
||||||
int challenge;
|
int challenge;
|
||||||
|
int clientChallenge; // challenge number coming from the client
|
||||||
int time; // time the last packet was sent to the autherize server
|
int time; // time the last packet was sent to the autherize server
|
||||||
int pingTime; // time the challenge response was sent to client
|
int pingTime; // time the challenge response was sent to client
|
||||||
int firstTime; // time the adr was first used, for authorize timeout checks
|
int firstTime; // time the adr was first used, for authorize timeout checks
|
||||||
|
|
|
@ -41,12 +41,21 @@ to be sent to the authorize server.
|
||||||
|
|
||||||
When an authorizeip is returned, a challenge response will be
|
When an authorizeip is returned, a challenge response will be
|
||||||
sent to that ip.
|
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 i;
|
||||||
int oldest;
|
int oldest;
|
||||||
int oldestTime;
|
int oldestTime;
|
||||||
|
const char *clientChallenge = Cmd_Argv(1);
|
||||||
challenge_t *challenge;
|
challenge_t *challenge;
|
||||||
|
|
||||||
// ignore if we are in single player
|
// 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
|
// this is the first time this client has asked for a challenge
|
||||||
challenge = &svs.challenges[oldest];
|
challenge = &svs.challenges[oldest];
|
||||||
challenge->challenge = ( (rand() << 16) ^ rand() ) ^ svs.time;
|
challenge->challenge = ( (rand() << 16) ^ rand() ) ^ svs.time;
|
||||||
|
challenge->clientChallenge = 0;
|
||||||
challenge->adr = from;
|
challenge->adr = from;
|
||||||
challenge->firstTime = svs.time;
|
challenge->firstTime = svs.time;
|
||||||
challenge->time = svs.time;
|
challenge->time = svs.time;
|
||||||
challenge->connected = qfalse;
|
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.
|
// 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
|
// 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 );
|
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" );
|
if (NET_StringToAdr(AUTHORIZE_SERVER_NAME, &svs.authorizeAddress, NA_IP))
|
||||||
return;
|
{
|
||||||
}
|
|
||||||
svs.authorizeAddress.port = BigShort( PORT_AUTHORIZE );
|
svs.authorizeAddress.port = BigShort( PORT_AUTHORIZE );
|
||||||
Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", AUTHORIZE_SERVER_NAME,
|
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[0], svs.authorizeAddress.ip[1],
|
||||||
svs.authorizeAddress.ip[2], svs.authorizeAddress.ip[3],
|
svs.authorizeAddress.ip[2], svs.authorizeAddress.ip[3],
|
||||||
BigShort( svs.authorizeAddress.port ) );
|
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
|
// if they have been challenging for a long time and we
|
||||||
// haven't heard anything from the authorize server, go ahead and
|
// haven't heard anything from the authorize server, go ahead and
|
||||||
// let them in, assuming the id server is down
|
// 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" );
|
Com_DPrintf( "authorize server timed out\n" );
|
||||||
|
else
|
||||||
challenge->pingTime = svs.time;
|
{
|
||||||
NET_OutOfBandPrint( NS_SERVER, challenge->adr,
|
|
||||||
"challengeResponse %i", challenge->challenge );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise send their ip to the authorize server
|
// otherwise send their ip to the authorize server
|
||||||
if ( svs.authorizeAddress.type != NA_BAD ) {
|
|
||||||
cvar_t *fs;
|
cvar_t *fs;
|
||||||
char game[1024];
|
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 ));
|
Com_DPrintf( "sending getIpAuthorize for %s\n", NET_AdrToString( from ));
|
||||||
|
|
||||||
strcpy(game, BASEGAME);
|
strcpy(game, BASEGAME);
|
||||||
|
@ -136,18 +140,16 @@ void SV_GetChallenge( netadr_t from ) {
|
||||||
// the 0 is for backwards compatibility with obsolete sv_allowanonymous flags
|
// the 0 is for backwards compatibility with obsolete sv_allowanonymous flags
|
||||||
// getIpAuthorize <challenge> <IP> <game> 0 <auth-flag>
|
// getIpAuthorize <challenge> <IP> <game> 0 <auth-flag>
|
||||||
NET_OutOfBandPrint( NS_SERVER, svs.authorizeAddress,
|
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 );
|
from.ip[0], from.ip[1], from.ip[2], from.ip[3], game, sv_strictAuth->string );
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
challenge->pingTime = svs.time;
|
|
||||||
|
|
||||||
NET_OutOfBandPrint( NS_SERVER, challenge->adr,
|
return;
|
||||||
"challengeResponse %i", challenge->challenge );
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
challenge->pingTime = svs.time;
|
||||||
|
NET_OutOfBandPrint( NS_SERVER, challenge->adr, "challengeResponse %i %s", challenge->challenge, clientChallenge);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef STANDALONE
|
#ifndef STANDALONE
|
||||||
|
@ -165,6 +167,7 @@ void SV_AuthorizeIpPacket( netadr_t from ) {
|
||||||
int i;
|
int i;
|
||||||
char *s;
|
char *s;
|
||||||
char *r;
|
char *r;
|
||||||
|
challenge_t *challengeptr;
|
||||||
|
|
||||||
if ( !NET_CompareBaseAdr( from, svs.authorizeAddress ) ) {
|
if ( !NET_CompareBaseAdr( from, svs.authorizeAddress ) ) {
|
||||||
Com_Printf( "SV_AuthorizeIpPacket: not from authorize server\n" );
|
Com_Printf( "SV_AuthorizeIpPacket: not from authorize server\n" );
|
||||||
|
@ -183,43 +186,45 @@ void SV_AuthorizeIpPacket( netadr_t from ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
challengeptr = &svs.challenges[i];
|
||||||
|
|
||||||
// send a packet back to the original client
|
// send a packet back to the original client
|
||||||
svs.challenges[i].pingTime = svs.time;
|
challengeptr->pingTime = svs.time;
|
||||||
s = Cmd_Argv( 2 );
|
s = Cmd_Argv( 2 );
|
||||||
r = Cmd_Argv( 3 ); // reason
|
r = Cmd_Argv( 3 ); // reason
|
||||||
|
|
||||||
if ( !Q_stricmp( s, "demo" ) ) {
|
if ( !Q_stricmp( s, "demo" ) ) {
|
||||||
// they are a demo client trying to connect to a real server
|
// 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
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
if ( !Q_stricmp( s, "accept" ) ) {
|
if ( !Q_stricmp( s, "accept" ) ) {
|
||||||
NET_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr,
|
NET_OutOfBandPrint(NS_SERVER, challengeptr->adr,
|
||||||
"challengeResponse %i", svs.challenges[i].challenge );
|
"challengeResponse %d %d", challengeptr->challenge, challengeptr->clientChallenge);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( !Q_stricmp( s, "unknown" ) ) {
|
if ( !Q_stricmp( s, "unknown" ) ) {
|
||||||
if (!r) {
|
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 {
|
} 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
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// authorization failed
|
// authorization failed
|
||||||
if (!r) {
|
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 {
|
} 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
|
// 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
|
#endif
|
||||||
|
|
||||||
|
@ -535,9 +540,11 @@ void SV_DropClient( client_t *drop, const char *reason ) {
|
||||||
// see if we already have a challenge for this ip
|
// see if we already have a challenge for this ip
|
||||||
challenge = &svs.challenges[0];
|
challenge = &svs.challenges[0];
|
||||||
|
|
||||||
for (i = 0 ; i < MAX_CHALLENGES ; i++, challenge++) {
|
for (i = 0 ; i < MAX_CHALLENGES ; i++, challenge++)
|
||||||
if ( NET_CompareAdr( drop->netchan.remoteAddress, challenge->adr ) ) {
|
{
|
||||||
challenge->connected = qfalse;
|
if(NET_CompareAdr(drop->netchan.remoteAddress, challenge->adr))
|
||||||
|
{
|
||||||
|
Com_Memset(challenge, 0, sizeof(*challenge));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue