initial rewrite of limits

git-svn-id: file:///var/lib/svn/clamav-devel/branches/newlimits@3591 77e5149b-7576-45b1-b177-96237e5ba77b
This commit is contained in:
aCaB 2008-02-06 21:19:10 +00:00
parent b80ae27752
commit d91ab809a2
19 changed files with 121 additions and 351 deletions

View file

@ -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");
}

View file

@ -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},

View file

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

View file

@ -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))) {

View file

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

View file

@ -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 */

View file

@ -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)) {

View file

@ -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) {

View file

@ -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);

View file

@ -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->scansize<needed) {
/* ... we tell the caller to skip this file */
cli_dbgmsg("%s: scansize exceeded (initial: %u, remaining: %u, needed: %u)\n", who, ctx->limits->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->maxfilesize<needed) {
if(needed && ctx->limits->maxfilesize && ctx->limits->maxfilesize<needed) {
/* ... we tell the caller to skip this file */
cli_dbgmsg("%s: filesize exceeded (allowed: %u, needed: %u)\n", who, ctx->limits->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)

View file

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

View file

@ -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;
}

View file

@ -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; \

View file

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

View file

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

View file

@ -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<<c)+0x736)*sizeof(uint16_t);
if(ctx->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;

View file

@ -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);

View file

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

View file

@ -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);