git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@832 77e5149b-7576-45b1-b177-96237e5ba77b
Nigel Horne authored on 2004/09/06 17:34:47... | ... |
@@ -16,6 +16,9 @@ |
16 | 16 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
17 | 17 |
* |
18 | 18 |
* $Log: blob.c,v $ |
19 |
+ * Revision 1.21 2004/09/06 08:34:47 nigelhorne |
|
20 |
+ * Randomise extracted file names from tar file |
|
21 |
+ * |
|
19 | 22 |
* Revision 1.20 2004/08/30 11:35:45 nigelhorne |
20 | 23 |
* Now compiles on AIX and OSF |
21 | 24 |
* |
... | ... |
@@ -62,7 +65,7 @@ |
62 | 62 |
* Change LOG to Log |
63 | 63 |
* |
64 | 64 |
*/ |
65 |
-static char const rcsid[] = "$Id: blob.c,v 1.20 2004/08/30 11:35:45 nigelhorne Exp $"; |
|
65 |
+static char const rcsid[] = "$Id: blob.c,v 1.21 2004/09/06 08:34:47 nigelhorne Exp $"; |
|
66 | 66 |
|
67 | 67 |
#if HAVE_CONFIG_H |
68 | 68 |
#include "clamav-config.h" |
... | ... |
@@ -165,27 +168,15 @@ blobSetFilename(blob *b, const char *dir, const char *filename) |
165 | 165 |
assert(b->magic == BLOB); |
166 | 166 |
assert(filename != NULL); |
167 | 167 |
|
168 |
+ cli_dbgmsg("blobSetFilename: %s\n", filename); |
|
169 |
+ |
|
168 | 170 |
if(b->name) |
169 | 171 |
free(b->name); |
170 |
- b->name = strdup(filename); |
|
171 | 172 |
|
172 |
- if(b->name) { |
|
173 |
- char *ptr; |
|
174 |
- |
|
175 |
- for(ptr = b->name; *ptr; ptr++) { |
|
176 |
-#ifdef C_DARWIN |
|
177 |
- *ptr &= '\177'; |
|
178 |
-#endif |
|
179 |
-#if defined(MSDOS) || defined(C_CYGWIN) || defined(WIN32) |
|
180 |
- if(strchr("/*?<>|\"+=,;: ", *ptr)) |
|
181 |
-#else |
|
182 |
- if(*ptr == '/') |
|
183 |
-#endif |
|
184 |
- *ptr = '_'; |
|
185 |
- } |
|
186 |
- } |
|
173 |
+ b->name = strdup(filename); |
|
187 | 174 |
|
188 |
- cli_dbgmsg("blobSetFilename: %s\n", filename); |
|
175 |
+ if(b->name) |
|
176 |
+ sanitiseName(b->name); |
|
189 | 177 |
} |
190 | 178 |
|
191 | 179 |
const char * |
... | ... |
@@ -470,3 +461,24 @@ fileblobGetFilename(const fileblob *fb) |
470 | 470 |
{ |
471 | 471 |
return blobGetFilename(&(fb->b)); |
472 | 472 |
} |
473 |
+ |
|
474 |
+/* |
|
475 |
+ * Different operating systems allow different characters in their filenames |
|
476 |
+ */ |
|
477 |
+void |
|
478 |
+sanitiseName(char *name) |
|
479 |
+{ |
|
480 |
+ while(*name) { |
|
481 |
+#ifdef C_DARWIN |
|
482 |
+ *name &= '\177'; |
|
483 |
+#endif |
|
484 |
+#if defined(MSDOS) || defined(C_CYGWIN) || defined(WIN32) |
|
485 |
+ if(strchr("/*?<>|\"+=,;: ", *name)) |
|
486 |
+#else |
|
487 |
+ if(*name == '/') |
|
488 |
+#endif |
|
489 |
+ *name = '_'; |
|
490 |
+ name++; |
|
491 |
+ } |
|
492 |
+} |
|
493 |
+ |
... | ... |
@@ -60,5 +60,6 @@ void fileblobDestroy(fileblob *fb); |
60 | 60 |
void fileblobSetFilename(fileblob *fb, const char *dir, const char *filename); |
61 | 61 |
const char *fileblobGetFilename(const fileblob *fb); |
62 | 62 |
void fileblobAddData(fileblob *fb, const unsigned char *data, size_t len); |
63 |
+void sanitiseName(char *name); |
|
63 | 64 |
|
64 | 65 |
#endif /*_BLOB_H*/ |
... | ... |
@@ -15,11 +15,14 @@ |
15 | 15 |
* along with this program; if not, write to the Free Software |
16 | 16 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
17 | 17 |
* |
18 |
- * Some of this code is based on minitar.c which is in the public domain. |
|
18 |
+ * Much of this code is based on minitar.c which is in the public domain. |
|
19 | 19 |
* Author: Charles G. Waldman (cgw@pgt.com), Aug 4 1998 |
20 | 20 |
* |
21 | 21 |
* Change History: |
22 | 22 |
* $Log: untar.c,v $ |
23 |
+ * Revision 1.3 2004/09/06 08:34:47 nigelhorne |
|
24 |
+ * Randomise extracted file names from tar file |
|
25 |
+ * |
|
23 | 26 |
* Revision 1.2 2004/09/05 18:58:21 nigelhorne |
24 | 27 |
* Extract files completed |
25 | 28 |
* |
... | ... |
@@ -27,22 +30,25 @@ |
27 | 27 |
* First draft |
28 | 28 |
* |
29 | 29 |
*/ |
30 |
-static char const rcsid[] = "$Id: untar.c,v 1.2 2004/09/05 18:58:21 nigelhorne Exp $"; |
|
30 |
+static char const rcsid[] = "$Id: untar.c,v 1.3 2004/09/06 08:34:47 nigelhorne Exp $"; |
|
31 | 31 |
|
32 | 32 |
#include <stdio.h> |
33 | 33 |
#include <errno.h> |
34 | 34 |
#include <string.h> |
35 | 35 |
#include <unistd.h> |
36 | 36 |
#include <sys/stat.h> |
37 |
+#include <fcntl.h> |
|
38 |
+#include <sys/param.h> /* for NAME_MAX */ |
|
37 | 39 |
|
38 | 40 |
#include "clamav.h" |
39 | 41 |
#include "others.h" |
42 |
+#include "untar.h" |
|
43 |
+#include "blob.h" |
|
40 | 44 |
|
41 | 45 |
#define BLOCKSIZE 512 |
42 |
-#define MAXNAMELEN 1024 |
|
43 | 46 |
|
44 |
-static |
|
45 |
-int octal(const char *str) |
|
47 |
+static int |
|
48 |
+octal(const char *str) |
|
46 | 49 |
{ |
47 | 50 |
int ret = -1; |
48 | 51 |
|
... | ... |
@@ -55,13 +61,12 @@ cli_untar(const char *dir, int desc) |
55 | 55 |
{ |
56 | 56 |
int size = 0; |
57 | 57 |
int in_block = 0; |
58 |
- int directory = 0; |
|
58 |
+ char fullname[NAME_MAX + 1]; |
|
59 | 59 |
FILE *outfile = (FILE*)0; |
60 | 60 |
|
61 | 61 |
cli_dbgmsg("In untar(%s, %d)\n", dir ? dir : "", desc); |
62 | 62 |
|
63 | 63 |
for(;;) { |
64 |
- char fullname[MAXNAMELEN]; |
|
65 | 64 |
char block[BLOCKSIZE]; |
66 | 65 |
const int nread = read(desc, block, sizeof(block)); |
67 | 66 |
|
... | ... |
@@ -74,9 +79,20 @@ cli_untar(const char *dir, int desc) |
74 | 74 |
} |
75 | 75 |
|
76 | 76 |
if(!in_block) { |
77 |
- char magic[7]; |
|
78 |
- char name[101]; |
|
79 | 77 |
char type; |
78 |
+ char *suffix; |
|
79 |
+ size_t suffixLen = 0; |
|
80 |
+ int fd, directory; |
|
81 |
+ char magic[7], name[101], osize[13]; |
|
82 |
+ |
|
83 |
+ if(outfile) { |
|
84 |
+ if(fclose(outfile)) { |
|
85 |
+ cli_errmsg("cli_untar: cannot close file %s\n", |
|
86 |
+ fullname); |
|
87 |
+ return CL_EIO; |
|
88 |
+ } |
|
89 |
+ outfile = (FILE*)0; |
|
90 |
+ } |
|
80 | 91 |
|
81 | 92 |
if(block[0] == '\0') /* We're done */ |
82 | 93 |
break; |
... | ... |
@@ -88,10 +104,6 @@ cli_untar(const char *dir, int desc) |
88 | 88 |
return CL_EDSIG; |
89 | 89 |
} |
90 | 90 |
|
91 |
- strncpy(name, block, 100); |
|
92 |
- name[100] = '\0'; |
|
93 |
- sprintf(fullname, "%s/%s", dir, name); |
|
94 |
- cli_dbgmsg("cli_untar: extracting %s\n", fullname); |
|
95 | 91 |
type = block[156]; |
96 | 92 |
|
97 | 93 |
switch(type) { |
... | ... |
@@ -109,33 +121,59 @@ cli_untar(const char *dir, int desc) |
109 | 109 |
|
110 | 110 |
if(directory) |
111 | 111 |
continue; |
112 |
- else { /*file */ |
|
113 |
- char osize[13]; |
|
114 |
- |
|
115 |
- in_block = 1; |
|
116 |
- if(outfile) { |
|
117 |
- if(fclose(outfile)) { |
|
118 |
- cli_errmsg("cli_untar: cannot close file %s\n", |
|
119 |
- fullname); |
|
120 |
- return CL_EIO; |
|
121 |
- } |
|
122 |
- outfile = (FILE*)0; |
|
123 |
- } |
|
124 | 112 |
|
125 |
- if(!(outfile = fopen(fullname,"wb"))) { |
|
126 |
- cli_errmsg("cli_untar: cannot create file %s\n", |
|
127 |
- fullname); |
|
128 |
- return CL_ETMPFILE; |
|
129 |
- } |
|
113 |
+ strncpy(name, block, 100); |
|
114 |
+ name[100] = '\0'; |
|
130 | 115 |
|
131 |
- strncpy(osize, block+124, 12); |
|
132 |
- osize[12] = '\0'; |
|
133 |
- size = octal(osize); |
|
134 |
- if(size < 0){ |
|
135 |
- cli_errmsg("Invalid size in tar header\n"); |
|
136 |
- return CL_EDSIG; |
|
116 |
+ /* |
|
117 |
+ * see also fileblobSetFilename() |
|
118 |
+ * TODO: check if the suffix needs to be put back |
|
119 |
+ */ |
|
120 |
+ sanitiseName(name); |
|
121 |
+ suffix = strrchr(name, '.'); |
|
122 |
+ if(suffix == NULL) |
|
123 |
+ suffix = ""; |
|
124 |
+ else { |
|
125 |
+ suffixLen = strlen(suffix); |
|
126 |
+ if(suffixLen > 4) { |
|
127 |
+ /* Found a full stop which isn't a suffix */ |
|
128 |
+ suffix = ""; |
|
129 |
+ suffixLen = 0; |
|
137 | 130 |
} |
138 | 131 |
} |
132 |
+ snprintf(fullname, sizeof(fullname) - 1 - suffixLen, "%s/%.*sXXXXXX", dir, |
|
133 |
+ (int)(sizeof(fullname) - 9 - suffixLen - strlen(dir)), name); |
|
134 |
+#if defined(C_LINUX) || defined(C_BSD) || defined(HAVE_MKSTEMP) || defined(C_SOLARIS) || defined(C_CYGWIN) |
|
135 |
+ fd = mkstemp(fullname); |
|
136 |
+#else |
|
137 |
+ (void)mktemp(fullname); |
|
138 |
+ fd = open(fullname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600); |
|
139 |
+#endif |
|
140 |
+ |
|
141 |
+ if(fd < 0) { |
|
142 |
+ cli_errmsg("Can't create temporary file %s: %s\n", fullname, strerror(errno)); |
|
143 |
+ cli_dbgmsg("%lu %d %d\n", suffixLen, sizeof(fullname), strlen(fullname)); |
|
144 |
+ return CL_ETMPFILE; |
|
145 |
+ } |
|
146 |
+ |
|
147 |
+ cli_dbgmsg("cli_untar: extracting %s\n", fullname); |
|
148 |
+ |
|
149 |
+ in_block = 1; |
|
150 |
+ if((outfile = fdopen(fd, "wb")) == NULL) { |
|
151 |
+ cli_errmsg("cli_untar: cannot create file %s\n", |
|
152 |
+ fullname); |
|
153 |
+ close(fd); |
|
154 |
+ return CL_ETMPFILE; |
|
155 |
+ } |
|
156 |
+ |
|
157 |
+ strncpy(osize, block+124, 12); |
|
158 |
+ osize[12] = '\0'; |
|
159 |
+ size = octal(osize); |
|
160 |
+ if(size < 0){ |
|
161 |
+ cli_errmsg("Invalid size in tar header\n"); |
|
162 |
+ fclose(outfile); |
|
163 |
+ return CL_EDSIG; |
|
164 |
+ } |
|
139 | 165 |
} else { /* write or continue writing file contents */ |
140 | 166 |
const int nbytes = size>512? 512:size; |
141 | 167 |
const int nwritten = fwrite(block, 1, nbytes, outfile); |
... | ... |
@@ -149,5 +187,7 @@ cli_untar(const char *dir, int desc) |
149 | 149 |
in_block = 0; |
150 | 150 |
} |
151 | 151 |
} |
152 |
+ if(outfile) |
|
153 |
+ fclose(outfile); |
|
152 | 154 |
return CL_CLEAN; |
153 | 155 |
} |