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... | ... |
@@ -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 |