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