tags 413296 + patch fixed-upstream
tags 413299 + patch fixed-upstream
thanks

Ah, I see... this has already been reported and fixed upstream.

Attached is the latest upstream commit, fixing both reported security
holes (and some more?).

svn -r691:693 diff svn://radscan.com/conquest/trunk > 691-693.diff

-- 
Regards,
Andreas Henriksson
Index: nWelcome.c
===================================================================
--- nWelcome.c  (revision 691)
+++ nWelcome.c  (revision 693)
@@ -104,12 +104,20 @@
       switch (pkttype)
         {
         case SP_CLIENTSTAT:
-          scstat = (spClientStat_t *)buf;
-          
-          Context.unum = (int)ntohs(scstat->unum);
-          Context.snum = scstat->snum;
-          Ships[Context.snum].team = scstat->team;
-          done = TRUE;
+          if ((scstat = chkClientStat(buf)))
+            {
+              Context.unum = scstat->unum;
+              Context.snum = scstat->snum;
+              Ships[Context.snum].team = scstat->team;
+              done = TRUE;
+            }
+          else
+            {
+              clog("nWelcomeInit: invalid CLIENTSTAT");
+              fatal = TRUE;
+              done = TRUE;
+              return;
+            }
           break;
         case SP_ACK:
           sack = *(spAck_t *)buf;
Index: meta.c
===================================================================
--- meta.c      (revision 691)
+++ meta.c      (revision 693)
@@ -352,12 +352,14 @@
 /* contact a meta server, and return a pointer to a static array of
    metaSRec_t's coresponding to the server list.  returns number
    of servers found, or ERR if error */
+#define SERVER_BUFSIZE 1024
+
 int metaGetServerList(char *remotehost, metaSRec_t **srvlist)
 {
   static metaSRec_t servers[META_MAXSERVERS];
   struct sockaddr_in sa;
   struct hostent *hp;
-  char buf[1024];               /* server buffer */
+  char buf[SERVER_BUFSIZE];               /* server buffer */
   int off;
   int firsttime = TRUE;
   int s;                        /* socket */
@@ -405,7 +407,7 @@
   off = 0;
   while (read(s, &c, 1) > 0)
     {
-      if (c != '\n')
+      if (c != '\n' && off < (SERVER_BUFSIZE - 1))
         {
           buf[off++] = c;
         }
@@ -414,11 +416,19 @@
           buf[off] = 0;
 
           /* convert to a metaSRec_t */
-          if (str2srec(&servers[nums], buf))
-            nums++;
+          if (nums < META_MAXSERVERS)
+            {
+              if (str2srec(&servers[nums], buf))
+                nums++;
+              else
+                clog("metaGetServerList: str2srec(%s) failed, skipping", buf);
+            }
           else
-            clog("metaGetServerList: str2srec(%s) failed, skipping", buf);
-          
+            {
+              clog("metaGetServerList: num servers exceeds %d, skipping", 
+                   META_MAXSERVERS);
+            }
+            
           off = 0;
         }
     }
Index: nPlay.c
===================================================================
--- nPlay.c     (revision 691)
+++ nPlay.c     (revision 693)
@@ -124,13 +124,25 @@
          break;
          
        case SP_CLIENTSTAT:
-         scstat = *(spClientStat_t *)buf; /* make a copy... */
-         /* first things first */
-         Context.unum = (int)ntohs(scstat.unum);
-         Context.snum = scstat.snum;
-         Ships[Context.snum].team = scstat.team;
-         
-          return TRUE;
+          {
+            spClientStat_t *scstatp;
+
+            if ((scstatp = chkClientStat(buf)))
+              {
+                scstat = *scstatp; /* make a copy */
+                /* first things first */
+                Context.unum = scstat.unum;
+                Context.snum = scstat.snum;
+                Ships[Context.snum].team = scstat.team;
+                
+                return TRUE;
+              }
+            else
+              {
+                clog("nPlay: _newship: invalid CLIENTSTAT");
+                return FALSE;
+              }
+          }
          break;
          
          /* we might get other packets too */
Index: client.c
===================================================================
--- client.c    (revision 691)
+++ client.c    (revision 693)
@@ -984,11 +984,13 @@
       break;
 
     case SP_CLIENTSTAT:
-      scstat = (spClientStat_t *)buf;
-      Context.snum = scstat->snum;
-      Context.unum = (int)ntohs(scstat->unum);
-      Ships[Context.snum].team = scstat->team;
-      clientFlags = scstat->flags;
+      if ((scstat = chkClientStat(buf)))
+        {
+          Context.snum = scstat->snum;
+          Context.unum = scstat->unum;
+          Ships[Context.snum].team = scstat->team;
+          clientFlags = scstat->flags;
+        }
       break;
 
     case SP_MESSAGE:
@@ -1066,3 +1068,45 @@
 
   return;
 }
+
+/* this function accepts a character buffer representing a clientstat packet
+   and validates it.  It return a pointer to a static spClientStat_t
+   packet if everything is in order, NULL otherwise. */
+spClientStat_t *chkClientStat(char *buf)
+{
+  static spClientStat_t scstat;
+
+  if (!buf)
+    return NULL;
+
+  scstat = *(spClientStat_t *)buf;
+  
+  scstat.unum = (Unsgn16)ntohs(scstat.unum);
+
+  if (scstat.unum >= MAXUSERS)
+    {
+#if defined(DEBUG_PKT)
+      clog("%s: unum not in valid range", __FUNCTION__);
+#endif
+      return NULL;
+    }
+
+  if (scstat.snum < 1 || scstat.snum > MAXSHIPS)
+    {
+#if defined(DEBUG_PKT)
+      clog("%s: snum not in valid range", __FUNCTION__);
+#endif
+      return NULL;
+    }
+
+  if (scstat.team >= NUMALLTEAMS)
+    {
+#if defined(DEBUG_PKT)
+      clog("%s: team not in valid range", __FUNCTION__);
+#endif
+      return NULL;
+    }
+
+  return &scstat;
+}
+  
Index: HISTORY
===================================================================
--- HISTORY     (revision 691)
+++ HISTORY     (revision 693)
@@ -9,6 +9,14 @@
 
                               Conquest HISTORY
 
+???
+
+3/3/2006
+
+       - fixed some security (possble buffer overruns) in the client
+         (meta.c and CLIENTSTAT processing) reported by Luigi Auriemma.
+
+
 8.2a (devel) 11/27/2006
 
        - Added sound support using SDL and the SDL_mixer API based on
Index: client.h
===================================================================
--- client.h    (revision 691)
+++ client.h    (revision 693)
@@ -91,4 +91,6 @@
 
 void sendUDPKeepAlive(Unsgn32 timebase);
 
+spClientStat_t *chkClientStat(char *buf);
+
 #endif /* CLIENT_H_INCLUDED */
Index: conquest.c
===================================================================
--- conquest.c  (revision 691)
+++ conquest.c  (revision 693)
@@ -3132,7 +3132,7 @@
              break;
              
            default:
-             clog("conquest:newship: unexpected ack code %d",
+             clog("newship: unexpected ack code %d",
                   sack->code);
              break;
            }
@@ -3141,22 +3141,28 @@
          break;
          
        case SP_CLIENTSTAT:
-         scstat = (spClientStat_t *)buf;
+          if ((scstat = chkClientStat(buf)))  
+            {
+              /* first things first */
+              Context.unum = scstat->unum;
+              Context.snum = scstat->snum;
+              Ships[Context.snum].team = scstat->team;
+              
+              if (scstat->esystem == 0)        /* we are done */
+                return TRUE;
+              
+              /* otherwise, need to prompt for system to enter */
+              if (selectentry(scstat->esystem))
+                return TRUE;           /* done */
+              else
+                return FALSE;
+            }
+          else
+            {
+              clog("newship: invalid CLIENTSTAT\n");
+              return FALSE;       /* don't want to hang if a bad pkt */
+            }
          
-         /* first things first */
-         Context.unum = (int)ntohs(scstat->unum);
-         Context.snum = scstat->snum;
-         Ships[Context.snum].team = scstat->team;
-         
-         if (scstat->esystem == 0)     /* we are done */
-           return TRUE;
-         
-         /* otherwise, need to prompt for system to enter */
-         if (selectentry(scstat->esystem))
-           return TRUE;                /* done */
-         else
-           return FALSE;
-         
          break;
          
          /* we might get other packets too */
@@ -3322,7 +3328,7 @@
   char * selected_str="You have been selected to command a";
   char * starship_str=" starship.";
   char * prepare_str="Prepare to be beamed aboard...";
-  spClientStat_t scstat = {};
+  spClientStat_t *scstat;
   spAck_t *sack = NULL;
   int pkttype;
   Unsgn8 buf[PKT_MAXSIZE];
@@ -3350,12 +3356,18 @@
       switch (pkttype)
         {
         case SP_CLIENTSTAT:
-          scstat = *(spClientStat_t *)buf;
-          
-          *unum = (int)ntohs(scstat.unum);
-          Context.snum = scstat.snum;
-          Ships[Context.snum].team = scstat.team;
-          done = TRUE;
+          if ((scstat = chkClientStat(buf)))
+            {
+              *unum = scstat->unum;
+              Context.snum = scstat->snum;
+              Ships[Context.snum].team = scstat->team;
+              done = TRUE;
+            }
+          else
+            {
+              clog("welcome: invalid CLIENTSTAT\n");
+              return FALSE;
+            }
 
           break;
         case SP_ACK:
@@ -3370,7 +3382,7 @@
         }
     }
 
-  if ( pkttype == SP_CLIENTSTAT && (scstat.flags & SPCLNTSTAT_FLAG_NEW) )
+  if ( pkttype == SP_CLIENTSTAT && (scstat->flags & SPCLNTSTAT_FLAG_NEW) )
     {                          
       /* Must be a new player. */
       cdclear();
@@ -3385,7 +3397,7 @@
          c_sleep( 2.0 );
          return ( FALSE );
        }
-      team = scstat.team;
+      team = scstat->team;
       cbuf[0] = EOS;
       apptitle( team, cbuf );
       appchr( ' ', cbuf );

Reply via email to