Browse code

newlimits started

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

aCaB authored on 2008/01/29 12:27:30
Showing 5 changed files
... ...
@@ -181,7 +181,7 @@ static int ea05(int desc, cli_ctx *ctx, char *tmpd) {
181 181
   uint8_t b[300], comp;
182 182
   uint8_t *buf = b;
183 183
   uint32_t s, m4sum=0;
184
-  int i;
184
+  int i, ret;
185 185
   unsigned int files=0;
186 186
   char tempfile[1024];
187 187
   struct UNP UNP;
... ...
@@ -192,7 +192,7 @@ static int ea05(int desc, cli_ctx *ctx, char *tmpd) {
192 192
   for (i=0; i<16; i++)
193 193
     m4sum += buf[i];
194 194
 
195
-  while(!ctx->limits || !ctx->limits->maxfiles || files < ctx->limits->maxfiles) {
195
+  while((ret=cli_checklimits("autoit", ctx, 0, 0, 0))==CL_CONTINUE) {
196 196
     buf = b;
197 197
     if (cli_readn(desc, buf, 8)!=8)
198 198
       return CL_CLEAN;
... ...
@@ -250,8 +250,9 @@ static int ea05(int desc, cli_ctx *ctx, char *tmpd) {
250 250
     cli_dbgmsg("autoit: advertised uncompressed size %x\n", cli_readint32((char *)buf+5) ^ 0x45aa);
251 251
     cli_dbgmsg("autoit: ref chksum: %x\n", cli_readint32((char *)buf+9) ^ 0xc3d2);
252 252
 
253
-    if(ctx->limits && ctx->limits->maxfilesize && UNP.csize > ctx->limits->maxfilesize) {
254
-      cli_dbgmsg("autoit: skipping file due to size limit (%u, max: %lu)\n", UNP.csize, ctx->limits->maxfilesize);
253
+    
254
+    if((ret=cli_checklimits("autoit", ctx, UNP.csize, 0, 0))!=CL_CONTINUE) {
255
+      if(ret==CL_VIRUS) return ret;
255 256
       lseek(desc, UNP.csize, SEEK_CUR);
256 257
       continue;
257 258
     }
... ...
@@ -275,9 +276,9 @@ static int ea05(int desc, cli_ctx *ctx, char *tmpd) {
275 275
 
276 276
       if(!(UNP.usize = be32_to_host(*(uint32_t *)(buf+4))))
277 277
 	UNP.usize = UNP.csize; /* only a specifically crafted or badly corrupted sample should land here */
278
-      if(ctx->limits && ctx->limits->maxfilesize && UNP.usize > ctx->limits->maxfilesize) {
279
-	cli_dbgmsg("autoit: skipping file due to size limit (%u, max: %lu)\n", UNP.csize, ctx->limits->maxfilesize);
278
+      if((ret=cli_checklimits("autoit", ctx, UNP.usize, 0, 0))!=CL_CONTINUE) {
280 279
 	free(buf);
280
+	if(ret==CL_VIRUS) return ret;
281 281
 	continue;
282 282
       }
283 283
 
... ...
@@ -382,8 +383,7 @@ static int ea05(int desc, cli_ctx *ctx, char *tmpd) {
382 382
     close(i);
383 383
     if(!cli_leavetemps_flag) unlink(tempfile);
384 384
   }
385
-  cli_dbgmsg("autoit: files limit reached (max: %u)\n", ctx->limits->maxfiles);
386
-  return CL_EMAXFILES;
385
+  return ret;
387 386
 }
388 387
 
389 388
 
... ...
@@ -478,7 +478,7 @@ static int ea06(int desc, cli_ctx *ctx, char *tmpd) {
478 478
   uint8_t b[600], comp, script;
479 479
   uint8_t *buf;
480 480
   uint32_t s;
481
-  int i;
481
+  int i, ret;
482 482
   unsigned int files=0;
483 483
   char tempfile[1024];
484 484
   const char prefixes[] = { '\0', '\0', '@', '$', '\0', '.', '"', '#' };
... ...
@@ -492,7 +492,7 @@ static int ea06(int desc, cli_ctx *ctx, char *tmpd) {
492 492
   /*   buf+=0x10; */
493 493
   lseek(desc, 16, SEEK_CUR);   /* for now we just skip the garbage */
494 494
 
495
-  while(!ctx->limits || !ctx->limits->maxfiles || files < ctx->limits->maxfiles) {
495
+  while((ret=cli_checklimits("cli_autoit", ctx, 0, 0, 0))==CL_CONTINUE) {
496 496
     buf = b;
497 497
     if (cli_readn(desc, buf, 8)!=8)
498 498
       return CL_CLEAN;
... ...
@@ -555,8 +555,8 @@ static int ea06(int desc, cli_ctx *ctx, char *tmpd) {
555 555
     cli_dbgmsg("autoit: advertised uncompressed size %x\n", cli_readint32((char *)buf+5) ^ 0x87bc);
556 556
     cli_dbgmsg("autoit: ref chksum: %x\n", cli_readint32((char *)buf+9) ^ 0xa685);
557 557
 
558
-    if(ctx->limits && ctx->limits->maxfilesize && UNP.csize > ctx->limits->maxfilesize) {
559
-      cli_dbgmsg("autoit: skipping file due to size limit (%u, max: %lu)\n", UNP.csize, ctx->limits->maxfilesize);
558
+    if((ret=cli_checklimits("autoit", ctx, UNP.csize, 0, 0))!=CL_CONTINUE) {
559
+      if(ret==CL_VIRUS) return ret;
560 560
       lseek(desc, UNP.csize, SEEK_CUR);
561 561
       continue;
562 562
     }
... ...
@@ -581,8 +581,9 @@ static int ea06(int desc, cli_ctx *ctx, char *tmpd) {
581 581
 
582 582
       if(!(UNP.usize = be32_to_host(*(uint32_t *)(buf+4))))
583 583
 	UNP.usize = UNP.csize; /* only a specifically crafted or badly corrupted sample should land here */
584
-      if(ctx->limits && ctx->limits->maxfilesize && UNP.usize > ctx->limits->maxfilesize) {
584
+      if((ret=cli_checklimits("autoit", ctx, UNP.usize, 0, 0))!=CL_CONTINUE) {
585 585
 	free(buf);
586
+	if(ret==CL_VIRUS) return ret;
586 587
 	continue;
587 588
       }
588 589
       if (!(UNP.outputbuf = cli_malloc(UNP.usize))) {
... ...
@@ -893,8 +894,7 @@ static int ea06(int desc, cli_ctx *ctx, char *tmpd) {
893 893
     close(i);
894 894
     if(!cli_leavetemps_flag) unlink(tempfile);
895 895
   }
896
-  cli_dbgmsg("autoit: Files limit reached (max: %u)\n", ctx->limits->maxfiles);
897
-  return CL_EMAXFILES;
896
+  return ret;
898 897
 }
899 898
 
900 899
 #endif /* FPU_WORDS_BIGENDIAN */
... ...
@@ -108,13 +108,9 @@ int cli_msexpand(int fd, int ofd, cli_ctx *ctx)
108 108
 
109 109
     cli_dbgmsg("MSEXPAND: File size from header: %u\n", hdr.fsize);
110 110
 
111
-    if(ctx->limits && ctx->limits->maxfilesize && (hdr.fsize > ctx->limits->maxfilesize)) {
112
-	cli_dbgmsg("MSEXPAND: Size exceeded (%u, max: %lu)\n", hdr.fsize, ctx->limits->maxfilesize);
113
-        if(BLOCKMAX) {
114
-	    *ctx->virname = "MSEXPAND.ExceededFileSize";
115
-            return CL_VIRUS;
116
-        }
117
-	hdr.fsize = ctx->limits->maxfilesize;
111
+    if((ret=cli_checklimits("MSEXPAND", ctx, hdr.fsize, 0, 0))!=CL_CONTINUE) {
112
+        if(ret==CL_VIRUS) return ret;
113
+	hdr.fsize = (ctx->limits->maxfilesize > ctx->limits->maxscansize-ctx->scansize) ? ctx->limits->maxscansize-ctx->scansize : ctx->limits->maxfilesize;
118 114
 	cli_dbgmsg("MSEXPAND: Only extracting first %u bytes\n", hdr.fsize); /* may extract up to 2kB more */
119 115
     }
120 116
 
... ...
@@ -196,63 +196,65 @@ const char *cl_strerror(int clerror)
196 196
     }
197 197
 }
198 198
 
199
-int cli_sizelimits(cli_ctx *ctx, unsigned long need1, unsigned long need2, unsigned long need3) {
200
-  int ret = CL_SUCCESS;
201
-  unsigned long needed;
202
-
203
-  /* if called without limits, go on, unpack, scan */
204
-  if(!ctx || !ctx->limits) return CL_SUCCESS;
205
-
206
-  needed = (need1>need2)?need1:need2;
207
-  needed = (needed>need3)?needed:need3;
208
-
209
-  /* if we have global scan limits */
210
-  if(ctx->limits->maxscansize) {
211
-    /* if the remaining scansize is too small... */
212
-    if(ctx->limits->maxscansize-ctx->scansize<needed) {
213
-      cli_dbgmsg("cli_limits: scansize exceeded (initial: %u, remaining: %u, needed: %u)\n", ctx->limits->maxscansize, ctx->scansize, needed);
214
-      /* ... we return INFECTED only upon request */ 
215
-      if(BLOCKMAX) {
216
-	*ctx->virname = "Archive.ExceededScanSize";
217
-	return CL_VIRUS;
218
-      }
219
-      /* ... otherwise we tell the caller to skip this file */
220
-      ret = CL_BREAK;
221
-    } else {
222
-      /* if the remaining scanzise is big enough, we update it */
223
-      ctx->scansize+=needed;
199
+int cli_checklimits(const char *who, cli_ctx *ctx, unsigned long need1, unsigned long need2, unsigned long need3) {
200
+    int ret = CL_SUCCESS;
201
+    unsigned long needed;
202
+
203
+    /* if called without limits, go on, unpack, scan */
204
+    if(!ctx || !ctx->limits) return CL_SUCCESS;
205
+
206
+    /* check if we have limits on the number of files */
207
+    /* FIMMELIMITS: this only makes sense in updatelimits */
208
+    if(ctx->limits->maxfiles && ctx->scanned>=ctx->limits->maxfiles) {
209
+        cli_dbgmsg("%s: files limit reached (max: %u)\n", who, ctx->maxfiles);
210
+        return CL_EMAXFILES;
224 211
     }
225
-  }
226
-
227
-  /* if we have per-file size limits, and we are overlimit... */
228
-  if(ctx->limits->maxfilesize && ctx->limits->maxfilesize<needed) {
229
-    /* ... we return INFECTED only upon request */ 
230
-    if(BLOCKMAX) {
231
-      *ctx->virname = "Archive.ExceededFileSize";
232
-      return CL_VIRUS;
212
+
213
+    needed = (need1>need2)?need1:need2;
214
+    needed = (needed>need3)?needed:need3;
215
+
216
+    /* if we have global scan limits */
217
+    if(ctx->limits->maxscansize) {
218
+        /* if the remaining scansize is too small... */
219
+        if(ctx->limits->maxscansize-ctx->scansize<needed) {
220
+	    cli_dbgmsg("%s: scansize exceeded (initial: %u, remaining: %u, needed: %u)\n", who, ctx->limits->maxscansize, ctx->scansize, needed);
221
+	    /* ... we return INFECTED only upon request */ 
222
+	    if(BLOCKMAX) {
223
+	        *ctx->virname = "Archive.ExceededScanSize";
224
+		return CL_VIRUS;
225
+	    }
226
+	    /* ... otherwise we tell the caller to skip this file */
227
+	    ret = CL_EMAXSIZE;
228
+	}
233 229
     }
234
-    /* ... otherwise we tell the caller to skip this file */
235
-    ret = CL_BREAK;
236
-  }
237 230
 
238
-  return ret;
231
+    /* if we have per-file size limits, and we are overlimit... */
232
+    if(ctx->limits->maxfilesize && ctx->limits->maxfilesize<needed) {
233
+        cli_dbgmsg("%s: filesize exceeded (allowed: %u, needed: %u)\n", who, ctx->limits->maxfilesize, needed);
234
+        /* ... we return INFECTED only upon request */ 
235
+        if(BLOCKMAX) {
236
+	    *ctx->virname = "Archive.ExceededFileSize";
237
+	    return CL_VIRUS;
238
+	}
239
+	/* ... otherwise we tell the caller to skip this file */
240
+	ret = CL_EMAXSIZE;
241
+    }
242
+    return ret;
239 243
 }
240 244
 
241
-int cli_filelimits(cli_ctx *ctx) {
242
-  /* FIXME: inline in magic_scandesc? */
245
+int cli_updatelimits(cli_ctx *ctx, unsigned long need) {
246
+    int ret;
243 247
 
244
-  /* if called without limits, go on, unpack, scan */
245
-  if(!ctx || !ctx->limits || !ctx->limits->maxfiles) return CL_SUCCESS;
248
+    if((ret=cli_checklimits(ctx, need, 0, 0))==CL_SUCCESS) {
249
+        /* update counter */
250
+        ctx->scanned++;
251
+	/* update the remaining scanzise */
252
+	ctx->scansize+=needed;
253
+	if(ctx->scansize > ctx->limits->maxscansize)
254
+	    ctx->scansize = ctx->limits->maxscansize;
255
+    }
246 256
 
247
-  /* if we are within the limit */
248
-  if(ctx->limits->maxfiles > ctx->scanned) {
249
-    /* update counters and ack */
250
-    ctx->scanned++;
251
-    return CL_SUCCESS;
252
-  } else {
253
-    /* else tell the caller to quit */
254
-    return CL_BREAK;
255
-  }
257
+    return ret;
256 258
 }
257 259
 
258 260
 unsigned char *cli_md5digest(int desc)
... ...
@@ -231,5 +231,7 @@ bitset_t *cli_bitset_init(void);
231 231
 void cli_bitset_free(bitset_t *bs);
232 232
 int cli_bitset_set(bitset_t *bs, unsigned long bit_offset);
233 233
 int cli_bitset_test(bitset_t *bs, unsigned long bit_offset);
234
+int cli_checklimits(const char *, cli_ctx *, unsigned long, unsigned long, unsigned long);
235
+int cli_updatelimits(cli_ctx *, unsigned long);
234 236
 
235 237
 #endif
... ...
@@ -79,10 +79,9 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
79 79
 	char *buf;	/* start of memory mapped area */
80 80
 	const char *p, *q, *trailerstart;
81 81
 	const char *xrefstart;	/* cross reference table */
82
-	const struct cl_limits *limits;
83 82
 	/*size_t xreflength;*/
84 83
 	table_t *md5table;
85
-	int printed_predictor_message, printed_embedded_font_message, rc;
84
+	int printed_predictor_message, printed_embedded_font_message, rc, ret;
86 85
 	unsigned int files;
87 86
 	struct stat statb;
88 87
 
... ...
@@ -192,7 +191,6 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
192 192
 
193 193
 	rc = CL_CLEAN;
194 194
 	files = 0;
195
-	limits = ctx->limits;
196 195
 
197 196
 	/*
198 197
 	 * The body section consists of a sequence of indirect objects
... ...
@@ -494,10 +492,10 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
494 494
 		free(md5digest);
495 495
 		cli_dbgmsg("cli_pdf: extracted file %u to %s\n", ++files,
496 496
 			fullname);
497
-		if(limits && limits->maxfiles && (files >= limits->maxfiles)) {
497
+
498
+		if((ret=cli_checklimits("cli_pdf", ctx, 0, 0, 0))!=CL_CONTINUE) {
498 499
 			/* Bug 698 */
499
-			cli_dbgmsg("cli_pdf: number of files exceeded %u\n", limits->maxfiles);
500
-			rc = CL_EMAXFILES;
500
+			rc = ret;
501 501
 		}
502 502
 	}
503 503
 
... ...
@@ -541,7 +539,7 @@ try_flatedecode(unsigned char *buf, off_t real_len, off_t calculated_len, int fo
541 541
 static int
542 542
 flatedecode(unsigned char *buf, off_t len, int fout, const cli_ctx *ctx)
543 543
 {
544
-	int zstat;
544
+	int zstat, ret;
545 545
 	off_t nbytes;
546 546
 	z_stream stream;
547 547
 	unsigned char output[BUFSIZ];
... ...
@@ -611,17 +609,9 @@ flatedecode(unsigned char *buf, off_t len, int fout, const cli_ctx *ctx)
611 611
 					}
612 612
 					nbytes += written;
613 613
 
614
-					if(ctx->limits &&
615
-					   ctx->limits->maxfilesize &&
616
-					   (nbytes > (off_t) ctx->limits->maxfilesize)) {
617
-						cli_dbgmsg("cli_pdf: flatedecode size exceeded (%lu > %lu)\n",
618
-							   (unsigned long)nbytes, (unsigned long)ctx->limits->maxfilesize);
614
+					if((ret=cli_checklimits("cli_pdf", ctx, nbytes, 0, 0))!=CL_CONTINUE) {
619 615
 						inflateEnd(&stream);
620
-						if(BLOCKMAX) {
621
-							*ctx->virname = "PDF.ExceededFileSize";
622
-							return CL_VIRUS;
623
-						}
624
-						return CL_CLEAN;
616
+						return ret;
625 617
 					}
626 618
 					stream.next_out = output;
627 619
 					stream.avail_out = sizeof(output);
... ...
@@ -651,28 +641,6 @@ flatedecode(unsigned char *buf, off_t len, int fout, const cli_ctx *ctx)
651 651
 		}
652 652
 	}
653 653
 			
654
-
655
-	/*
656
-	 * On BSD systems total_in and total_out are "long long", so these
657
-	 * numbers could (in theory) get truncated in the debug statement
658
-	 */
659
-	cli_dbgmsg("cli_pdf: flatedecode in=%lu out=%lu ratio %lu (max %u)\n",
660
-		(unsigned long)stream.total_in, (unsigned long)stream.total_out,
661
-		(unsigned long)(stream.total_out / stream.total_in),
662
-		ctx->limits ? ctx->limits->maxratio : 0);
663
-
664
-	if(ctx->limits &&
665
-	   ctx->limits->maxratio &&
666
-	   ((stream.total_out / stream.total_in) > ctx->limits->maxratio)) {
667
-		cli_dbgmsg("cli_pdf: flatedecode Max ratio reached\n");
668
-		inflateEnd(&stream);
669
-		if(BLOCKMAX) {
670
-			*ctx->virname = "Oversized.PDF";
671
-			return CL_VIRUS;
672
-		}
673
-		return CL_CLEAN;
674
-	}
675
-
676 654
 #ifdef	SAVE_TMP
677 655
 	unlink(tmpfilename);
678 656
 #endif