diff options
Diffstat (limited to 'code')
-rw-r--r-- | code/client/cl_main.c | 68 |
1 files changed, 46 insertions, 22 deletions
diff --git a/code/client/cl_main.c b/code/client/cl_main.c index 814e7ab..b4d3d9b 100644 --- a/code/client/cl_main.c +++ b/code/client/cl_main.c @@ -1561,10 +1561,14 @@ void CL_Connect_f( void ) { // if we aren't playing on a lan, we need to authenticate // with the cd key - if ( NET_IsLocalAddress( clc.serverAddress ) ) { + if(NET_IsLocalAddress(clc.serverAddress)) cls.state = CA_CHALLENGING; - } else { + else + { cls.state = CA_CONNECTING; + + // Set a client challenge number that ideally is mirrored back by the server. + clc.challenge = ((rand() << 16) ^ rand()) ^ Com_Milliseconds(); } Key_SetCatcher( 0 ); @@ -2078,7 +2082,11 @@ void CL_CheckForResend( void ) { if (!Cvar_VariableIntegerValue("com_standalone") && clc.serverAddress.type == NA_IP && !Sys_IsLANAddress( clc.serverAddress ) ) CL_RequestAuthorization(); #endif - NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "getchallenge"); + + // 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); + + NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, data); break; case CA_CHALLENGING: @@ -2328,21 +2336,39 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { Com_DPrintf ("CL packet %s: %s\n", NET_AdrToStringwPort(from), c); // challenge from the server we are connecting to - if ( !Q_stricmp(c, "challengeResponse") ) { - if ( cls.state != CA_CONNECTING ) { - Com_DPrintf( "Unwanted challenge response received. Ignored.\n" ); - } else { - // start sending challenge repsonse instead of challenge request packets - clc.challenge = atoi(Cmd_Argv(1)); - cls.state = CA_CHALLENGING; - clc.connectPacketCount = 0; - clc.connectTime = -99999; - - // take this address as the new server address. This allows - // a server proxy to hand off connections to multiple servers - clc.serverAddress = from; - Com_DPrintf ("challengeResponse: %d\n", clc.challenge); + if (!Q_stricmp(c, "challengeResponse")) + { + if (cls.state != CA_CONNECTING) + { + Com_DPrintf("Unwanted challenge response received. Ignored.\n"); + return; } + + 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. + + c = Cmd_Argv(2); + + if(!*c || atoi(c) != clc.challenge) + { + Com_DPrintf("Challenge response received from unexpected source. Ignored.\n"); + return; + } + } + + // start sending challenge response instead of challenge request packets + clc.challenge = atoi(Cmd_Argv(1)); + cls.state = CA_CHALLENGING; + clc.connectPacketCount = 0; + clc.connectTime = -99999; + + // take this address as the new server address. This allows + // a server proxy to hand off connections to multiple servers + clc.serverAddress = from; + Com_DPrintf ("challengeResponse: %d\n", clc.challenge); return; } @@ -2353,13 +2379,11 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { return; } if ( cls.state != CA_CHALLENGING ) { - Com_Printf ("connectResponse packet while not connecting. Ignored.\n"); + Com_Printf ("connectResponse packet while not connecting. Ignored.\n"); return; } - if ( !NET_CompareBaseAdr( from, clc.serverAddress ) ) { - Com_Printf( "connectResponse from a different address. Ignored.\n" ); - Com_Printf( "%s should have been %s\n", NET_AdrToStringwPort( from ), - NET_AdrToStringwPort( clc.serverAddress ) ); + if ( !NET_CompareAdr( from, clc.serverAddress ) ) { + Com_Printf( "connectResponse from wrong address. Ignored.\n" ); return; } Netchan_Setup (NS_CLIENT, &clc.netchan, from, Cvar_VariableValue( "net_qport" ) ); |