Browse code

check limits in ole2

git-svn: trunk@3635

aCaB authored on 2008/02/15 05:34:02
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+Thu Feb 14 21:20:39 CET 2008 (acab)
2
+-----------------------------------
3
+  * libclamav/ole2_extract.c: check limits
4
+
1 5
 Thu Feb 14 19:38:48 CET 2008 (acab)
2 6
 -----------------------------------
3 7
   * clamscan/manager.c: another typo in setting limits - thx nitrox
... ...
@@ -464,20 +464,18 @@ static void ole2_read_property_tree(int fd, ole2_header_t *hdr, const char *dir,
464 464
 
465 465
 static void ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir, int32_t prop_index,
466 466
 				int (*handler)(int fd, ole2_header_t *hdr, property_t *prop, const char *dir),
467
-				unsigned int rec_level, unsigned int *file_count, const struct cl_limits *limits)
467
+				    unsigned int rec_level, unsigned int *file_count, cli_ctx *ctx, unsigned long *scansize)
468 468
 {
469 469
 	property_t prop_block[4];
470 470
 	int32_t idx, current_block, i;
471 471
 	char *dirname;
472
+	const struct cl_limits *limits = ctx->limits;
472 473
 
473 474
 	current_block = hdr->prop_start;
474 475
 
475 476
 	if ((prop_index < 0) || (prop_index > (int32_t) hdr->max_block_no) || (rec_level > 100) || (*file_count > 100000)) {
476 477
 		return;
477 478
 	}
478
-	/* FIXMELIMITS
479
-	 * DOES recursion on virtual object make sense ?
480
-	 * WHY no size checking ? */
481 479
 	if (limits && limits->maxfiles && (*file_count > limits->maxfiles)) {
482 480
 		cli_dbgmsg("OLE2: File limit reached (max: %d)\n", limits->maxfiles);
483 481
 		return;
... ...
@@ -537,28 +535,37 @@ static void ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir,
537 537
 			}
538 538
 			hdr->sbat_root_start = prop_block[idx].start_block;
539 539
 			ole2_walk_property_tree(fd, hdr, dir,
540
-				prop_block[idx].prev, handler, rec_level+1, file_count, limits);
540
+				prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize);
541 541
 			ole2_walk_property_tree(fd, hdr, dir,
542
-				prop_block[idx].next, handler, rec_level+1, file_count, limits);
542
+				prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize);
543 543
 			ole2_walk_property_tree(fd, hdr, dir,
544
-				prop_block[idx].child, handler, rec_level+1, file_count, limits);
544
+				prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize);
545 545
 			break;
546 546
 		case 2: /* File */
547
-			(*file_count)++;
548
-			if (!handler(fd, hdr, &prop_block[idx], dir)) {
549
-				cli_dbgmsg("ERROR: handler failed\n");
550
-				/* If we don't return on this error then
551
-					we can sometimes pull VBA code
552
-					from corrupted files.
553
-				*/
547
+			if (limits && limits->maxfiles && ctx->scannedfiles + *file_count > limits->maxfiles) {
548
+			  cli_dbgmsg("ole2: files limit reached (max: %u)\n", ctx->limits->maxfiles);
549
+			  break;
550
+			}
551
+			if (!limits || !limits->maxfilesize || prop_block[idx].size <= limits->maxfilesize || *scansize == -1 || prop_block[idx].size <= *scansize) {
552
+				(*file_count)++;
553
+				*scansize-=prop_block[idx].size;
554
+				if (!handler(fd, hdr, &prop_block[idx], dir)) {
555
+					cli_dbgmsg("ERROR: handler failed\n");
556
+					/* If we don't return on this error then
557
+					   we can sometimes pull VBA code
558
+					   from corrupted files.
559
+					*/
554 560
 			
561
+				}
562
+			} else {
563
+				cli_dbgmsg("ole2: filesize exceeded\n");
555 564
 			}
556 565
 			ole2_walk_property_tree(fd, hdr, dir,
557
-				prop_block[idx].prev, handler, rec_level, file_count, limits);
566
+				prop_block[idx].prev, handler, rec_level, file_count, ctx, scansize);
558 567
 			ole2_walk_property_tree(fd, hdr, dir,
559
-				prop_block[idx].next, handler, rec_level, file_count, limits);
568
+				prop_block[idx].next, handler, rec_level, file_count, ctx, scansize);
560 569
 			ole2_walk_property_tree(fd, hdr, dir,
561
-				prop_block[idx].child, handler, rec_level, file_count, limits);
570
+				prop_block[idx].child, handler, rec_level, file_count, ctx, scansize);
562 571
 			break;
563 572
 		case 1: /* Directory */
564 573
 			dirname = (char *) cli_malloc(strlen(dir)+8);
... ...
@@ -572,11 +579,11 @@ static void ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir,
572 572
 			}
573 573
 			cli_dbgmsg("OLE2 dir entry: %s\n",dirname);
574 574
 			ole2_walk_property_tree(fd, hdr, dir,
575
-				prop_block[idx].prev, handler, rec_level+1, file_count, limits);
575
+				prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize);
576 576
 			ole2_walk_property_tree(fd, hdr, dir,
577
-				prop_block[idx].next, handler, rec_level+1, file_count, limits);
577
+				prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize);
578 578
 			ole2_walk_property_tree(fd, hdr, dirname,
579
-				prop_block[idx].child, handler, rec_level+1, file_count, limits);
579
+				prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize);
580 580
 			free(dirname);
581 581
 			break;
582 582
 		default:
... ...
@@ -786,8 +793,16 @@ int cli_ole2_extract(int fd, const char *dirname, cli_ctx *ctx)
786 786
 	int hdr_size;
787 787
 	struct stat statbuf;
788 788
 	unsigned int file_count=0;
789
-	
789
+	unsigned long scansize;
790
+
790 791
 	cli_dbgmsg("in cli_ole2_extract()\n");
792
+
793
+	if (ctx->limits && ctx->limits->maxscansize) {
794
+	  if (ctx->limits->maxscansize > ctx->scansize)
795
+	    scansize = ctx->limits->maxscansize - ctx->scansize;
796
+	  else
797
+	    return CL_EMAXSIZE;
798
+	} else scansize = -1;
791 799
 	
792 800
 	/* size of header - size of other values in struct */
793 801
 	hdr_size = sizeof(struct ole2_header_tag) - sizeof(int32_t) -
... ...
@@ -880,7 +895,7 @@ int cli_ole2_extract(int fd, const char *dirname, cli_ctx *ctx)
880 880
 	
881 881
 	/* OR */
882 882
 	
883
-	ole2_walk_property_tree(fd, &hdr, dirname, 0, handler_writefile, 0, &file_count, ctx->limits);
883
+	ole2_walk_property_tree(fd, &hdr, dirname, 0, handler_writefile, 0, &file_count, ctx, &scansize);
884 884
 
885 885
 abort:
886 886
 #ifdef HAVE_MMAP