clamscan: new flag --archive-verbose

This shows the archive member names (if known) when a virus is found.
When combined with -v it shows the archive member names while scanning too.
remotes/push_mirror/valgrind-mpool
Török Edvin 15 years ago
parent e86311ab4e
commit 248c2f4d9c
  1. 1
      clamscan/clamscan.c
  2. 122
      clamscan/manager.c
  3. 5
      libclamav/ishield.c
  4. 1
      libclamav/matcher.c
  5. 2
      shared/optparser.c

@ -195,6 +195,7 @@ void help(void)
mprintf(" --help -h Print this help screen\n");
mprintf(" --version -V Print version number\n");
mprintf(" --verbose -v Be verbose\n");
mprintf(" --archive-verbose -a Show filenames inside scanned archives\n");
mprintf(" --debug Enable libclamav's debug messages\n");
mprintf(" --quiet Only output error messages\n");
mprintf(" --stdout Write to stdout instead of stderr\n");

@ -120,12 +120,104 @@ static int checkaccess(const char *path, const char *username, int mode)
}
#endif
struct metachain {
char **chains;
unsigned lastadd;
unsigned lastvir;
unsigned level;
unsigned n;
};
static cl_error_t pre(int fd, const char *type, void *context)
{
struct metachain *c = context;
if (c) {
c->level++;
}
return CL_CLEAN;
}
static int print_chain(struct metachain *c, char *str, unsigned len)
{
unsigned i;
unsigned na = 0;
for (i=0;i<c->n-1;i++) {
unsigned int n = strlen(c->chains[i]);
if (na)
str[na++] = '!';
if (n + na + 2 > len)
break;
memcpy(str + na, c->chains[i], n);
na += n;
}
str[na] = '\0';
str[len-1] = '\0';
return i == c->n-1 ? 0 : 1;
}
static cl_error_t post(int fd, int result, const char *virname, void *context)
{
struct metachain *c = context;
if (c && c->n) {
char str[128];
int toolong = print_chain(c, str, sizeof(str));
if (c->level == c->lastadd && !virname)
free(c->chains[--c->n]);
if (virname && !c->lastvir)
c->lastvir = c->level;
}
if (c)
c->level--;
return CL_CLEAN;
}
static cl_error_t meta(const char* container_type, unsigned long fsize_container, const char *filename,
unsigned long fsize_real, int is_encrypted, unsigned int filepos_container, void *context)
{
int na = 0;
char prev[128];
struct metachain *c = context;
const char *type = !strncmp(container_type,"CL_TYPE_",8) ? container_type + 8 : container_type;
unsigned n = strlen(type) + 1 + strlen(filename) + 1;
char *chain;
char **chains;
int toolong;
if (!c)
return CL_CLEAN;
chain = malloc(n);
if (!chain)
return CL_CLEAN;
if (!strcmp(type, "ANY"))
snprintf(chain, n,"%s", filename);
else
snprintf(chain, n,"%s:%s", type, filename);
if (c->lastadd != c->level) {
n = c->n + 1;
chains = realloc(c->chains, n * sizeof(*chains));
if (!chains) {
free(chain);
return CL_CLEAN;
}
c->chains = chains;
c->n = n;
c->lastadd = c->level;
} else {
free(c->chains[c->n-1]);
}
c->chains[c->n-1] = chain;
toolong = print_chain(c, prev, sizeof(prev));
logg("*Scanning %s%s!%s\n", prev,toolong ? "..." : "", chain);
return CL_CLEAN;
}
static void scanfile(const char *filename, struct cl_engine *engine, const struct optstruct *opts, unsigned int options)
{
int ret = 0, fd, included, printclean = 1;
int ret = 0, fd, included, printclean = 1, i;
const struct optstruct *opt;
const char *virname;
struct stat sb;
struct metachain chain;
if((opt = optget(opts, "exclude"))->enabled) {
while(opt) {
@ -181,6 +273,14 @@ static void scanfile(const char *filename, struct cl_engine *engine, const struc
}
#endif
memset(&chain, 0, sizeof(chain));
if(optget(opts, "archive-verbose")->enabled) {
chain.chains = malloc(sizeof(*chain.chains));
if (chain.chains) {
chain.chains[0] = strdup(filename);
chain.n = 1;
}
}
logg("*Scanning %s\n", filename);
if((fd = safe_open(filename, O_RDONLY|O_BINARY)) == -1) {
@ -189,7 +289,16 @@ static void scanfile(const char *filename, struct cl_engine *engine, const struc
return;
}
if((ret = cl_scandesc(fd, &virname, &info.blocks, engine, options)) == CL_VIRUS) {
if((ret = cl_scandesc_callback(fd, &virname, &info.blocks, engine, options, &chain)) == CL_VIRUS) {
if(optget(opts, "archive-verbose")->enabled) {
if (chain.n > 1) {
char str[128];
int toolong = print_chain(&chain, str, sizeof(str));
logg("~%s%s!(%d)%s: %s FOUND\n", str, toolong ? "..." : "", chain.lastvir-1, chain.chains[chain.n-1], virname);
} else if (chain.lastvir)
logg("~%s!(%d): %s FOUND\n", filename, chain.lastvir-1, virname);
}
logg("~%s: %s FOUND\n", filename, virname);
info.files++;
info.ifiles++;
@ -207,6 +316,9 @@ static void scanfile(const char *filename, struct cl_engine *engine, const struc
info.errors++;
}
for (i=0;i<chain.n;i++)
free(chain.chains[i]);
free(chain.chains);
close(fd);
if(ret == CL_VIRUS && action)
@ -541,6 +653,12 @@ int scanmanager(const struct optstruct *opts)
return 2;
}
if(optget(opts, "archive-verbose")->enabled) {
cl_engine_set_clcb_meta(engine, meta);
cl_engine_set_clcb_pre_scan(engine, pre);
cl_engine_set_clcb_post_scan(engine, post);
}
/* set limits */
if((opt = optget(opts, "max-scansize"))->active) {

@ -343,6 +343,7 @@ int cli_scanishield(cli_ctx *ctx, off_t off, size_t sz) {
off_t coff = off;
struct IS_CABSTUFF c = { NULL, -1, 0, 0 };
fmap_t *map = *ctx->fmap;
unsigned fc = 0;
while(ret == CL_CLEAN) {
fname = fmap_need_offstr(map, coff, 2048);
@ -371,6 +372,10 @@ int cli_scanishield(cli_ctx *ctx, off_t off, size_t sz) {
) break;
cli_dbgmsg("ishield: @%lx found file %s (%s) - version %s - size %lu\n", (unsigned long int) coff, fname, path, version, (unsigned long int) fsize);
if(cli_matchmeta(ctx, fname, fsize, fsize, 0, fc++, 0, NULL) == CL_VIRUS) {
ret = CL_VIRUS;
break;
}
sz -= (data - fname) + fsize;
if(!strncasecmp(fname, "data", 4)) {

@ -824,6 +824,7 @@ int cli_matchmeta(cli_ctx *ctx, const char *fname, size_t fsizec, size_t fsizer,
if (ctx->engine && ctx->engine->cb_meta)
if (ctx->engine->cb_meta(cli_ftname(ctx->container_type), fsizec, fname, fsizer, encrypted, filepos, ctx->cb_ctx) == CL_VIRUS) {
cli_dbgmsg("inner file blacklisted by callback: %s\n", fname);
*ctx->virname = "Detected.By.Callback";
return CL_VIRUS;
}

@ -134,6 +134,8 @@ const struct clam_option __clam_options[] = {
{ NULL, "trace", 't', TYPE_NUMBER, MATCH_NUMBER, 7, NULL, 0, OPT_CLAMBC, "bytecode trace level",""},
{ NULL, "no-trace-showsource", 's', TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC, "Don't show source line during tracing",""},
{ NULL, "archive-verbose", 'a', TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", ""},
/* cmdline only - deprecated */
{ NULL, "bytecode-trust-all", 't', TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", ""},
{ NULL, "http-proxy", 0, TYPE_STRING, NULL, 0, NULL, 0, OPT_FRESHCLAM | OPT_DEPRECATED, "", "" },

Loading…
Cancel
Save