git-svn: trunk@107
Tomasz Kojm authored on 2003/11/10 04:26:44... | ... |
@@ -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; |