Blame SOURCES/LibVNCServer-0.9.10-CVE-2014-6055.patch

e0f39d
commit 06ccdf016154fde8eccb5355613ba04c59127b2e
e0f39d
Author: Nicolas Ruff <nruff@google.com>
e0f39d
Date:   Mon Sep 1 14:36:26 2014 +0200
e0f39d
e0f39d
    Fix multiple stack-based buffer overflows in file transfer feature
e0f39d
e0f39d
diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
e0f39d
index df7d74c..445331a 100644
e0f39d
--- a/libvncserver/rfbserver.c
e0f39d
+++ b/libvncserver/rfbserver.c
e0f39d
@@ -1241,21 +1241,35 @@ typedef struct {
e0f39d
 #define RFB_FILE_ATTRIBUTE_TEMPORARY  0x100
e0f39d
 #define RFB_FILE_ATTRIBUTE_COMPRESSED 0x800
e0f39d
 
e0f39d
-rfbBool rfbFilenameTranslate2UNIX(rfbClientPtr cl, char *path, char *unixPath)
e0f39d
+rfbBool rfbFilenameTranslate2UNIX(rfbClientPtr cl, /* in */ char *path, /* out */ char *unixPath, size_t unixPathMaxLen )
e0f39d
 {
e0f39d
     int x;
e0f39d
     char *home=NULL;
e0f39d
 
e0f39d
     FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
e0f39d
 
e0f39d
+    /*
e0f39d
+     * Do not use strncpy() - truncating the file name would probably have undesirable side effects
e0f39d
+     * Instead check if destination buffer is big enough
e0f39d
+     */
e0f39d
+
e0f39d
+    if (strlen(path) >= unixPathMaxLen)
e0f39d
+      return FALSE;
e0f39d
+
e0f39d
     /* C: */
e0f39d
     if (path[0]=='C' && path[1]==':')
e0f39d
+    {
e0f39d
       strcpy(unixPath, &path[2]);
e0f39d
+    }
e0f39d
     else
e0f39d
     {
e0f39d
       home = getenv("HOME");
e0f39d
       if (home!=NULL)
e0f39d
       {
e0f39d
+        /* Re-check buffer size */
e0f39d
+        if ((strlen(path) + strlen(home) + 1) >= unixPathMaxLen)
e0f39d
+          return FALSE;
e0f39d
+
e0f39d
         strcpy(unixPath, home);
e0f39d
         strcat(unixPath,"/");
e0f39d
         strcat(unixPath, path);
e0f39d
@@ -1293,7 +1307,8 @@ rfbBool rfbSendDirContent(rfbClientPtr cl, int length, char *buffer)
e0f39d
     FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
e0f39d
 
e0f39d
     /* Client thinks we are Winblows */
e0f39d
-    rfbFilenameTranslate2UNIX(cl, buffer, path);
e0f39d
+    if (!rfbFilenameTranslate2UNIX(cl, buffer, path, sizeof(path)))
e0f39d
+      return FALSE;
e0f39d
 
e0f39d
     if (DB) rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: \"%s\"->\"%s\"\n",buffer, path);
e0f39d
 
e0f39d
@@ -1570,7 +1585,11 @@ rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t con
e0f39d
         /* add some space to the end of the buffer as we will be adding a timespec to it */
e0f39d
         if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
e0f39d
         /* The client requests a File */
e0f39d
-        rfbFilenameTranslate2UNIX(cl, buffer, filename1);
e0f39d
+        if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1)))
e0f39d
+        {
e0f39d
+          if (buffer!=NULL) free(buffer);
e0f39d
+          return FALSE;
e0f39d
+        }
e0f39d
         cl->fileTransfer.fd=open(filename1, O_RDONLY, 0744);
e0f39d
 
e0f39d
         /*
e0f39d
@@ -1685,7 +1704,11 @@ rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t con
e0f39d
         }
e0f39d
         sizeHtmp = Swap32IfLE(sizeHtmp);
e0f39d
         
e0f39d
-        rfbFilenameTranslate2UNIX(cl, buffer, filename1);
e0f39d
+        if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1)))
e0f39d
+        {
e0f39d
+          if (buffer!=NULL) free(buffer);
e0f39d
+          return FALSE;
e0f39d
+        }
e0f39d
 
e0f39d
         /* If the file exists... We can send a rfbFileChecksums back to the client before we send an rfbFileAcceptHeader */
e0f39d
         /* TODO: Delta Transfer */
e0f39d
@@ -1814,7 +1837,12 @@ rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t con
e0f39d
         if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
e0f39d
         switch (contentParam) {
e0f39d
         case rfbCDirCreate:  /* Client requests the creation of a directory */
e0f39d
-            rfbFilenameTranslate2UNIX(cl, buffer, filename1);
e0f39d
+            if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1)))
e0f39d
+            {
e0f39d
+              if (buffer!=NULL) free(buffer);
e0f39d
+              return FALSE;
e0f39d
+            }
e0f39d
+
e0f39d
             retval = mkdir(filename1, 0755);
e0f39d
             if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCDirCreate(\"%s\"->\"%s\") %s\n", buffer, filename1, (retval==-1?"Failed":"Success"));
e0f39d
             /*
e0f39d
@@ -1823,7 +1851,12 @@ rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t con
e0f39d
             if (buffer!=NULL) free(buffer);
e0f39d
             return retval;
e0f39d
         case rfbCFileDelete: /* Client requests the deletion of a file */
e0f39d
-            rfbFilenameTranslate2UNIX(cl, buffer, filename1);
e0f39d
+            if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1)))
e0f39d
+            {
e0f39d
+              if (buffer!=NULL) free(buffer);
e0f39d
+              return FALSE;
e0f39d
+            }
e0f39d
+
e0f39d
             if (stat(filename1,&statbuf)==0)
e0f39d
             {
e0f39d
                 if (S_ISDIR(statbuf.st_mode))
e0f39d
@@ -1841,8 +1874,18 @@ rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t con
e0f39d
             {
e0f39d
                 /* Split into 2 filenames ('*' is a seperator) */
e0f39d
                 *p = '\0';
e0f39d
-                rfbFilenameTranslate2UNIX(cl, buffer, filename1);
e0f39d
-                rfbFilenameTranslate2UNIX(cl, p+1,    filename2);
e0f39d
+                if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1)))
e0f39d
+                {
e0f39d
+                  if (buffer!=NULL) free(buffer);
e0f39d
+                  return FALSE;
e0f39d
+                }
e0f39d
+
e0f39d
+                if (!rfbFilenameTranslate2UNIX(cl, p+1,    filename2, sizeof(filename2)))
e0f39d
+                {
e0f39d
+                  if (buffer!=NULL) free(buffer);
e0f39d
+                  return FALSE;
e0f39d
+                }
e0f39d
+
e0f39d
                 retval = rename(filename1,filename2);
e0f39d
                 if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCFileRename(\"%s\"->\"%s\" -->> \"%s\"->\"%s\") %s\n", buffer, filename1, p+1, filename2, (retval==-1?"Failed":"Success"));
e0f39d
                 /*
e0f39d
e0f39d
commit f528072216dec01cee7ca35d94e171a3b909e677
e0f39d
Author: Nicolas Ruff <nruff@google.com>
e0f39d
Date:   Mon Sep 1 14:51:07 2014 +0200
e0f39d
e0f39d
    Fix stack-based buffer overflow in rfbFileTransferOffer message, FileTime processing
e0f39d
e0f39d
diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
e0f39d
index 445331a..23532b0 100644
e0f39d
--- a/libvncserver/rfbserver.c
e0f39d
+++ b/libvncserver/rfbserver.c
e0f39d
@@ -1683,16 +1683,17 @@ rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t con
e0f39d
         */
e0f39d
         if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
e0f39d
 
e0f39d
-        /* Parse the FileTime */
e0f39d
+        /* Parse the FileTime
e0f39d
+         * TODO: FileTime is actually never used afterwards
e0f39d
+         */
e0f39d
         p = strrchr(buffer, ',');
e0f39d
         if (p!=NULL) {
e0f39d
             *p = '\0';
e0f39d
-            strcpy(szFileTime, p+1);
e0f39d
+            strncpy(szFileTime, p+1, sizeof(szFileTime));
e0f39d
+            szFileTime[sizeof(szFileTime)-1] = '\x00'; /* ensure NULL terminating byte is present, even if copy overflowed */
e0f39d
         } else
e0f39d
             szFileTime[0]=0;
e0f39d
 
e0f39d
-
e0f39d
-
e0f39d
         /* Need to read in sizeHtmp */
e0f39d
         if ((n = rfbReadExact(cl, (char *)&sizeHtmp, 4)) <= 0) {
e0f39d
             if (n != 0)