shithub: choc

Download patch

ref: 2d45e6c02cfe002ff4c5a3aa6a360f918ee54e61
parent: 89332f29ae9d780129c2bcc2a831f959eda255ec
author: Simon Howard <[email protected]>
date: Thu Apr 6 13:53:43 EDT 2006

Sanity check data received by the server. Send version string earlier
in SYN packets to allow the fields that follow to be changed later on
if necessary.

Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 461

--- a/src/net_client.c
+++ b/src/net_client.c
@@ -1,7 +1,7 @@
 // Emacs style mode select   -*- C++ -*- 
 //-----------------------------------------------------------------------------
 //
-// $Id: net_client.c 455 2006-03-30 19:08:37Z fraggle $
+// $Id: net_client.c 461 2006-04-06 17:53:43Z fraggle $
 //
 // Copyright(C) 2005 Simon Howard
 //
@@ -1012,11 +1012,11 @@
     packet = NET_NewPacket(10);
     NET_WriteInt16(packet, NET_PACKET_TYPE_SYN);
     NET_WriteInt32(packet, NET_MAGIC_NUMBER);
+    NET_WriteString(packet, PACKAGE_STRING);
     NET_WriteInt16(packet, gamemode);
     NET_WriteInt16(packet, gamemission);
     NET_WriteInt8(packet, lowres_turn);
     NET_WriteString(packet, net_player_name);
-    NET_WriteString(packet, PACKAGE_STRING);
     NET_Conn_SendPacket(&client_connection, packet);
     NET_FreePacket(packet);
 }
--- a/src/net_common.c
+++ b/src/net_common.c
@@ -1,7 +1,7 @@
 // Emacs style mode select   -*- C++ -*- 
 //-----------------------------------------------------------------------------
 //
-// $Id: net_common.c 456 2006-03-30 19:13:20Z fraggle $
+// $Id: net_common.c 461 2006-04-06 17:53:43Z fraggle $
 //
 // Copyright(C) 2005 Simon Howard
 //
@@ -557,4 +557,71 @@
     putchar('\n');
 }
 
+// Check that a gamemode+gamemission received over the network is valid.
+
+boolean NET_ValidGameMode(GameMode_t mode, GameMission_t mission)
+{
+    if (mode == shareware || mode == registered || mode == retail)
+    {
+        return true;
+    }
+    else if (mode == commercial)
+    {
+        return mission == doom2 || mission == pack_tnt || mission == pack_plut;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+// Check that game settings are valid
+
+boolean NET_ValidGameSettings(GameMode_t mode, GameMission_t mission,
+                              net_gamesettings_t *settings)
+{
+    if (settings->ticdup <= 0)
+        return false;
+
+    if (settings->extratics < 0)
+        return false;
+
+    if (settings->deathmatch < 0 || settings->deathmatch > 2)
+        return false;
+
+    if (settings->skill < sk_noitems || settings->skill > sk_nightmare)
+        return false;
+
+    if (settings->gameversion < exe_doom_1_9 || settings->gameversion > exe_final)
+        return false;
+
+    if (mode == shareware || mode == retail || mode == registered)
+    {
+        if (settings->map < 1 || settings->map > 9)
+            return false;
+    }
+    else
+    {
+        if (settings->map < 1 || settings->map > 32)
+            return false;
+    }
+    
+    if (mode == shareware)
+    {
+        if (settings->episode != 1)
+            return false;
+    }
+    else if (mode == registered)
+    {
+        if (settings->episode < 1 || settings->episode > 3)
+            return false;
+    }
+    else if (mode == retail)
+    {
+        if (settings->episode < 1 || settings->episode > 4)
+            return false;
+    }
+    
+    return true;
+}
 
--- a/src/net_common.h
+++ b/src/net_common.h
@@ -1,7 +1,7 @@
 // Emacs style mode select   -*- C++ -*- 
 //-----------------------------------------------------------------------------
 //
-// $Id: net_common.h 412 2006-03-07 18:24:12Z fraggle $
+// $Id: net_common.h 461 2006-04-06 17:53:43Z fraggle $
 //
 // Copyright(C) 2005 Simon Howard
 //
@@ -134,6 +134,10 @@
 
 void NET_SafePuts(char *msg);
 unsigned int NET_ExpandTicNum(unsigned int relative, unsigned int b);
+
+boolean NET_ValidGameMode(GameMode_t mode, GameMission_t mission);
+boolean NET_ValidGameSettings(GameMode_t mode, GameMission_t mission, 
+                              net_gamesettings_t *settings);
 
 #endif /* #ifndef NET_COMMON_H */
 
--- a/src/net_server.c
+++ b/src/net_server.c
@@ -1,7 +1,7 @@
 // Emacs style mode select   -*- C++ -*- 
 //-----------------------------------------------------------------------------
 //
-// $Id: net_server.c 460 2006-04-01 20:16:43Z fraggle $
+// $Id: net_server.c 461 2006-04-06 17:53:43Z fraggle $
 //
 // Copyright(C) 2005 Simon Howard
 //
@@ -544,6 +544,21 @@
         return;
     }
 
+    // Check the client version is the same as the server
+    //
+    client_version = NET_ReadString(packet);
+
+    if (client_version == NULL)
+    {
+        return;
+    }
+
+    if (strcmp(client_version, PACKAGE_STRING) != 0)
+    {
+        NET_SV_SendReject(addr, "Different versions cannot play a network game!");
+        return;
+    }
+
     // read the game mode and mission
 
     if (!NET_ReadInt16(packet, &cl_gamemode) 
@@ -553,6 +568,11 @@
         return;
     }
 
+    if (!NET_ValidGameMode(cl_gamemode, cl_gamemission))
+    {
+        return;
+    }
+
     // read the player's name
 
     player_name = NET_ReadString(packet);
@@ -561,13 +581,6 @@
     {
         return;
     }
-
-    client_version = NET_ReadString(packet);
-
-    if (client_version == NULL)
-    {
-        return;
-    }
     
     // received a valid SYN
 
@@ -576,6 +589,7 @@
     if (server_state != SERVER_WAITING_START)
     {
         NET_SV_SendReject(addr, "Server is not currently accepting connections");
+        return;
     }
     
     // allocate a client slot if there isn't one already
@@ -626,12 +640,6 @@
             return;
         }
 
-        if (strcmp(client_version, PACKAGE_STRING) != 0)
-        {
-            NET_SV_SendReject(addr, "Different versions cannot play a network game!");
-            return;
-        }
-
         // TODO: Add server option to allow rejecting clients which
         // set lowres_turn.  This is potentially desirable as the 
         // presence of such clients affects turning resolution.
@@ -689,6 +697,13 @@
         return;
     }
 
+    // Check the game settings are valid
+
+    if (!NET_ValidGameSettings(sv_gamemode, sv_gamemission, &settings))
+    {
+        return;
+    }
+
     if (server_state != SERVER_WAITING_START)
     {
         // Can only start a game if we are in the waiting start state.
@@ -1003,8 +1018,9 @@
 
 static void NET_SV_ParseResendRequest(net_packet_t *packet, net_client_t *client)
 {
-    static unsigned int start;
-    static unsigned int num_tics;
+    unsigned int start, last;
+    unsigned int num_tics;
+    int i;
 
     // Read the starting tic and number of tics
 
@@ -1016,9 +1032,30 @@
 
     //printf("SV: %p: resend %i-%i\n", client, start, start+num_tics-1);
 
+    // Check we have all the requested tics
+
+    last = start + num_tics - 1;
+
+    for (i=start; i<=last; ++i)
+    {
+        net_full_ticcmd_t *cmd;
+
+        cmd = &client->sendqueue[i % BACKUPTICS];
+
+        if (i != cmd->seq)
+        {
+            // We do not have the requested tic (any more)
+            // This is pretty fatal.  We could disconnect the client, 
+            // but then again this could be a spoofed packet.  Just 
+            // ignore it.
+
+            return;
+        }
+    }
+
     // Resend those tics
 
-    NET_SV_SendTics(client, start, start + num_tics - 1);
+    NET_SV_SendTics(client, start, last);
 }