foxygit / doom Log in
commit 2d45e6c02cfe002ff4c5a3aa6a360f918ee54e61
Author:     Simon Howard <fraggle@gmail.com>
AuthorDate: Thu Apr 6 17:53:43 2006 +0000
Commit:     Simon Howard <fraggle@gmail.com>
CommitDate: Thu Apr 6 17:53:43 2006 +0000

    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
---
 src/net_client.c |  4 ++--
 src/net_common.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/net_common.h |  6 ++++-
 src/net_server.c | 71 ++++++++++++++++++++++++++++++++++++++++++--------------
 4 files changed, 129 insertions(+), 21 deletions(-)

diff --git a/src/net_client.c b/src/net_client.c
index 097b2f44..95a3f81b 100644
--- 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 @@ static void NET_CL_SendSYN(void)
     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);
 }
diff --git a/src/net_common.c b/src/net_common.c
index 35bc67e1..ba8d24bf 100644
--- 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 @@ void NET_SafePuts(char *s)
     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;
+}

diff --git a/src/net_common.h b/src/net_common.h
index 973a66e6..d645b002 100644
--- 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
 //
@@ -135,5 +135,9 @@ net_packet_t *NET_Conn_NewReliable(net_connection_t *conn, int packet_type);
 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 */

diff --git a/src/net_server.c b/src/net_server.c
index 8ecc4aa0..3a01f3b9 100644
--- 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 @@ static void NET_SV_ParseSYN(net_packet_t *packet,
         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,18 +568,16 @@ static void NET_SV_ParseSYN(net_packet_t *packet,
         return;
     }

-    // read the player's name
-
-    player_name = NET_ReadString(packet);
-
-    if (player_name == NULL)
+    if (!NET_ValidGameMode(cl_gamemode, cl_gamemission))
     {
         return;
     }

-    client_version = NET_ReadString(packet);
+    // read the player's name

-    if (client_version == NULL)
+    player_name = NET_ReadString(packet);
+
+    if (player_name == NULL)
     {
         return;
     }
@@ -576,6 +589,7 @@ static void NET_SV_ParseSYN(net_packet_t *packet,
     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 @@ static void NET_SV_ParseSYN(net_packet_t *packet,
             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 @@ static void NET_SV_ParseGameStart(net_packet_t *packet, net_client_t *client)
         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_SendTics(net_client_t *client, int start, int end)

 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 @@ static void NET_SV_ParseResendRequest(net_packet_t *packet, net_client_t *client

     //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);
 }