summaryrefslogtreecommitdiffstats
path: root/package/libvncserver/libvncserver-0004-CVE-2014-6055.patch
blob: 2a6ee76ae34c5f2e194da4967aad2e94c4296ee4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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;
 }
 
 /*
OpenPOWER on IntegriCloud