|
@@ -1,150 +0,0 @@
|
|
-Description: fix denial of service and possible code execution via
|
|
|
|
- stack overflows in File Transfer feature
|
|
|
|
-Origin: backport, https://github.com/newsoft/libvncserver/commit/06ccdf016154fde8eccb5355613ba04c59127b2e
|
|
|
|
-Origin: backport, https://github.com/newsoft/libvncserver/commit/f528072216dec01cee7ca35d94e171a3b909e677
|
|
|
|
-Origin: backport, https://github.com/newsoft/libvncserver/commit/256964b884c980038cd8b2f0d180fbb295b1c748
|
|
|
|
-
|
|
|
|
-Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar>
|
|
|
|
-
|
|
|
|
-Index: libvncserver-0.9.9+dfsg/libvncserver/rfbserver.c
|
|
|
|
-===================================================================
|
|
|
|
---- libvncserver-0.9.9+dfsg.orig/libvncserver/rfbserver.c 2014-09-25 11:20:22.972070915 -0400
|
|
|
|
-+++ libvncserver-0.9.9+dfsg/libvncserver/rfbserver.c 2014-09-25 11:20:40.368071381 -0400
|
|
|
|
-@@ -1237,21 +1237,35 @@
|
|
|
|
- #define RFB_FILE_ATTRIBUTE_TEMPORARY 0x100
|
|
|
|
- #define RFB_FILE_ATTRIBUTE_COMPRESSED 0x800
|
|
|
|
-
|
|
|
|
--rfbBool rfbFilenameTranslate2UNIX(rfbClientPtr cl, char *path, char *unixPath)
|
|
|
|
-+rfbBool rfbFilenameTranslate2UNIX(rfbClientPtr cl, /* in */ char *path, /* out */ char *unixPath, size_t unixPathMaxLen )
|
|
|
|
- {
|
|
|
|
- int x;
|
|
|
|
- char *home=NULL;
|
|
|
|
-
|
|
|
|
- FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
|
|
|
|
-
|
|
|
|
-+ /*
|
|
|
|
-+ * Do not use strncpy() - truncating the file name would probably have undesirable side effects
|
|
|
|
-+ * Instead check if destination buffer is big enough
|
|
|
|
-+ */
|
|
|
|
-+
|
|
|
|
-+ if (strlen(path) >= unixPathMaxLen)
|
|
|
|
-+ return FALSE;
|
|
|
|
-+
|
|
|
|
- /* C: */
|
|
|
|
- if (path[0]=='C' && path[1]==':')
|
|
|
|
-+ {
|
|
|
|
- strcpy(unixPath, &path[2]);
|
|
|
|
-+ }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- home = getenv("HOME");
|
|
|
|
- if (home!=NULL)
|
|
|
|
- {
|
|
|
|
-+ /* Re-check buffer size */
|
|
|
|
-+ if ((strlen(path) + strlen(home) + 1) >= unixPathMaxLen)
|
|
|
|
-+ return FALSE;
|
|
|
|
-+
|
|
|
|
- strcpy(unixPath, home);
|
|
|
|
- strcat(unixPath,"/");
|
|
|
|
- strcat(unixPath, path);
|
|
|
|
-@@ -1289,7 +1303,8 @@
|
|
|
|
- FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
|
|
|
|
-
|
|
|
|
- /* Client thinks we are Winblows */
|
|
|
|
-- rfbFilenameTranslate2UNIX(cl, buffer, path);
|
|
|
|
-+ if (!rfbFilenameTranslate2UNIX(cl, buffer, path, sizeof(path)))
|
|
|
|
-+ return FALSE;
|
|
|
|
-
|
|
|
|
- if (DB) rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: \"%s\"->\"%s\"\n",buffer, path);
|
|
|
|
-
|
|
|
|
-@@ -1566,7 +1581,9 @@
|
|
|
|
- /* add some space to the end of the buffer as we will be adding a timespec to it */
|
|
|
|
- if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
|
|
|
|
- /* The client requests a File */
|
|
|
|
-- rfbFilenameTranslate2UNIX(cl, buffer, filename1);
|
|
|
|
-+ if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1)))
|
|
|
|
-+ goto fail;
|
|
|
|
-+
|
|
|
|
- cl->fileTransfer.fd=open(filename1, O_RDONLY, 0744);
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
-@@ -1660,16 +1677,17 @@
|
|
|
|
- */
|
|
|
|
- if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
|
|
|
|
-
|
|
|
|
-- /* Parse the FileTime */
|
|
|
|
-+ /* Parse the FileTime
|
|
|
|
-+ * TODO: FileTime is actually never used afterwards
|
|
|
|
-+ */
|
|
|
|
- p = strrchr(buffer, ',');
|
|
|
|
- if (p!=NULL) {
|
|
|
|
- *p = '\0';
|
|
|
|
-- strcpy(szFileTime, p+1);
|
|
|
|
-+ strncpy(szFileTime, p+1, sizeof(szFileTime));
|
|
|
|
-+ szFileTime[sizeof(szFileTime)-1] = '\x00'; /* ensure NULL terminating byte is present, even if copy overflowed */
|
|
|
|
- } else
|
|
|
|
- szFileTime[0]=0;
|
|
|
|
-
|
|
|
|
--
|
|
|
|
--
|
|
|
|
- /* Need to read in sizeHtmp */
|
|
|
|
- if ((n = rfbReadExact(cl, (char *)&sizeHtmp, 4)) <= 0) {
|
|
|
|
- if (n != 0)
|
|
|
|
-@@ -1681,7 +1699,8 @@
|
|
|
|
- }
|
|
|
|
- sizeHtmp = Swap32IfLE(sizeHtmp);
|
|
|
|
-
|
|
|
|
-- rfbFilenameTranslate2UNIX(cl, buffer, filename1);
|
|
|
|
-+ if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1)))
|
|
|
|
-+ goto fail;
|
|
|
|
-
|
|
|
|
- /* If the file exists... We can send a rfbFileChecksums back to the client before we send an rfbFileAcceptHeader */
|
|
|
|
- /* TODO: Delta Transfer */
|
|
|
|
-@@ -1810,7 +1829,9 @@
|
|
|
|
- if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
|
|
|
|
- switch (contentParam) {
|
|
|
|
- case rfbCDirCreate: /* Client requests the creation of a directory */
|
|
|
|
-- rfbFilenameTranslate2UNIX(cl, buffer, filename1);
|
|
|
|
-+ if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1)))
|
|
|
|
-+ goto fail;
|
|
|
|
-+
|
|
|
|
- retval = mkdir(filename1, 0755);
|
|
|
|
- if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCDirCreate(\"%s\"->\"%s\") %s\n", buffer, filename1, (retval==-1?"Failed":"Success"));
|
|
|
|
- /*
|
|
|
|
-@@ -1819,7 +1840,9 @@
|
|
|
|
- if (buffer!=NULL) free(buffer);
|
|
|
|
- return retval;
|
|
|
|
- case rfbCFileDelete: /* Client requests the deletion of a file */
|
|
|
|
-- rfbFilenameTranslate2UNIX(cl, buffer, filename1);
|
|
|
|
-+ if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1)))
|
|
|
|
-+ goto fail;
|
|
|
|
-+
|
|
|
|
- if (stat(filename1,&statbuf)==0)
|
|
|
|
- {
|
|
|
|
- if (S_ISDIR(statbuf.st_mode))
|
|
|
|
-@@ -1837,8 +1860,12 @@
|
|
|
|
- {
|
|
|
|
- /* Split into 2 filenames ('*' is a seperator) */
|
|
|
|
- *p = '\0';
|
|
|
|
-- rfbFilenameTranslate2UNIX(cl, buffer, filename1);
|
|
|
|
-- rfbFilenameTranslate2UNIX(cl, p+1, filename2);
|
|
|
|
-+ if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1)))
|
|
|
|
-+ goto fail;
|
|
|
|
-+
|
|
|
|
-+ if (!rfbFilenameTranslate2UNIX(cl, p+1, filename2, sizeof(filename2)))
|
|
|
|
-+ goto fail;
|
|
|
|
-+
|
|
|
|
- retval = rename(filename1,filename2);
|
|
|
|
- if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCFileRename(\"%s\"->\"%s\" -->> \"%s\"->\"%s\") %s\n", buffer, filename1, p+1, filename2, (retval==-1?"Failed":"Success"));
|
|
|
|
- /*
|
|
|
|
-@@ -1858,6 +1885,10 @@
|
|
|
|
- /* NOTE: don't forget to free(buffer) if you return early! */
|
|
|
|
- if (buffer!=NULL) free(buffer);
|
|
|
|
- return TRUE;
|
|
|
|
-+
|
|
|
|
-+fail:
|
|
|
|
-+ if (buffer!=NULL) free(buffer);
|
|
|
|
-+ return FALSE;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /*
|
|
|