Browse code

SCANBUFF -> FILEBUFF fix

git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@107 77e5149b-7576-45b1-b177-96237e5ba77b

Tomasz Kojm authored on 2003/11/10 04:26:44
Showing 4 changed files
... ...
@@ -1,3 +1,10 @@
1
+Sun Nov  9 20:25:11 CET 2003 (tk)
2
+---------------------------------
3
+  * libclamav: some functions were still using SCANBUFF instead of FILEBUFF,
4
+	       this is now finally fixed (bug reported by J.D. Bronson
5
+	       jeff_bronson*wixb.com). Also added more zip hardening checks
6
+	       to handle broken Mimail-like archives.
7
+
1 8
 Sun Nov  9 03:21:48 CET 2003 (tk)
2 9
 ---------------------------------
3 10
   * libclamav: archive wrapper and database parsing functions were using a
... ...
@@ -30,6 +30,10 @@
30 30
 #include "defaults.h"
31 31
 #include "treewalk.h"
32 32
 
33
+#ifdef C_LINUX
34
+#include <sys/resource.h>
35
+#endif
36
+
33 37
 void help(void);
34 38
 
35 39
 /* this local macro takes care about freeing memory at exit */
... ...
@@ -62,8 +66,17 @@ void clamscan(struct optstruct *opt)
62 62
     if(optl(opt, "stdout")) mprintf_stdout = 1;
63 63
     else mprintf_stdout = 0;
64 64
 
65
-    if(optl(opt, "debug"))
66
-	cl_debug();
65
+    if(optl(opt, "debug")) {
66
+#if defined(C_LINUX)
67
+	    /* njh@bandsman.co.uk: create a dump if needed */
68
+	    struct rlimit rlim;
69
+
70
+	rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
71
+	if(setrlimit(RLIMIT_CORE, &rlim) < 0)
72
+	    perror("setrlimit");
73
+#endif
74
+	cl_debug(); /* enable debug messages */
75
+    }
67 76
 
68 77
     if(optc(opt, 'V')) {
69 78
 	mprintf("clamscan / ClamAV version "VERSION"\n");
... ...
@@ -26,9 +26,6 @@
26 26
 #define _GNU_SOURCE
27 27
 #include "getopt.h"
28 28
 
29
-#if defined(C_LINUX) && defined(CL_DEBUG)
30
-#include <sys/resource.h>
31
-#endif
32 29
 
33 30
 #include "options.h"
34 31
 #include "others.h"
... ...
@@ -86,14 +83,6 @@ int main(int argc, char **argv)
86 86
 	    {0, 0, 0, 0}
87 87
     	};
88 88
 
89
-#if defined(C_LINUX) && defined(CL_DEBUG)
90
-	/* njh@bandsman.co.uk: create a dump if needed */
91
-	struct rlimit rlim;
92
-
93
-    rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
94
-    if(setrlimit(RLIMIT_CORE, &rlim) < 0)
95
-	perror("setrlimit");
96
-#endif
97 89
 
98 90
     opt=(struct optstruct*) mmalloc(sizeof(struct optstruct));
99 91
     opt->optlist = NULL;
... ...
@@ -61,6 +61,7 @@ int cli_scanrar_inuse = 0;
61 61
 #define DELIVERED_MAGIC_STR "Delivered-To: "
62 62
 #define BZIP_MAGIC_STR "BZh"
63 63
 
64
+#define ZIPOSDET 20 /* FIXME: Make it user definable */
64 65
 
65 66
 int cli_magic_scandesc(int desc, char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *reclev);
66 67
 
... ...
@@ -120,7 +121,7 @@ void cli_unlock_mutex(void *mtx)
120 120
 
121 121
 int cli_scanrar(int desc, char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *reclev)
122 122
 {
123
-	FILE *tmp;
123
+	FILE *tmp = NULL;
124 124
 	int files = 0, fd, ret = CL_CLEAN;
125 125
 	ArchiveList_struct *rarlist = NULL;
126 126
 	char *rar_data_ptr;
... ...
@@ -240,10 +241,10 @@ int cli_scanzip(int desc, char **virname, long int *scanned, const struct cl_nod
240 240
 	ZZIP_DIR *zdir;
241 241
 	ZZIP_DIRENT zdirent;
242 242
 	ZZIP_FILE *zfp;
243
-	FILE *tmp;
243
+	FILE *tmp = NULL;
244 244
 	char *buff;
245 245
 	int fd, bytes, files = 0, ret = CL_CLEAN, err;
246
-
246
+	struct stat source;
247 247
 
248 248
     cli_dbgmsg("Starting scanzip()\n");
249 249
 
... ...
@@ -253,9 +254,25 @@ int cli_scanzip(int desc, char **virname, long int *scanned, const struct cl_nod
253 253
 	return CL_EZIP;
254 254
     }
255 255
 
256
+    fstat(desc, &source);
257
+
256 258
     while(zzip_dir_read(zdir, &zdirent)) {
259
+
260
+	if(!zdirent.d_name || !strlen(zdirent.d_name)) { /* Mimail fix */
261
+	    cli_dbgmsg("strlen(zdirent.d_name) == %d\n", strlen(zdirent.d_name));
262
+	    *virname = "Seriously Broken Zip";
263
+	    ret = CL_VIRUS;
264
+	    break;
265
+	}
266
+
257 267
 	cli_dbgmsg("Zip -> %s, compressed: %d, normal: %d.\n", zdirent.d_name, zdirent.d_csize, zdirent.st_size);
258 268
 
269
+	if(source.st_size && (zdirent.st_size / source.st_size) >= ZIPOSDET) {
270
+	    *virname = "Oversized Zip";
271
+	    ret = CL_VIRUS;
272
+	    break;
273
+	}
274
+
259 275
 	if(!zdirent.st_size) { /* omit directories and null files */
260 276
 	    files++;
261 277
 	    continue;
... ...
@@ -265,7 +282,10 @@ int cli_scanzip(int desc, char **virname, long int *scanned, const struct cl_nod
265 265
 	if(zdirent.d_csize < 0 || zdirent.st_size < 0) {
266 266
 	    files++;
267 267
 	    cli_dbgmsg("Zip -> Malformed archive detected.\n");
268
-	    ret = CL_EMALFZIP;
268
+	    /* ret = CL_EMALFZIP; */
269
+	    /* report it as a virus */
270
+	    *virname = "Seriously Broken Zip";
271
+	    ret = CL_VIRUS;
269 272
 	    break;
270 273
 	}
271 274
 
... ...
@@ -274,7 +294,7 @@ int cli_scanzip(int desc, char **virname, long int *scanned, const struct cl_nod
274 274
 		cli_dbgmsg("Zip -> %s: Size exceeded (%d, max: %d)\n", zdirent.d_name, zdirent.st_size, limits->maxfilesize);
275 275
 		files++;
276 276
 		ret = CL_EMAXSIZE;
277
-		continue;
277
+		continue; /* this is not a bug */
278 278
 	    }
279 279
 
280 280
 	    if(limits->maxfiles && (files > limits->maxfiles)) {
... ...
@@ -287,28 +307,29 @@ int cli_scanzip(int desc, char **virname, long int *scanned, const struct cl_nod
287 287
 	/* generate temporary file and get its descriptor */
288 288
 	if((tmp = tmpfile()) == NULL) {
289 289
 	    cli_dbgmsg("Zip -> Can't generate tmpfile().\n");
290
-	    zzip_dir_close(zdir);
291
-	    return CL_ETMPFILE;
290
+	    ret = CL_ETMPFILE;
291
+	    break;
292 292
 	}
293 293
 
294 294
 	if((zfp = zzip_file_open(zdir, zdirent.d_name, 0)) == NULL) {
295 295
 	    cli_dbgmsg("Zip -> %s: Can't open file.\n", zdirent.d_name);
296 296
 	    ret = CL_EZIP;
297
-	    continue;
297
+	    break;
298 298
 	}
299 299
 
300
-	if(!(buff = (char *) cli_malloc(FILEBUFF)))
301
-	    return CL_EMEM;
300
+	if(!(buff = (char *) cli_malloc(FILEBUFF))) {
301
+	    ret = CL_EMEM;
302
+	    break;
303
+	}
302 304
 
303 305
 	while((bytes = zzip_file_read(zfp, buff, FILEBUFF)) > 0) {
304 306
 	    if(fwrite(buff, bytes, 1, tmp)*bytes != bytes) {
305 307
 		cli_dbgmsg("Zip -> Can't fwrite() file: %s\n", strerror(errno));
306 308
 		zzip_file_close(zfp);
307
-		zzip_dir_close(zdir);
308 309
 		files++;
309
-		fclose(tmp);
310 310
 		free(buff);
311
-		return CL_EZIP;
311
+		ret = CL_EZIP;
312
+		break;
312 313
 	    }
313 314
 	}
314 315
 
... ...
@@ -317,9 +338,8 @@ int cli_scanzip(int desc, char **virname, long int *scanned, const struct cl_nod
317 317
 
318 318
 	if(fflush(tmp) != 0) {
319 319
 	    cli_errmsg("fflush() failed: %s\n", strerror(errno));
320
-	    zzip_dir_close(zdir);
321
-	    fclose(tmp);
322
-	    return CL_EFSYNC;
320
+	    ret = CL_EFSYNC;
321
+	    break;
323 322
 	}
324 323
 
325 324
 	fd = fileno(tmp);
... ...
@@ -327,18 +347,14 @@ int cli_scanzip(int desc, char **virname, long int *scanned, const struct cl_nod
327 327
 	lseek(fd, 0, SEEK_SET);
328 328
 	if((ret = cli_magic_scandesc(fd, virname, scanned, root, limits, options, reclev)) == CL_VIRUS ) {
329 329
 	    cli_dbgmsg("Zip -> Found %s virus.\n", *virname);
330
-	    fclose(tmp);
331
-	    tmp = NULL;
332 330
 	    ret = CL_VIRUS;
333 331
 	    break;
334 332
 	} else if(ret == CL_EMALFZIP) {
335 333
 	    /* 
336
-	     * The trick with detection of ZoD works with higher (>= 5)
334
+	     * The trick with detection of ZoD only works with higher (>= 5)
337 335
 	     * recursion limit level.
338 336
 	     */
339 337
 	    cli_dbgmsg("Zip -> Malformed Zip, scanning stopped.\n");
340
-	    fclose(tmp);
341
-	    tmp = NULL;
342 338
 	    *virname = "Malformed Zip";
343 339
 	    ret = CL_VIRUS;
344 340
 	    break;
... ...
@@ -364,10 +380,12 @@ int cli_scangzip(int desc, char **virname, long int *scanned, const struct cl_no
364 364
 	int fd, bytes, ret = CL_CLEAN;
365 365
 	long int size = 0;
366 366
 	char *buff;
367
-	FILE *tmp;
367
+	FILE *tmp = NULL;
368 368
 	gzFile gd;
369 369
 
370 370
 
371
+    cli_dbgmsg("in cli_scangzip()\n");
372
+
371 373
     if((gd = gzdopen(dup(desc), "rb")) == NULL) {
372 374
 	cli_dbgmsg("Can't gzdopen() descriptor %d.\n", desc);
373 375
 	return CL_EGZIP;
... ...
@@ -380,14 +398,16 @@ int cli_scangzip(int desc, char **virname, long int *scanned, const struct cl_no
380 380
     }
381 381
     fd = fileno(tmp);
382 382
 
383
-    if(!(buff = (char *) cli_malloc(FILEBUFF)))
383
+    if(!(buff = (char *) cli_malloc(FILEBUFF))) {
384
+	gzclose(gd);
384 385
 	return CL_EMEM;
386
+    }
385 387
 
386
-    while((bytes = gzread(gd, buff, SCANBUFF)) > 0) {
388
+    while((bytes = gzread(gd, buff, FILEBUFF)) > 0) {
387 389
 	size += bytes;
388 390
 
389 391
 	if(limits)
390
-	    if(limits->maxfilesize && (size + SCANBUFF > limits->maxfilesize)) {
392
+	    if(limits->maxfilesize && (size + FILEBUFF > limits->maxfilesize)) {
391 393
 		cli_dbgmsg("Gzip->desc(%d): Size exceeded (stopped at %d, max: %d)\n", desc, size, limits->maxfilesize);
392 394
 		ret = CL_EMAXSIZE;
393 395
 		break;
... ...
@@ -436,7 +456,7 @@ int cli_scanbzip(int desc, char **virname, long int *scanned, const struct cl_no
436 436
 	short memlim = 0;
437 437
 	long int size = 0;
438 438
 	char *buff;
439
-	FILE *fs, *tmp;
439
+	FILE *fs, *tmp = NULL;
440 440
 	BZFILE *bfd;
441 441
 
442 442
 
... ...
@@ -464,11 +484,11 @@ int cli_scanbzip(int desc, char **virname, long int *scanned, const struct cl_no
464 464
     if(!(buff = (char *) cli_malloc(FILEBUFF)))
465 465
 	return CL_EMEM;
466 466
 
467
-    while((bytes = BZ2_bzRead(&bzerror, bfd, buff, SCANBUFF)) > 0) {
467
+    while((bytes = BZ2_bzRead(&bzerror, bfd, buff, FILEBUFF)) > 0) {
468 468
 	size += bytes;
469 469
 
470 470
 	if(limits)
471
-	    if(limits->maxfilesize && (size + SCANBUFF > limits->maxfilesize)) {
471
+	    if(limits->maxfilesize && (size + FILEBUFF > limits->maxfilesize)) {
472 472
 		cli_dbgmsg("Bzip2->desc(%d): Size exceeded (stopped at %d, max: %d)\n", desc, size, limits->maxfilesize);
473 473
 		ret = CL_EMAXSIZE;
474 474
 		break;