Browse code

Randomise extracted file names from tar file

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
Showing 3 changed files
... ...
@@ -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
 }