Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
* upstream/master:
  Bump up mod version
  Ignore key bindings when downloading a map and when waiting for gamestate from the server. Original patch by @mickael9 mickael9/ioq3@77e7012
  Potential exploit fix: do not allow the client to modify the flag of a ROM or INIT cvar
  Potential exploit fix: do not allow loading .menu files from the /download/ subfolder
  Removed the binaries from the repository. We'll include them in the GitHub releases now.
  Updated the engine version
  Fix CVE-2017-6903 (FrozenSand#73)
  Server browser: when quickly refreshing the servers list multiple times, make sure that we're not displaying the same server several times. Patch by Tequila
  Exploit fix: on the client, check that a challengeResponse packet comes from the expected server address. This prevents a malicious server from hijacking a client's connection to a legit server.
  • Loading branch information
anthonynguyen committed Mar 19, 2018
2 parents 371e833 + 296274f commit d589186
Show file tree
Hide file tree
Showing 17 changed files with 254 additions and 76 deletions.
50 changes: 37 additions & 13 deletions code/client/cl_console.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,16 +323,33 @@ void Con_Dump (console_t *console) {
int l, x, i;
short *line;
fileHandle_t f;
char buffer[1024];
int bufferlen;
char *buffer;
char filename[MAX_QPATH];

f = FS_FOpenFileWrite( Cmd_Argv( 1 ) );
if (Cmd_Argc() != 2)
{
Com_Printf ("usage: condump <filename>\n");
return;
}

Q_strncpyz( filename, Cmd_Argv( 1 ), sizeof( filename ) );
COM_DefaultExtension( filename, sizeof( filename ), ".txt" );

if (!COM_CompareExtension(filename, ".txt"))
{
Com_Printf("Con_Dump_f: Only the \".txt\" extension is supported by this command!\n");
return;
}

f = FS_FOpenFileWrite( filename );
if (!f)
{
Com_Printf ("ERROR: couldn't open %s.\n", Cmd_Argv(1));
Com_Printf ("ERROR: couldn't open %s.\n", filename);
return;
}

Com_Printf ("Dumped console text to %s.\n", Cmd_Argv(1) );
Com_Printf ("Dumped console text to %s.\n", filename );

// skip empty lines
for (l = console->current - console->totallines + 1 ; l <= console->current ; l++)
Expand All @@ -345,9 +362,17 @@ void Con_Dump (console_t *console) {
break;
}

#ifdef _WIN32
bufferlen = consoles[CONSOLE_ALL].linewidth + 3 * sizeof ( char );
#else
bufferlen = consoles[CONSOLE_ALL].linewidth + 2 * sizeof ( char );
#endif

buffer = Hunk_AllocateTempMemory( bufferlen );

// write the remaining lines
buffer[console->linewidth] = 0;
for ( ; l <= console->current ; l++)
buffer[bufferlen-1] = 0;
for ( ; l <= consoles[CONSOLE_ALL].current ; l++)
{
line = console->text + (l%console->totallines)*console->linewidth;
for(i=0; i<console->linewidth; i++)
Expand All @@ -359,16 +384,15 @@ void Con_Dump (console_t *console) {
else
break;
}

#ifdef _WIN32
strcat(buffer, "\r\n");
#else
strcat(buffer, "\n");
#endif

#ifdef _WIN32
Q_strcat(buffer, bufferlen, "\r\n");
#else
Q_strcat(buffer, bufferlen, "\n");
#endif
FS_Write(buffer, strlen(buffer), f);
}

Hunk_FreeTempMemory( buffer );
FS_FCloseFile( f );
}

Expand Down
10 changes: 8 additions & 2 deletions code/client/cl_curl.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,14 @@ qboolean CL_cURL_Init()
if(cURLLib)
return qtrue;


Com_Printf("Loading \"%s\"...", cl_cURLLib->string);

if ( COM_CompareExtension( cl_cURLLib->string, ".pk3" ) )
{
Com_Printf( S_COLOR_RED "Rejecting cl_cURLLib named \"%s\"\n", cl_cURLLib->string );
return qfalse;
}

if( (cURLLib = OBJLOAD(cl_cURLLib->string)) == 0 )
{
#ifdef _WIN32
Expand Down Expand Up @@ -344,7 +350,7 @@ void CL_cURL_PerformDownload(void)
}
FS_FCloseFile(clc.download);
if(msg->msg == CURLMSG_DONE && msg->data.result == CURLE_OK) {
FS_SV_Rename(clc.downloadTempName, clc.downloadName);
FS_SV_Rename(clc.downloadTempName, clc.downloadName, qfalse);
clc.downloadRestart = qtrue;
}
else {
Expand Down
2 changes: 1 addition & 1 deletion code/client/cl_keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -1511,7 +1511,7 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
}
} else if ( cls.keyCatchers & KEYCATCH_MESSAGE ) {
Message_Key( key );
} else if ( cls.state == CA_DISCONNECTED ) {
} else if ( cls.state == CA_DISCONNECTED || cls.state == CA_CONNECTED || *clc.downloadName) {
Console_Key( key );
} else {
int i;
Expand Down
50 changes: 30 additions & 20 deletions code/client/cl_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2108,13 +2108,8 @@ void CL_MotdPacket( netadr_t from ) {
CL_InitServerInfo
===================
*/
void CL_InitServerInfo( serverInfo_t *server, serverAddress_t *address ) {
server->adr.type = NA_IP;
server->adr.ip[0] = address->ip[0];
server->adr.ip[1] = address->ip[1];
server->adr.ip[2] = address->ip[2];
server->adr.ip[3] = address->ip[3];
server->adr.port = address->port;
void CL_InitServerInfo( serverInfo_t *server, netadr_t *address ) {
server->adr = *address;
server->clients = 0;
server->hostName[0] = '\0';
server->mapName[0] = '\0';
Expand All @@ -2138,11 +2133,11 @@ CL_ServersResponsePacket
===================
*/
void CL_ServersResponsePacket( netadr_t from, msg_t *msg ) {
int i, count, max, total;
serverAddress_t addresses[MAX_SERVERSPERPACKET];
int numservers;
byte* buffptr;
byte* buffend;
int i, j, count, max, total;
netadr_t addresses[MAX_SERVERSPERPACKET];
int numservers;
byte* buffptr;
byte* buffend;

Com_Printf("CL_ServersResponsePacket\n");

Expand Down Expand Up @@ -2183,6 +2178,8 @@ void CL_ServersResponsePacket( netadr_t from, msg_t *msg ) {
addresses[numservers].port += *buffptr++;
addresses[numservers].port = BigShort( addresses[numservers].port );

addresses[numservers].type = NA_IP;

// syntax check
if (*buffptr != '\\') {
break;
Expand Down Expand Up @@ -2218,6 +2215,18 @@ void CL_ServersResponsePacket( netadr_t from, msg_t *msg ) {
// build net address
serverInfo_t *server = (cls.masterNum == 0) ? &cls.globalServers[count] : &cls.mplayerServers[count];

// Tequila: It's possible to have sent many master server requests. Then
// we may receive many times the same addresses from the master server.
// We just avoid to add a server if it is still in the global servers list.
for (j = 0; j < count; j++)
{
if (NET_CompareAdr(cls.globalServers[j].adr, addresses[i]))
break;
}

if (j < count)
continue;

CL_InitServerInfo( server, &addresses[i] );
// advance to next slot
count++;
Expand All @@ -2228,14 +2237,8 @@ void CL_ServersResponsePacket( netadr_t from, msg_t *msg ) {
if ( cls.numGlobalServerAddresses < MAX_GLOBAL_SERVERS ) {
// if we couldn't store the servers in the main list anymore
for (; i < numservers && count >= max; i++) {
serverAddress_t *addr;
// just store the addresses in an additional list
addr = &cls.globalServerAddresses[cls.numGlobalServerAddresses++];
addr->ip[0] = addresses[i].ip[0];
addr->ip[1] = addresses[i].ip[1];
addr->ip[2] = addresses[i].ip[2];
addr->ip[3] = addresses[i].ip[3];
addr->port = addresses[i].port;
cls.globalServerAddresses[cls.numGlobalServerAddresses++] = addresses[i];
}
}
}
Expand Down Expand Up @@ -2278,6 +2281,14 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
if ( cls.state != CA_CONNECTING ) {
Com_Printf( "Unwanted challenge response received. Ignored.\n" );
} else {

if(!NET_CompareAdr(from, clc.serverAddress))
{
// This challenge response is not coming from the expected address.
Com_DPrintf("Challenge response received from unexpected source. Ignored.\n");
return;
}

// start sending challenge repsonse instead of challenge request packets
clc.challenge = atoi(Cmd_Argv(1));
cls.state = CA_CHALLENGING;
Expand Down Expand Up @@ -4240,4 +4251,3 @@ void CL_Maplist_f(void) {

Com_Printf("-----------------------\nEnd of current maplist\n");
}

24 changes: 12 additions & 12 deletions code/client/cl_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -709,21 +709,21 @@ void CL_ParseGamestate( msg_t *msg ) {
// reinitialize the filesystem if the game directory has changed
FS_ConditionalRestart( clc.checksumFeed );

if (foreignQVMsFound) {
char QVMList[MAX_STRING_CHARS];
for (i = 0; i < foreignQVMsFound; i++) {
strcat(QVMList, va("%s.pk3, ", foreignQVMNames[i]));
if (dangerousPaksFound) {
char PakList[MAX_STRING_CHARS];
for (i = 0; i < dangerousPaksFound; i++) {
Q_strcat(PakList, sizeof(PakList), va("%s.pk3, ", dangerousPakNames[i]));
}

QVMList[strlen(QVMList) - 2] = 0;
PakList[strlen(PakList) - 2] = 0;

Cvar_Set("com_errorMessage", va(
"^1WARNING! ^7QVM found in downloaded pk3%s\n\n%s\n\n"
"You should go delete %s immediately. %s could contain malicious code.",
foreignQVMsFound == 1 ? ":" : "s:",
QVMList,
foreignQVMsFound == 1 ? "that file" : "those files",
foreignQVMsFound == 1 ? "It" : "They"));
"^1WARNING! ^7Dangerous file(s) found in downloaded pk3%s:\n\n%s\n\n"
"You should go delete %s immediately. %s could lead to malicious code execution.",
dangerousPaksFound == 1 ? "" : "s",
PakList,
dangerousPaksFound == 1 ? "that file" : "those files",
dangerousPaksFound == 1 ? "It" : "They"));

VM_Call(uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN);
return;
Expand Down Expand Up @@ -820,7 +820,7 @@ void CL_ParseDownload ( msg_t *msg ) {
clc.download = 0;

// rename the file
FS_SV_Rename ( clc.downloadTempName, clc.downloadName );
FS_SV_Rename ( clc.downloadTempName, clc.downloadName, qfalse );
}
*clc.downloadTempName = *clc.downloadName = 0;
Cvar_Set( "cl_downloadName", "" );
Expand Down
7 changes: 1 addition & 6 deletions code/client/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,11 +274,6 @@ typedef struct {
char modversion[MAX_NAME_LENGTH]; //@Barbatos - g_modversion
} serverInfo_t;

typedef struct {
byte ip[4];
unsigned short port;
} serverAddress_t;

typedef struct {
connstate_t state; // connection status
int keyCatchers; // bit flags
Expand Down Expand Up @@ -307,7 +302,7 @@ typedef struct {
serverInfo_t globalServers[MAX_GLOBAL_SERVERS];
// additional global servers
int numGlobalServerAddresses;
serverAddress_t globalServerAddresses[MAX_GLOBAL_SERVERS];
netadr_t globalServerAddresses[MAX_GLOBAL_SERVERS];

int numfavoriteservers;
serverInfo_t favoriteServers[MAX_OTHER_SERVERS];
Expand Down
7 changes: 7 additions & 0 deletions code/client/snd_openal.c
Original file line number Diff line number Diff line change
Expand Up @@ -1878,6 +1878,13 @@ qboolean S_AL_Init( soundInterface_t *si )

s_alDriver = Cvar_Get( "s_alDriver", ALDRIVER_DEFAULT, CVAR_ARCHIVE );


if ( COM_CompareExtension( s_alDriver->string, ".pk3" ) )
{
Com_Printf( S_COLOR_RED "Rejecting s_alDriver named \"%s\"\n", s_alDriver->string );
return qfalse;
}

// Load QAL
if( !QAL_Init( s_alDriver->string ) )
{
Expand Down
7 changes: 7 additions & 0 deletions code/qcommon/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -2650,6 +2650,13 @@ void Com_WriteConfig_f( void ) {

Q_strncpyz( filename, Cmd_Argv(1), sizeof( filename ) );
COM_DefaultExtension( filename, sizeof( filename ), ".cfg" );

if (!COM_CompareExtension(filename, ".cfg"))
{
Com_Printf("Com_WriteConfig_f: Only the \".cfg\" extension is supported by this command!\n");
return;
}

Com_Printf( "Writing %s.\n", filename );
Com_WriteConfigToFile( filename );
}
Expand Down
15 changes: 15 additions & 0 deletions code/qcommon/cvar.c
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,11 @@ void Cvar_SetU_f( void ) {
if ( !v ) {
return;
}

if (v->flags & CVAR_ROM || v->flags & CVAR_INIT) {
return;
}

v->flags |= CVAR_USERINFO;
}

Expand All @@ -630,6 +635,11 @@ void Cvar_SetS_f( void ) {
if ( !v ) {
return;
}

if (v->flags & CVAR_ROM || v->flags & CVAR_INIT) {
return;
}

v->flags |= CVAR_SERVERINFO;
}

Expand All @@ -652,6 +662,11 @@ void Cvar_SetA_f( void ) {
if ( !v ) {
return;
}

if (v->flags & CVAR_ROM || v->flags & CVAR_INIT) {
return;
}

v->flags |= CVAR_ARCHIVE;
}

Expand Down
Loading

0 comments on commit d589186

Please sign in to comment.