From d91ab809a2f7ca9cdb952fdaab02a9ed3c890af9 Mon Sep 17 00:00:00 2001 From: aCaB Date: Wed, 6 Feb 2008 21:19:10 +0000 Subject: [PATCH] initial rewrite of limits git-svn-id: file:///var/lib/svn/clamav-devel/branches/newlimits@3591 77e5149b-7576-45b1-b177-96237e5ba77b --- clamd/server-th.c | 12 --- clamscan/clamscan_opt.h | 3 - clamscan/manager.c | 13 --- libclamav/autoit.c | 16 ++-- libclamav/blob.c | 2 +- libclamav/cab.c | 2 +- libclamav/mbox.c | 13 +-- libclamav/msexpand.c | 7 +- libclamav/nsis/nulsft.c | 11 +-- libclamav/others.c | 63 +++++++------- libclamav/others.h | 6 +- libclamav/pdf.c | 10 +-- libclamav/pe.c | 13 +-- libclamav/scanners.c | 189 +++++++--------------------------------- libclamav/sis.c | 49 ++++------- libclamav/unsp.c | 4 +- libclamav/untar.c | 16 ++-- libclamav/untar.h | 10 ++- libclamav/unzip.c | 33 +------ 19 files changed, 121 insertions(+), 351 deletions(-) diff --git a/clamd/server-th.c b/clamd/server-th.c index 1ba6657bb..dd37b15f6 100644 --- a/clamd/server-th.c +++ b/clamd/server-th.c @@ -332,12 +332,6 @@ int acceptloop_th(int *socketds, int nsockets, struct cl_engine *engine, unsigne logg("^Archive: Files limit protection disabled.\n"); } - if((limits.maxratio = cfgopt(copt, "ArchiveMaxCompressionRatio")->numarg)) { - logg("Archive: Compression ratio limit set to %u.\n", limits.maxratio); - } else { - logg("^Archive: Compression ratio limit disabled.\n"); - } - if(cfgopt(copt, "ArchiveLimitMemoryUsage")->enabled) { limits.archivememlim = 1; logg("Archive: Limited memory usage.\n"); @@ -401,12 +395,6 @@ int acceptloop_th(int *socketds, int nsockets, struct cl_engine *engine, unsigne options |= CL_SCAN_MAILURL; } - if((limits.maxmailrec = cfgopt(copt, "MailMaxRecursion")->numarg)) { - logg("Mail: Recursion level limit set to %u.\n", limits.maxmailrec); - } else { - logg("^Mail: Recursion level limit protection disabled.\n"); - } - } else { logg("Mail files support disabled.\n"); } diff --git a/clamscan/clamscan_opt.h b/clamscan/clamscan_opt.h index 062b4098a..115df6422 100644 --- a/clamscan/clamscan_opt.h +++ b/clamscan/clamscan_opt.h @@ -55,16 +55,13 @@ static struct option clamscan_longopt[] = { {"include-dir", 1, 0, 0}, {"max-files", 1, 0, 0}, {"max-space", 1, 0, 0}, - {"max-ratio", 1, 0, 0}, {"max-recursion", 1, 0, 0}, {"max-dir-recursion", 1, 0, 0}, - {"max-mail-recursion", 1, 0, 0}, {"detect-pua", 0, 0, 0}, {"disable-archive", 0, 0, 0}, {"no-archive", 0, 0, 0}, {"detect-broken", 0, 0, 0}, {"block-encrypted", 0, 0, 0}, - {"block-max", 0, 0, 0}, {"no-pe", 0, 0, 0}, {"no-elf", 0, 0, 0}, {"no-ole2", 0, 0, 0}, diff --git a/clamscan/manager.c b/clamscan/manager.c index bfdb4a155..b157a0335 100644 --- a/clamscan/manager.c +++ b/clamscan/manager.c @@ -243,16 +243,6 @@ int scanmanager(const struct optstruct *opt) else limits.maxreclevel = 8; - if(opt_check(opt, "max-mail-recursion")) - limits.maxmailrec = atoi(opt_arg(opt, "max-mail-recursion")); - else - limits.maxmailrec = 64; - - if(opt_check(opt, "max-ratio")) - limits.maxratio = atoi(opt_arg(opt, "max-ratio")); - else - limits.maxratio = 250; - /* set options */ if(opt_check(opt, "disable-archive") || opt_check(opt, "no-archive")) @@ -266,9 +256,6 @@ int scanmanager(const struct optstruct *opt) if(opt_check(opt, "block-encrypted")) options |= CL_SCAN_BLOCKENCRYPTED; - if(opt_check(opt, "block-max")) - options |= CL_SCAN_BLOCKMAX; - if(opt_check(opt, "no-pe")) options &= ~CL_SCAN_PE; else diff --git a/libclamav/autoit.c b/libclamav/autoit.c index 81f9d1ac4..cb280bbba 100644 --- a/libclamav/autoit.c +++ b/libclamav/autoit.c @@ -192,7 +192,7 @@ static int ea05(int desc, cli_ctx *ctx, char *tmpd) { for (i=0; i<16; i++) m4sum += buf[i]; - while((ret=cli_checklimits("autoit", ctx, 0, 0, 0))==CL_CONTINUE) { + while((ret=cli_checklimits("autoit", ctx, 0, 0, 0))==CL_CLEAN) { buf = b; if (cli_readn(desc, buf, 8)!=8) return CL_CLEAN; @@ -251,8 +251,7 @@ static int ea05(int desc, cli_ctx *ctx, char *tmpd) { cli_dbgmsg("autoit: ref chksum: %x\n", cli_readint32((char *)buf+9) ^ 0xc3d2); - if((ret=cli_checklimits("autoit", ctx, UNP.csize, 0, 0))!=CL_CONTINUE) { - if(ret==CL_VIRUS) return ret; + if(cli_checklimits("autoit", ctx, UNP.csize, 0, 0)!=CL_CLEAN) { lseek(desc, UNP.csize, SEEK_CUR); continue; } @@ -276,9 +275,8 @@ static int ea05(int desc, cli_ctx *ctx, char *tmpd) { if(!(UNP.usize = be32_to_host(*(uint32_t *)(buf+4)))) UNP.usize = UNP.csize; /* only a specifically crafted or badly corrupted sample should land here */ - if((ret=cli_checklimits("autoit", ctx, UNP.usize, 0, 0))!=CL_CONTINUE) { + if(cli_checklimits("autoit", ctx, UNP.usize, 0, 0)!=CL_CLEAN) { free(buf); - if(ret==CL_VIRUS) return ret; continue; } @@ -492,7 +490,7 @@ static int ea06(int desc, cli_ctx *ctx, char *tmpd) { /* buf+=0x10; */ lseek(desc, 16, SEEK_CUR); /* for now we just skip the garbage */ - while((ret=cli_checklimits("cli_autoit", ctx, 0, 0, 0))==CL_CONTINUE) { + while((ret=cli_checklimits("cli_autoit", ctx, 0, 0, 0))==CL_CLEAN) { buf = b; if (cli_readn(desc, buf, 8)!=8) return CL_CLEAN; @@ -555,8 +553,7 @@ static int ea06(int desc, cli_ctx *ctx, char *tmpd) { cli_dbgmsg("autoit: advertised uncompressed size %x\n", cli_readint32((char *)buf+5) ^ 0x87bc); cli_dbgmsg("autoit: ref chksum: %x\n", cli_readint32((char *)buf+9) ^ 0xa685); - if((ret=cli_checklimits("autoit", ctx, UNP.csize, 0, 0))!=CL_CONTINUE) { - if(ret==CL_VIRUS) return ret; + if(cli_checklimits("autoit", ctx, UNP.csize, 0, 0)!=CL_CLEAN) { lseek(desc, UNP.csize, SEEK_CUR); continue; } @@ -581,9 +578,8 @@ static int ea06(int desc, cli_ctx *ctx, char *tmpd) { if(!(UNP.usize = be32_to_host(*(uint32_t *)(buf+4)))) UNP.usize = UNP.csize; /* only a specifically crafted or badly corrupted sample should land here */ - if((ret=cli_checklimits("autoit", ctx, UNP.usize, 0, 0))!=CL_CONTINUE) { + if(cli_checklimits("autoit", ctx, UNP.usize, 0, 0)!=CL_CLEAN) { free(buf); - if(ret==CL_VIRUS) return ret; continue; } if (!(UNP.outputbuf = cli_malloc(UNP.usize))) { diff --git a/libclamav/blob.c b/libclamav/blob.c index e6d3e88e5..314e1e983 100644 --- a/libclamav/blob.c +++ b/libclamav/blob.c @@ -617,7 +617,7 @@ fileblobAddData(fileblob *fb, const unsigned char *data, size_t len) if(ctx) { int do_scan = 1; - if(ctx->limits) + if(ctx->limits && ctx->limits->maxfilesize) /* FIXMELIMITS */ if(fb->bytes_scanned >= ctx->limits->maxfilesize) do_scan = 0; diff --git a/libclamav/cab.c b/libclamav/cab.c index d1925412f..09715e963 100644 --- a/libclamav/cab.c +++ b/libclamav/cab.c @@ -49,7 +49,7 @@ #endif /* hard limits */ -#define CAB_FOLDER_LIMIT 5000 +#define CAB_FOLDER_LIMIT 5000 /* FIXMELIMITS */ #define CAB_FILE_LIMIT 5000 /* Cabinet format data structures */ diff --git a/libclamav/mbox.c b/libclamav/mbox.c index 0b71780c1..84f4a5480 100644 --- a/libclamav/mbox.c +++ b/libclamav/mbox.c @@ -1991,22 +1991,17 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re cli_dbgmsg("in parseEmailBody, %u files saved so far\n", mctx->files); - if(limits) { - if(limits->maxmailrec) { + if(limits) { /* FIXMELIMITS */ + if(limits->maxreclevel) { const cli_ctx *ctx = mctx->ctx; /* needed for BLOCKMAX :-( */ /* * This is approximate */ - if(recursion_level > limits->maxmailrec) { + if(recursion_level > limits->maxreclevel) { cli_warnmsg("parseEmailBody: hit maximum recursion level (%u)\n", recursion_level); - if(BLOCKMAX) { - if(ctx->virname) - *ctx->virname = "MIME.RecursionLimit"; - return VIRUS; - } else - return MAXREC; + return MAXREC; } } if(limits->maxfiles && (mctx->files >= limits->maxfiles)) { diff --git a/libclamav/msexpand.c b/libclamav/msexpand.c index ba638d5e8..e81277431 100644 --- a/libclamav/msexpand.c +++ b/libclamav/msexpand.c @@ -108,11 +108,8 @@ int cli_msexpand(int fd, int ofd, cli_ctx *ctx) cli_dbgmsg("MSEXPAND: File size from header: %u\n", hdr.fsize); - if((ret=cli_checklimits("MSEXPAND", ctx, hdr.fsize, 0, 0))!=CL_CONTINUE) { - if(ret==CL_VIRUS) return ret; - hdr.fsize = (ctx->limits->maxfilesize > ctx->limits->maxscansize-ctx->scansize) ? ctx->limits->maxscansize-ctx->scansize : ctx->limits->maxfilesize; - cli_dbgmsg("MSEXPAND: Only extracting first %u bytes\n", hdr.fsize); /* may extract up to 2kB more */ - } + if(cli_checklimits("MSEXPAND", ctx, hdr.fsize, 0, 0)!=CL_CLEAN) + return CL_SUCCESS; while(1) { diff --git a/libclamav/nsis/nulsft.c b/libclamav/nsis/nulsft.c index ad84a0a2d..7375a61a9 100644 --- a/libclamav/nsis/nulsft.c +++ b/libclamav/nsis/nulsft.c @@ -534,15 +534,8 @@ int cli_scannulsft(int desc, cli_ctx *ctx, off_t offset) { do { ret = cli_nsis_unpack(&nsist, ctx); - if(ret != CL_SUCCESS) { - if(ret == CL_EMAXSIZE) { - if(BLOCKMAX) { - *ctx->virname = "NSIS.ExceededFileSize"; - ret=CL_VIRUS; - } else { - ret = nsist.solid ? CL_BREAK : CL_SUCCESS; - } - } + if(ret == CL_EMAXSIZE) { + ret = nsist.solid ? CL_BREAK : CL_SUCCESS; } else { cli_dbgmsg("NSIS: Successully extracted file #%u\n", nsist.fno); lseek(nsist.ofd, 0, SEEK_SET); diff --git a/libclamav/others.c b/libclamav/others.c index 55eec6e86..f86e1998c 100644 --- a/libclamav/others.c +++ b/libclamav/others.c @@ -196,65 +196,62 @@ const char *cl_strerror(int clerror) } } +unsigned long cli_getsizelimit(cli_ctx *ctx, unsigned long needed) { + if(!ctx || ! ctx->limits) + return needed; + if(needed > ctx->limits->maxfilesize) + needed = ctx->limits->maxfilesize; + if(needed > ctx->limits->maxscansize-ctx->scansize) + needed = ctx->limits->maxscansize-ctx->scansize; + return needed; +} + int cli_checklimits(const char *who, cli_ctx *ctx, unsigned long need1, unsigned long need2, unsigned long need3) { int ret = CL_SUCCESS; unsigned long needed; /* if called without limits, go on, unpack, scan */ - if(!ctx || !ctx->limits) return CL_SUCCESS; - - /* check if we have limits on the number of files */ - /* FIMMELIMITS: this only makes sense in updatelimits */ - if(ctx->limits->maxfiles && ctx->scanned>=ctx->limits->maxfiles) { - cli_dbgmsg("%s: files limit reached (max: %u)\n", who, ctx->maxfiles); - return CL_EMAXFILES; - } + if(!ctx || !ctx->limits) return CL_CLEAN; needed = (need1>need2)?need1:need2; needed = (needed>need3)?needed:need3; /* if we have global scan limits */ - if(ctx->limits->maxscansize) { + if(needed && ctx->limits->maxscansize) { /* if the remaining scansize is too small... */ if(ctx->limits->maxscansize-ctx->scansizelimits->maxscansize, ctx->scansize, needed); - /* ... we return INFECTED only upon request */ - if(BLOCKMAX) { - *ctx->virname = "Archive.ExceededScanSize"; - return CL_VIRUS; - } - /* ... otherwise we tell the caller to skip this file */ ret = CL_EMAXSIZE; } } /* if we have per-file size limits, and we are overlimit... */ - if(ctx->limits->maxfilesize && ctx->limits->maxfilesizelimits->maxfilesize && ctx->limits->maxfilesizelimits->maxfilesize, needed); - /* ... we return INFECTED only upon request */ - if(BLOCKMAX) { - *ctx->virname = "Archive.ExceededFileSize"; - return CL_VIRUS; - } - /* ... otherwise we tell the caller to skip this file */ ret = CL_EMAXSIZE; } + + if(ctx->limits->maxfiles && ctx->scannedfiles>=ctx->limits->maxfiles) { + cli_dbgmsg("%s: files limit reached (max: %u)\n", who, ctx->limits->maxfiles); + return CL_EMAXFILES; + } return ret; } -int cli_updatelimits(cli_ctx *ctx, unsigned long need) { - int ret; +int cli_updatelimits(cli_ctx *ctx, unsigned long needed) { + /* FIXMELIMITS: + * we enter here via magicscan only + * magiscan callers should check for !CL_CLEAN instead of CL_VIRUS + */ - if((ret=cli_checklimits(ctx, need, 0, 0))==CL_SUCCESS) { - /* update counter */ - ctx->scanned++; - /* update the remaining scanzise */ - ctx->scansize+=needed; - if(ctx->scansize > ctx->limits->maxscansize) - ctx->scansize = ctx->limits->maxscansize; - } + ctx->scannedfiles++; + ctx->scansize+=needed; + if(ctx->scansize > ctx->limits->maxscansize) + ctx->scansize = ctx->limits->maxscansize; - return ret; + return cli_checklimits("updatelimits", ctx, needed, 0, 0); } unsigned char *cli_md5digest(int desc) diff --git a/libclamav/others.h b/libclamav/others.h index da5ac16b2..b5e21aa09 100644 --- a/libclamav/others.h +++ b/libclamav/others.h @@ -83,7 +83,7 @@ typedef struct { unsigned long scansize; unsigned int options; unsigned int recursion; - unsigned int scanned; + unsigned int scannedfiles; unsigned int found_possibly_unwanted; struct cli_dconf *dconf; } cli_ctx; @@ -97,7 +97,7 @@ typedef struct { #define SCAN_ELF (ctx->options & CL_SCAN_ELF) #define SCAN_ALGO (ctx->options & CL_SCAN_ALGORITHMIC) #define DETECT_ENCRYPTED (ctx->options & CL_SCAN_BLOCKENCRYPTED) -#define BLOCKMAX (ctx->options & CL_SCAN_BLOCKMAX) +/* #define BLOCKMAX (ctx->options & CL_SCAN_BLOCKMAX) */ #define DETECT_BROKEN (ctx->options & CL_SCAN_BLOCKBROKEN) /* based on macros from A. Melnikoff */ @@ -233,5 +233,5 @@ int cli_bitset_set(bitset_t *bs, unsigned long bit_offset); int cli_bitset_test(bitset_t *bs, unsigned long bit_offset); int cli_checklimits(const char *, cli_ctx *, unsigned long, unsigned long, unsigned long); int cli_updatelimits(cli_ctx *, unsigned long); - +unsigned long cli_getsizelimit(cli_ctx *, unsigned long); #endif diff --git a/libclamav/pdf.c b/libclamav/pdf.c index 7a92185c8..a94562918 100644 --- a/libclamav/pdf.c +++ b/libclamav/pdf.c @@ -195,7 +195,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx) /* * The body section consists of a sequence of indirect objects */ - while((p < xrefstart) && (rc == CL_CLEAN) && + while((p < xrefstart) && ((rc=cli_checklimits("cli_pdf", ctx, 0, 0, 0))==CL_CLEAN) && ((q = pdf_nextobject(p, bytesleft)) != NULL)) { int is_ascii85decode, is_flatedecode, fout, len, has_cr; /*int object_number, generation_number;*/ @@ -492,11 +492,6 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx) free(md5digest); cli_dbgmsg("cli_pdf: extracted file %u to %s\n", ++files, fullname); - - if((ret=cli_checklimits("cli_pdf", ctx, 0, 0, 0))!=CL_CONTINUE) { - /* Bug 698 */ - rc = ret; - } } munmap(buf, size); @@ -609,7 +604,8 @@ flatedecode(unsigned char *buf, off_t len, int fout, const cli_ctx *ctx) } nbytes += written; - if((ret=cli_checklimits("cli_pdf", ctx, nbytes, 0, 0))!=CL_CONTINUE) { + if((ret=cli_checklimits("cli_pdf", ctx, nbytes, 0, 0))!=CL_CLEAN) { + /* FIXMELIMITS */ inflateEnd(&stream); return ret; } diff --git a/libclamav/pe.c b/libclamav/pe.c index e32ca190d..9350fbb01 100644 --- a/libclamav/pe.c +++ b/libclamav/pe.c @@ -85,12 +85,7 @@ if(ctx->limits && ctx->limits->maxfilesize && (CHK) > ctx->limits->maxfilesize) { \ cli_dbgmsg(NAME": Sizes exceeded (%lu > %lu)\n", (unsigned long)(CHK), (unsigned long)ctx->limits->maxfilesize); \ free(exe_sections); \ - if(BLOCKMAX) { \ - *ctx->virname = "PE."NAME".ExceededFileSize"; \ - return CL_VIRUS; \ - } else { \ - return CL_CLEAN; \ - } \ + return CL_CLEAN; \ } #define CLI_UNPTEMP(NAME,FREEME) \ @@ -124,12 +119,6 @@ if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { \ close(ndesc); \ unlink(tempfile); \ cli_dbgmsg("PESpin: Size exceeded\n"); \ - if(BLOCKMAX) { \ - free(tempfile); \ - free(exe_sections); \ - *ctx->virname = "PE.Pespin.ExceededFileSize"; \ - return CL_VIRUS; \ - } \ free(tempfile); \ break; \ diff --git a/libclamav/scanners.c b/libclamav/scanners.c index 1dc5277e7..ded040b9a 100644 --- a/libclamav/scanners.c +++ b/libclamav/scanners.c @@ -120,10 +120,10 @@ static int cli_unrar_scanmetadata(int desc, unrar_metadata_t *metadata, cli_ctx *sfx_check = metadata->crc; } - cli_dbgmsg("RAR: %s, crc32: 0x%x, encrypted: %u, compressed: %u, normal: %u, method: %u, ratio: %u (max: %u)\n", + cli_dbgmsg("RAR: %s, crc32: 0x%x, encrypted: %u, compressed: %u, normal: %u, method: %u, ratio: %u\n", metadata->filename, metadata->crc, metadata->encrypted, (unsigned int) metadata->pack_size, (unsigned int) metadata->unpack_size, metadata->method, - metadata->pack_size ? (unsigned int) (metadata->unpack_size / metadata->pack_size) : 0, ctx->limits ? ctx->limits->maxratio : 0); + metadata->pack_size ? (unsigned int) (metadata->unpack_size / metadata->pack_size) : 0); /* Scan metadata */ mdata = ctx->engine->rar_mlist; @@ -146,7 +146,7 @@ static int cli_unrar_scanmetadata(int desc, unrar_metadata_t *metadata, cli_ctx if(mdata->fileno && mdata->fileno != files) continue; - if(mdata->maxdepth && ctx->arec > mdata->maxdepth) + if(mdata->maxdepth && ctx->recursion > mdata->maxdepth) /* FIXMELIMITS */ continue; /* TODO add support for regex */ @@ -176,42 +176,6 @@ static int cli_unrar_scanmetadata(int desc, unrar_metadata_t *metadata, cli_ctx return ret; } -static int cli_unrar_checklimits(const cli_ctx *ctx, const unrar_metadata_t *metadata, unsigned int files) -{ - if(ctx->limits) { - if(ctx->limits->maxratio && metadata->unpack_size && metadata->pack_size) { - if(metadata->unpack_size / metadata->pack_size >= ctx->limits->maxratio) { - cli_dbgmsg("RAR: Max ratio reached (%u, max: %u)\n", (unsigned int) (metadata->unpack_size / metadata->pack_size), ctx->limits->maxratio); - if(BLOCKMAX) { - *ctx->virname = "Oversized.RAR"; - return CL_VIRUS; - } - return CL_EMAXSIZE; - } - } - - if(ctx->limits->maxfilesize && (metadata->unpack_size > ctx->limits->maxfilesize)) { - cli_dbgmsg("RAR: %s: Size exceeded (%lu, max: %lu)\n", metadata->filename, (unsigned long int) metadata->unpack_size, ctx->limits->maxfilesize); - if(BLOCKMAX) { - *ctx->virname = "RAR.ExceededFileSize"; - return CL_VIRUS; - } - return CL_EMAXSIZE; - } - - if(ctx->limits->maxfiles && (files > ctx->limits->maxfiles)) { - cli_dbgmsg("RAR: Files limit reached (max: %u)\n", ctx->limits->maxfiles); - if(BLOCKMAX) { - *ctx->virname = "RAR.ExceededFilesLimit"; - return CL_VIRUS; - } - return CL_EMAXFILES; - } - } - - return CL_SUCCESS; -} - static int cli_scanrar(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_check) { int ret = CL_CLEAN; @@ -257,17 +221,11 @@ static int cli_scanrar(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_c ret = CL_ERAR; break; } - ret = cli_unrar_checklimits(ctx, rar_state.metadata_tail, rar_state.file_count); - if(ret && ret != CL_VIRUS) { + if((ret=cli_checklimits("RAR", ctx, rar_state.metadata_tail->unpack_size, rar_state.metadata_tail->pack_size, 0)!=CL_CLEAN)) { free(rar_state.file_header->filename); free(rar_state.file_header); ret = CL_CLEAN; continue; - } else if(ret == CL_VIRUS) { - /* needed since we didn't reach unrar_extract_next to clean this up*/ - free(rar_state.file_header->filename); - free(rar_state.file_header); - break; } ret = unrar_extract_next(&rar_state,dir); if(ret == UNRAR_OK) @@ -323,46 +281,6 @@ static int cli_scanrar(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_c } #endif /* ENABLE_UNRAR */ -static int cli_unarj_checklimits(const cli_ctx *ctx, const arj_metadata_t *metadata, unsigned int files) -{ - if (ctx->limits) { - if (ctx->limits->maxfilesize && (metadata->orig_size > ctx->limits->maxfilesize)) { - cli_dbgmsg("ARJ: %s: Size exceeded (%lu, max: %lu)\n", metadata->filename ? metadata->filename : "(none)", - (unsigned long int) metadata->orig_size, ctx->limits->maxfilesize); - if (BLOCKMAX) { - *ctx->virname = "ARJ.ExceededFileSize"; - return CL_VIRUS; - } - return CL_EMAXSIZE; - } - - if (ctx->limits->maxratio && metadata->orig_size && metadata->comp_size) { - if (metadata->orig_size / metadata->comp_size >= ctx->limits->maxratio) { - cli_dbgmsg("ARJ: Max ratio reached (%u, max: %u)\n", (unsigned int) (metadata->orig_size / metadata->comp_size), ctx->limits->maxratio); - if (ctx->limits->maxfilesize && (metadata->orig_size <= ctx->limits->maxfilesize)) { - cli_dbgmsg("ARJ: Ignoring ratio limit (file size doesn't hit limits)\n"); - } else { - if(BLOCKMAX) { - *ctx->virname = "Oversized.ARJ"; - return CL_VIRUS; - } - } - } - } - - if(ctx->limits->maxfiles && (files > ctx->limits->maxfiles)) { - cli_dbgmsg("ARJ: Files limit reached (max: %u)\n", ctx->limits->maxfiles); - if (BLOCKMAX) { - *ctx->virname = "ARJ.ExceededFilesLimit"; - return CL_VIRUS; - } - return CL_EMAXFILES; - } - } - - return CL_SUCCESS; -} - static int cli_scanarj(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_check) { int ret = CL_CLEAN, rc; @@ -399,9 +317,10 @@ static int cli_scanarj(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_c if (ret != CL_SUCCESS) { break; } - ret = cli_unarj_checklimits(ctx, &metadata, file_count); - if (ret == CL_VIRUS) { - break; + if ((ret = cli_checklimits("ARJ", ctx, metadata.orig_size, metadata.comp_size, 0))!=CL_CLEAN) { + /* FIXMELIMITS: is this correct, shall I free something? */ + ret = CL_SUCCESS; + continue; } ret = cli_unarj_extract_file(desc, dir, &metadata); if (metadata.ofd >= 0) { @@ -471,15 +390,8 @@ static int cli_scangzip(int desc, cli_ctx *ctx) while((bytes = gzread(gd, buff, FILEBUFF)) > 0) { size += bytes; - if(ctx->limits) - if(ctx->limits->maxfilesize && (size + FILEBUFF > ctx->limits->maxfilesize)) { - cli_dbgmsg("GZip: Size exceeded (stopped at %ld, max: %ld)\n", size, ctx->limits->maxfilesize); - if(BLOCKMAX) { - *ctx->virname = "GZip.ExceededFileSize"; - ret = CL_VIRUS; - } - break; - } + if(cli_checklimits("GZip", ctx, size + FILEBUFF, 0, 0)!=CL_CLEAN) + break; if(cli_writen(fd, buff, bytes) != bytes) { cli_dbgmsg("GZip: Can't write to file.\n"); @@ -585,15 +497,8 @@ static int cli_scanbzip(int desc, cli_ctx *ctx) while((bytes = BZ2_bzRead(&bzerror, bfd, buff, FILEBUFF)) > 0) { size += bytes; - if(ctx->limits) - if(ctx->limits->maxfilesize && (size + FILEBUFF > ctx->limits->maxfilesize)) { - cli_dbgmsg("Bzip: Size exceeded (stopped at %ld, max: %ld)\n", size, ctx->limits->maxfilesize); - if(BLOCKMAX) { - *ctx->virname = "BZip.ExceededFileSize"; - ret = CL_VIRUS; - } - break; - } + if(cli_checklimits("Bzip", ctx, size + FILEBUFF, 0, 0)!=CL_CLEAN) + break; if(cli_writen(fd, buff, bytes) != bytes) { cli_dbgmsg("Bzip: Can't write to file.\n"); @@ -696,25 +601,8 @@ static int cli_scanmscab(int desc, cli_ctx *ctx, off_t sfx_offset) for(file = cab.files; file; file = file->next) { files++; - if(ctx->limits && ctx->limits->maxfilesize && (file->length > ctx->limits->maxfilesize)) { - cli_dbgmsg("CAB: %s: Size exceeded (%u, max: %lu)\n", file->name, file->length, ctx->limits->maxfilesize); - if(BLOCKMAX) { - *ctx->virname = "CAB.ExceededFileSize"; - cab_free(&cab); - return CL_VIRUS; - } + if(cli_checklimits("CAB", ctx, file->length, 0, 0)!=CL_CLEAN) continue; - } - - if(ctx->limits && ctx->limits->maxfiles && (files > ctx->limits->maxfiles)) { - cli_dbgmsg("CAB: Files limit reached (max: %u)\n", ctx->limits->maxfiles); - cab_free(&cab); - if(BLOCKMAX) { - *ctx->virname = "CAB.ExceededFilesLimit"; - return CL_VIRUS; - } - return CL_CLEAN; - } tempname = cli_gentemp(NULL); cli_dbgmsg("CAB: Extracting file %s to %s, size %u\n", file->name, tempname, file->length); @@ -1160,7 +1048,7 @@ static int cli_scantar(int desc, cli_ctx *ctx, unsigned int posix) return CL_ETMPDIR; } - if((ret = cli_untar(dir, desc, posix, ctx->limits))) + if((ret = cli_untar(dir, desc, posix, ctx))) cli_dbgmsg("Tar: %s\n", cl_strerror(ret)); else ret = cli_scandir(dir, ctx); @@ -1473,7 +1361,7 @@ static int cli_scanmail(int desc, cli_ctx *ctx) int ret; - cli_dbgmsg("Starting cli_scanmail(), mrec == %u, arec == %u\n", ctx->mrec, ctx->arec); + cli_dbgmsg("Starting cli_scanmail(), recursion = %u\n", ctx->recursion); /* generate the temporary directory */ dir = cli_gentemp(NULL); @@ -1523,11 +1411,8 @@ static int cli_scanembpe(int desc, cli_ctx *ctx) while((bytes = read(desc, buff, sizeof(buff))) > 0) { size += bytes; - if(ctx->limits && ctx->limits->maxfilesize && (size + sizeof(buff) > ctx->limits->maxfilesize)) { - cli_dbgmsg("cli_scanembpe: Size exceeded (stopped at %lu, max: %lu)\n", size, ctx->limits->maxfilesize); - /* BLOCKMAX should be ignored here */ + if(cli_checklimits("cli_scanembpe", ctx, size + sizeof(buff), 0, 0)!=CL_CLEAN) break; - } if(cli_writen(fd, buff, bytes) != bytes) { cli_dbgmsg("cli_scanembpe: Can't write to temporary file\n"); @@ -1684,7 +1569,7 @@ static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type, uint8_t typercg) } } - ret == CL_TYPE_MAIL ? ctx->mrec++ : ctx->arec++; + ctx->recursion++; if(nret != CL_VIRUS) switch(ret) { case CL_TYPE_HTML: @@ -1700,7 +1585,7 @@ static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type, uint8_t typercg) default: break; } - ret == CL_TYPE_MAIL ? ctx->mrec-- : ctx->arec--; + ctx->recursion--; ret = nret; } @@ -1746,22 +1631,10 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx) return ret; } - if(SCAN_ARCHIVE && ctx->limits && ctx->limits->maxreclevel) - if(ctx->arec > ctx->limits->maxreclevel) { - cli_dbgmsg("Archive recursion limit exceeded (arec == %u).\n", ctx->arec); - if(BLOCKMAX) { - *ctx->virname = "Archive.ExceededRecursionLimit"; - return CL_VIRUS; - } - return CL_CLEAN; - } - - if(SCAN_MAIL) - if(ctx->mrec > MAX_MAIL_RECURSION) { - cli_dbgmsg("Mail recursion level exceeded (mrec == %u).\n", ctx->mrec); - /* return CL_EMAXREC; */ - return CL_CLEAN; - } + if((SCAN_MAIL || SCAN_ARCHIVE) && ctx->limits && ctx->limits->maxreclevel && ctx->recursion > ctx->limits->maxreclevel) { + cli_dbgmsg("Archive recursion limit exceeded (level = %u).\n", ctx->recursion); + return CL_CLEAN; + } lseek(desc, 0, SEEK_SET); type = cli_filetype2(desc, ctx->engine); @@ -1773,7 +1646,7 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx) lseek(desc, 0, SEEK_SET); } - type == CL_TYPE_MAIL ? ctx->mrec++ : ctx->arec++; + ctx->recursion++; switch(type) { case CL_TYPE_IGNORED: @@ -1840,7 +1713,7 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx) break; case CL_TYPE_RTF: - if(DCONF_DOC & DOC_CONF_RTF) + if(SCAN_ARCHIVE && (DCONF_DOC & DOC_CONF_RTF)) ret = cli_scanrtf(desc, ctx); break; @@ -1927,7 +1800,7 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx) break; } - type == CL_TYPE_MAIL ? ctx->mrec-- : ctx->arec--; + ctx->recursion--; if(type == CL_TYPE_ZIP && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) { if(sb.st_size > 1048576) { @@ -1942,7 +1815,7 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx) return CL_VIRUS; } - ctx->arec++; + ctx->recursion++; lseek(desc, 0, SEEK_SET); switch(type) { /* Due to performance reasons all executables were first scanned @@ -1956,7 +1829,7 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx) default: break; } - ctx->arec--; + ctx->recursion--; if(ret == CL_EFORMAT) { cli_dbgmsg("Descriptor[%d]: %s\n", desc, cl_strerror(CL_EFORMAT)); @@ -1969,18 +1842,20 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx) int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options) { cli_ctx ctx; - cl_limits l_limits; + struct cl_limits l_limits; int rc; memset(&ctx, '\0', sizeof(cli_ctx)); ctx.engine = engine; ctx.virname = virname; - ctx.limits = &l_limits; ctx.scanned = scanned; ctx.options = options; ctx.found_possibly_unwanted = 0; ctx.dconf = (struct cli_dconf *) engine->dconf; - memcpy(&l_limits, limits, sizeof(struct cl_limits)); + if (limits) { + ctx.limits = &l_limits; + memcpy(&l_limits, limits, sizeof(struct cl_limits)); + } rc = cli_magic_scandesc(desc, &ctx); if(rc == CL_CLEAN && ctx.found_possibly_unwanted) diff --git a/libclamav/sis.c b/libclamav/sis.c index 4a797e0b8..dddbfdc89 100644 --- a/libclamav/sis.c +++ b/libclamav/sis.c @@ -453,10 +453,7 @@ static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) { cli_dbgmsg("\tSkipping empty file\n"); continue; } - if (ctx->limits && ctx->limits->maxfilesize && lens[j] > ctx->limits->maxfilesize) { - cli_dbgmsg("\tSkipping file due to size limit (%u, max: %lu)\n", lens[j], ctx->limits->maxfilesize); - continue; - } + if (cli_checklimits("sis", ctx,lens[j], 0, 0)!=CL_CLEAN) continue; cli_dbgmsg("\tUnpacking lang#%d - ptr:%x csize:%x osize:%x\n", j, ptrs[j], lens[j], olens[j]); if (!(comp=cli_malloc(lens[j]))) { cli_dbgmsg("\tOOM\n"); @@ -471,15 +468,13 @@ static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) { continue; } if (compd) { - olen = (olens[j]<=lens[j]*3 || (ctx->limits && ctx->limits->maxfilesize && olens[j] > ctx->limits->maxfilesize)) ? lens[j]*3 : olens[j]; - if (ctx->limits && ctx->limits->maxfilesize && olen > ctx->limits->maxfilesize) { - if (olens[j] < ctx->limits->maxfilesize) - olen = olens[j]; - else { - cli_dbgmsg("\tSkipping file due to size limit (%u, max: %lu)\n", (unsigned int)olen, ctx->limits->maxfilesize); - free(comp); - continue; - } + if (olens[j]<=lens[j]*3 && cli_checklimits("sis", ctx, lens[j]*3, 0, 0)==CL_CLEAN) + olen=lens[j]*3; + else if (cli_checklimits("sis", ctx, olens[j], 0, 0)==CL_CLEAN) + olen=olens[j]; + else { + free(comp); + continue; } if (!(decomp=cli_malloc(olen))) { @@ -524,12 +519,6 @@ static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) { } close(fd); umped++; - if (ctx->limits && umped > ctx->limits->maxfiles) { - cli_dbgmsg("NSIS: Files limit reached (max: %u)\n", ctx->limits->maxfiles); - free(ptrs); - free(alangs); - return CL_EMAXFILES; - } } fseek(f,fpos,SEEK_SET); } @@ -726,10 +715,7 @@ static int real_scansis9x(FILE *f, cli_ctx *ctx, const char *tmpd) { fseek(s->f, -(long)s->sleft, SEEK_CUR); s->sleft = s->smax = 0; - if (ctx->limits && ctx->limits->maxfilesize && ALIGN4(s->fsize[s->level]) > ctx->limits->maxfilesize) { - cli_dbgmsg("SIS: Skipping file due to size limit (%u, max: %lu)\n", ALIGN4(s->fsize[s->level]), ctx->limits->maxfilesize); - break; - } + if (cli_checklimits("sis", ctx,ALIGN4(s->fsize[s->level]), 0, 0)!=CL_CLEAN) break; if (!(src=cli_malloc(ALIGN4(s->fsize[s->level])))) break; if (fread(src, ALIGN4(s->fsize[s->level]),1,s->f) != 1) { free(src); @@ -739,16 +725,15 @@ static int real_scansis9x(FILE *f, cli_ctx *ctx, const char *tmpd) { if(field) { /* compressed */ int zresult; - uusize = (usize<=s->fsize[s->level]*3 || (ctx->limits && ctx->limits->maxfilesize && uusize > ctx->limits->maxfilesize)) ? s->fsize[s->level]*3 : usize; - if (ctx->limits && ctx->limits->maxfilesize && uusize > ctx->limits->maxfilesize) { - if (usize < ctx->limits->maxfilesize) - uusize = usize; - else { - cli_dbgmsg("\tSkipping file due to size limit (%u, max: %lu)\n", (unsigned int)uusize, ctx->limits->maxfilesize); - free(src); - break; - } + if (usize<=s->fsize[s->level]*3 && cli_checklimits("sis", ctx, s->fsize[s->level]*3, 0, 0)==CL_CLEAN) + uusize=s->fsize[s->level]*3; + else if (cli_checklimits("sis", ctx, usize, 0, 0)==CL_CLEAN) + uusize=usize; + else { + free(src); + break; } + if (!(dst=cli_malloc(uusize))) { free(src); break; diff --git a/libclamav/unsp.c b/libclamav/unsp.c index 3581f4a97..9e83cb8cb 100644 --- a/libclamav/unsp.c +++ b/libclamav/unsp.c @@ -142,9 +142,9 @@ uint32_t unspack(char *start_of_stuff, char *dest, cli_ctx *ctx, uint32_t rva, u i = allocsz; c = (tre+i)&0xff; tablesz = ((0x300<limits && ctx->limits->maxfilesize && tablesz > ctx->limits->maxfilesize) { + + if(cli_checklimits("nspack", ctx, tablesz, 0, 0)!=CL_CLEAN) return 1; /* Should be ~15KB, if it's so big it's prolly just not nspacked */ - } cli_dbgmsg("unsp: table size = %d\n", tablesz); if (!(table = cli_malloc(tablesz))) return 1; diff --git a/libclamav/untar.c b/libclamav/untar.c index 8af9a79c5..bd3b5457a 100644 --- a/libclamav/untar.c +++ b/libclamav/untar.c @@ -61,9 +61,9 @@ octal(const char *str) } int -cli_untar(const char *dir, int desc, unsigned int posix, const struct cl_limits *limits) +cli_untar(const char *dir, int desc, unsigned int posix, cli_ctx *ctx) { - int size = 0; + int size = 0, ret; int in_block = 0; unsigned int files = 0; char fullname[NAME_MAX + 1]; @@ -103,11 +103,8 @@ cli_untar(const char *dir, int desc, unsigned int posix, const struct cl_limits if(block[0] == '\0') /* We're done */ break; - - if(limits && limits->maxfiles && (files >= limits->maxfiles)) { - cli_dbgmsg("cli_untar: number of files exceeded %u\n", limits->maxfiles); - return CL_CLEAN; - } + if((ret=cli_checklimits("cli_untar", ctx, 0, 0, 0))!=CL_CLEAN) + return ret; /* Notice assumption that BLOCKSIZE > 262 */ if(posix) { @@ -176,8 +173,7 @@ cli_untar(const char *dir, int desc, unsigned int posix, const struct cl_limits return CL_EFORMAT; } cli_dbgmsg("cli_untar: size = %d\n", size); - if(limits && limits->maxfilesize && ((unsigned int)size > limits->maxfilesize)) { - cli_dbgmsg("cli_untar: size exceeded %d bytes\n", size); + if((ret=cli_checklimits("cli_untar", ctx, size, 0, 0))!=CL_CLEAN) { skipEntry++; } @@ -250,7 +246,7 @@ cli_untar(const char *dir, int desc, unsigned int posix, const struct cl_limits } if (size == 0) in_block = 0; - } + } if(outfile) return fclose(outfile); diff --git a/libclamav/untar.h b/libclamav/untar.h index cb0dcfae4..8985906ee 100644 --- a/libclamav/untar.h +++ b/libclamav/untar.h @@ -34,4 +34,12 @@ * First draft * */ -int cli_untar(const char *dir, int desc, unsigned int posix, const struct cl_limits *limits); + +#ifndef __UNTAR_H +#define __UNTAR_H + +#include "others.h" + +int cli_untar(const char *dir, int desc, unsigned int posix, cli_ctx *ctx); + +#endif diff --git a/libclamav/unzip.c b/libclamav/unzip.c index 7ef4ecdd4..692f1fb5c 100644 --- a/libclamav/unzip.c +++ b/libclamav/unzip.c @@ -93,11 +93,6 @@ static int unz(uint8_t *src, uint32_t csize, uint32_t usize, uint16_t method, ui } if(res==1) { if(ctx->limits && ctx->limits->maxfilesize && csize > ctx->limits->maxfilesize) { - if(BLOCKMAX) { - *ctx->virname = "Zip.ExceededFileSize"; - ret = CL_VIRUS; - break; - } cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", ctx->limits->maxfilesize); csize = ctx->limits->maxfilesize; } @@ -159,11 +154,6 @@ static int unz(uint8_t *src, uint32_t csize, uint32_t usize, uint16_t method, ui if(*avail_out!=sizeof(obuf)) { written+=sizeof(obuf)-(*avail_out); if(ctx->limits && ctx->limits->maxfilesize && written > ctx->limits->maxfilesize) { - if(BLOCKMAX) { - *ctx->virname = "Zip.ExceededFileSize"; - ret = CL_VIRUS; - break; - } cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", ctx->limits->maxfilesize); res = Z_STREAM_END; break; @@ -201,11 +191,6 @@ static int unz(uint8_t *src, uint32_t csize, uint32_t usize, uint16_t method, ui if(strm.avail_out!=sizeof(obuf)) { written+=sizeof(obuf)-strm.avail_out; if(ctx->limits && ctx->limits->maxfilesize && written > ctx->limits->maxfilesize) { - if(BLOCKMAX) { - *ctx->virname = "Zip.ExceededFileSize"; - ret = CL_VIRUS; - break; - } cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", ctx->limits->maxfilesize); res = BZ_STREAM_END; break; @@ -244,11 +229,6 @@ static int unz(uint8_t *src, uint32_t csize, uint32_t usize, uint16_t method, ui if(strm.avail_out!=sizeof(obuf)) { written+=sizeof(obuf)-strm.avail_out; if(ctx->limits && ctx->limits->maxfilesize && written > ctx->limits->maxfilesize) { - if(BLOCKMAX) { - *ctx->virname = "Zip.ExceededFileSize"; - ret = CL_VIRUS; - break; - } cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", ctx->limits->maxfilesize); res = 0; break; @@ -346,7 +326,7 @@ static unsigned int lhdr(uint8_t *zip, uint32_t zsize, unsigned int *fu, unsigne zip+=LH_flen; zsize-=LH_flen; - cli_dbgmsg("cli_unzip: lh - ZMDNAME:%d:%s:%u:%u:%u:%u:%u:%u\n", ((LH_flags & F_ENCR)==0), name, LH_usize, LH_csize, LH_crc32, LH_method, fc, ctx->arec); + cli_dbgmsg("cli_unzip: lh - ZMDNAME:%d:%s:%u:%u:%u:%u:%u:%u\n", ((LH_flags & F_ENCR)==0), name, LH_usize, LH_csize, LH_crc32, LH_method, fc, ctx->recursion); /* ZMDfmt virname:encrypted(0-1):filename(exact|*):usize(exact|*):csize(exact|*):crc32(exact|*):method(exact|*):fileno(exact|*):maxdepth(exact|*) */ while(meta && @@ -357,7 +337,7 @@ static unsigned int lhdr(uint8_t *zip, uint32_t zsize, unsigned int *fu, unsigne (meta->crc32 && meta->crc32 != LH_crc32) || (meta->method>0 && meta->method != LH_method) || (meta->fileno && meta->fileno != fc ) || - (meta->maxdepth && ctx->arec > meta->maxdepth) || + (meta->maxdepth && ctx->recursion > meta->maxdepth) || (meta->filename && strcmp(name, meta->filename)) /* TODO: use a regex */ ) ) meta = meta->next; @@ -401,10 +381,6 @@ static unsigned int lhdr(uint8_t *zip, uint32_t zsize, unsigned int *fu, unsigne return 0; } cli_dbgmsg("cli_unzip: lh - skipping encrypted file\n"); - } else if(ctx->limits && ctx->limits->maxratio > 0 && (usize / csize) >= ctx->limits->maxratio) { - *ctx->virname = "Oversized.Zip"; - *ret = CL_VIRUS; - return 0; } else *ret = unz(zip, csize, usize, LH_method, LH_flags, fu, ctx, tmpd); zip+=csize; zsize-=csize; @@ -561,11 +537,6 @@ int cli_unzip(int f, cli_ctx *ctx) { } } - if(ret == CL_EMAXFILES && BLOCKMAX) { - *ctx->virname = "Zip.ExceededFilesLimit"; - ret = CL_VIRUS; - } - munmap(map, fsize); if (!cli_leavetemps_flag) cli_rmdirs(tmpd); free(tmpd);