Merge branch 'master' into fmapify

* master:
  rework scan callbacks
  add filetype clcb
  logg_size is unsigned
  fix safebrowsing detection on certain URLs

Conflicts:
	libclamav/scanners.c
remotes/push_mirror/fmapify
Török Edvin 14 years ago
commit 40cf24f6bf
  1. 2
      clamd/clamd.c
  2. 31
      libclamav/clamav.h
  3. 6
      libclamav/others.c
  4. 2
      libclamav/others.h
  5. 6
      libclamav/phishcheck.c
  6. 82
      libclamav/scanners.c
  7. 2
      win32/clamav-for-windows/clamav-for-windows/interface.c
  8. 1
      win32/libclamav.def

@ -318,7 +318,7 @@ int main(int argc, char **argv)
if(logg_size)
logg("#Log file size limited to %d bytes.\n", logg_size);
logg("#Log file size limited to %u bytes.\n", logg_size);
else
logg("#Log file size limit disabled.\n");

@ -200,9 +200,37 @@ extern int cl_engine_free(struct cl_engine *engine);
/* CALLBACKS */
/* I certainly wish I could declare the callback protoes stable and
move on to better things. But real life crossed my way enough times
already and what looked perfect had to evolve somehow.
So all I can say is I'll try my best not to break these things in the long run.
But I just can't guarantee that won't happen (again). */
typedef cl_error_t (*clcb_pre_cache)(int fd, const char *type, void *context);
/* PRE-CACHE
Called for each processed file (both the entry level - AKA 'outer' - file and
inner files - those generated when processing archive and container files), before
the actual scanning takes place.
Input:
fd = File descriptor which is about to be scanned
type = File type detected via magic - i.e. NOT on the fly - (e.g. "CL_TYPE_MSEXE")
context = Opaque application provided data
Output:
CL_CLEAN = File is scanned
CL_BREAK = Whitelisted by callback - file is skipped and marked as clean
CL_VIRUS = Blacklisted by callback - file is skipped and marked as infected
*/
extern void cl_engine_set_clcb_file_type(struct cl_engine *engine, clcb_pre_cache callback);
typedef cl_error_t (*clcb_pre_scan)(int fd, const char *type, void *context);
/* PRE-SCAN
Called for each NEW file (inner and outer) before the scanning takes place. This is
roughly the the same as clcb_before_cache, but it is affected by clean file caching.
This means that it won't be called if a clean cached file (inner or outer) is
scanned a second time.
Input:
fd = File descriptor which is about to be scanned
type = File type detected via magic - i.e. NOT on the fly - (e.g. "CL_TYPE_MSEXE")
@ -215,9 +243,10 @@ CL_VIRUS = Blacklisted by callback - file is skipped and marked as infected
*/
extern void cl_engine_set_clcb_pre_scan(struct cl_engine *engine, clcb_pre_scan callback);
typedef cl_error_t (*clcb_post_scan)(int fd, int result, const char *virname, void *context);
/* POST-SCAN
Called for each processed file (inner and outer), after the scanning is complete.
Input:
fd = File descriptor which is was scanned
result = The scan result for the file

@ -560,6 +560,7 @@ struct cl_settings *cl_engine_settings_copy(const struct cl_engine *engine)
settings->bytecode_mode = engine->bytecode_mode;
settings->pua_cats = engine->pua_cats ? strdup(engine->pua_cats) : NULL;
settings->cb_pre_cache = engine->cb_pre_cache;
settings->cb_pre_scan = engine->cb_pre_scan;
settings->cb_post_scan = engine->cb_post_scan;
settings->cb_sigload = engine->cb_sigload;
@ -605,6 +606,7 @@ int cl_engine_settings_apply(struct cl_engine *engine, const struct cl_settings
engine->pua_cats = NULL;
}
engine->cb_pre_cache = settings->cb_pre_cache;
engine->cb_pre_scan = settings->cb_pre_scan;
engine->cb_post_scan = settings->cb_post_scan;
engine->cb_sigload = settings->cb_sigload;
@ -1059,6 +1061,10 @@ int cli_bitset_test(bitset_t *bs, unsigned long bit_offset)
return (bs->bitset[char_offset] & ((unsigned char)1 << bit_offset));
}
void cl_engine_set_clcb_pre_cache(struct cl_engine *engine, clcb_pre_cache callback) {
engine->cb_pre_cache = callback;
}
void cl_engine_set_clcb_pre_scan(struct cl_engine *engine, clcb_pre_scan callback) {
engine->cb_pre_scan = callback;
}

@ -252,6 +252,7 @@ struct cl_engine {
mpool_t *mempool;
/* Callback(s) */
clcb_pre_cache cb_pre_cache;
clcb_pre_scan cb_pre_scan;
clcb_post_scan cb_post_scan;
clcb_sigload cb_sigload;
@ -290,6 +291,7 @@ struct cl_settings {
char *pua_cats;
/* callbacks */
clcb_pre_cache cb_pre_cache;
clcb_pre_scan cb_pre_scan;
clcb_post_scan cb_post_scan;
clcb_sigload cb_sigload;

@ -1438,9 +1438,6 @@ static enum phish_status phishingCheck(const struct cl_engine* engine,struct url
cli_dbgmsg("Phishcheck:Checking url %s->%s\n", urls->realLink.data,
urls->displayLink.data);
if(!strcmp(urls->realLink.data,urls->displayLink.data))
return CL_PHISH_CLEAN;/* displayed and real URL are identical -> clean */
if(!isURL(urls->realLink.data, 0)) {
cli_dbgmsg("Real 'url' is not url:%s\n",urls->realLink.data);
return CL_PHISH_CLEAN;
@ -1456,6 +1453,9 @@ static enum phish_status phishingCheck(const struct cl_engine* engine,struct url
}
}
if(!strcmp(urls->realLink.data,urls->displayLink.data))
return CL_PHISH_CLEAN;/* displayed and real URL are identical -> clean */
if (urls->displayLink.data[0] == '\0') {
return CL_PHISH_CLEAN;
}

@ -2037,42 +2037,43 @@ static void emax_reached(cli_ctx *ctx) {
#define LINESTR(x) #x
#define LINESTR2(x) LINESTR(x)
#define __AT__ " at line "LINESTR2(__LINE__)
#define ret_from_magicscan(retcode) do { \
cli_dbgmsg("cli_magic_scandesc: returning %d %s\n", retcode, __AT__); \
if(ctx->engine->cb_post_scan) { \
perf_start(ctx, PERFT_POSTCB); \
switch(ctx->engine->cb_post_scan(desc, retcode, retcode == CL_VIRUS && ctx->virname ? *ctx->virname : NULL, ctx->cb_ctx)) { \
case CL_BREAK: \
cli_dbgmsg("cli_magic_scandesc: file whitelisted by callback\n"); \
perf_stop(ctx, PERFT_POSTCB); \
return CL_CLEAN; \
case CL_VIRUS: \
cli_dbgmsg("cli_magic_scandesc: file blacklisted by callback\n"); \
if(ctx->virname) \
*ctx->virname = "Detected.By.Callback"; \
perf_stop(ctx, PERFT_POSTCB); \
return CL_VIRUS; \
case CL_CLEAN: \
break; \
default: \
cli_warnmsg("cli_magic_scandesc: ignoring bad return code from callback\n"); \
#define ret_from_magicscan(retcode) \
do { \
cli_dbgmsg("cli_magic_scandesc: returning %d %s\n", retcode, __AT__); \
if(ctx->engine->cb_post_scan) { \
perf_start(ctx, PERFT_POSTCB); \
switch(ctx->engine->cb_post_scan(desc, retcode, retcode == CL_VIRUS && ctx->virname ? *ctx->virname : NULL, ctx->cb_ctx)) { \
case CL_BREAK: \
cli_dbgmsg("cli_magic_scandesc: file whitelisted by post_scan callback\n"); \
perf_stop(ctx, PERFT_POSTCB); \
return CL_CLEAN; \
case CL_VIRUS: \
cli_dbgmsg("cli_magic_scandesc: file blacklisted by post_scan callback\n"); \
if(ctx->virname) \
*ctx->virname = "Detected.By.Callback"; \
perf_stop(ctx, PERFT_POSTCB); \
return CL_VIRUS; \
case CL_CLEAN: \
break; \
default: \
cli_warnmsg("cli_magic_scandesc: ignoring bad return code from post_scan callback\n"); \
} \
perf_stop(ctx, PERFT_POSTCB); \
} \
perf_stop(ctx, PERFT_POSTCB); \
}\
return retcode; \
return retcode; \
} while(0)
#define CALL_PRESCAN_CB(type_name) \
if(ctx->engine->cb_pre_scan) { \
#define CALL_PRESCAN_CB(scanfn) \
if(ctx->engine->scanfn) { \
perf_start(ctx, PERFT_PRECB); \
switch(ctx->engine->cb_pre_scan(desc, (type_name), ctx->cb_ctx)) { \
switch(ctx->engine->scanfn(desc, filetype, ctx->cb_ctx)) { \
case CL_BREAK: \
cli_dbgmsg("cli_magic_scandesc: file whitelisted by callback\n"); \
cli_dbgmsg("cli_magic_scandesc: file whitelisted by "#scanfn" callback\n"); \
perf_stop(ctx, PERFT_PRECB); \
ret_from_magicscan(CL_CLEAN); \
case CL_VIRUS: \
cli_dbgmsg("cli_magic_scandesc: file blacklisted by callback\n"); \
cli_dbgmsg("cli_magic_scandesc: file blacklisted by "#scanfn" callback\n"); \
if(ctx->virname) \
*ctx->virname = "Detected.By.Callback"; \
perf_stop(ctx, PERFT_PRECB); \
@ -2097,6 +2098,7 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type)
unsigned char hash[16];
bitset_t *old_hook_lsig_matches;
int desc = (*ctx->fmap)->fd;
const char *filetype;
if(ctx->engine->maxreclevel && ctx->recursion > ctx->engine->maxreclevel) {
cli_dbgmsg("cli_magic_scandesc: Archive recursion limit exceeded (%u, max: %u)\n", ctx->recursion, ctx->engine->maxreclevel);
@ -2119,6 +2121,18 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type)
ret_from_magicscan(CL_CLEAN);
}
perf_start(ctx, PERFT_FT);
if(type == CL_TYPE_ANY)
type = cli_filetype2(*ctx->fmap, ctx->engine);
perf_stop(ctx, PERFT_FT);
if(type == CL_TYPE_ERROR) {
cli_dbgmsg("cli_magic_scandesc: cli_filetype2 returned CL_TYPE_ERROR\n");
ctx->hook_lsig_matches = old_hook_lsig_matches;
ret_from_magicscan(CL_EREAD);
}
filetype = cli_ftname(type);
CALL_PRESCAN_CB(cb_pre_cache);
perf_start(ctx, PERFT_CACHE);
if(cache_check(hash, ctx) == CL_CLEAN) {
perf_stop(ctx, PERFT_CACHE);
@ -2135,7 +2149,7 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type)
else
cli_dbgmsg("Raw mode: No support for special files\n");
CALL_PRESCAN_CB("CL_TYPE_BINARY_DATA");
CALL_PRESCAN_CB(cb_pre_scan);
if((ret = cli_fmap_scandesc(ctx, 0, 0, NULL, AC_SCAN_VIR, NULL, hash)) == CL_VIRUS)
cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
else if(ret == CL_CLEAN) {
@ -2149,17 +2163,7 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type)
ret_from_magicscan(ret);
}
perf_start(ctx, PERFT_FT);
if(type == CL_TYPE_ANY)
type = cli_filetype2(*ctx->fmap, ctx->engine);
perf_stop(ctx, PERFT_FT);
if(type == CL_TYPE_ERROR) {
cli_dbgmsg("cli_magic_scandesc: cli_filetype2 returned CL_TYPE_ERROR\n");
ctx->hook_lsig_matches = old_hook_lsig_matches;
ret_from_magicscan(CL_EREAD);
}
CALL_PRESCAN_CB(cli_ftname(type));
CALL_PRESCAN_CB(cb_pre_scan);
#ifdef HAVE__INTERNAL__SHA_COLLECT
if(!ctx->sha_collect && type==CL_TYPE_MSEXE) ctx->sha_collect = 1;

@ -355,7 +355,7 @@ int CLAMAPI Scan_Initialize(const wchar_t *pEnginesFolder, const wchar_t *pTempR
unlock_engine();
FAIL(CL_EMEM, "Not enough memory for a new engine");
}
cl_engine_set_clcb_pre_scan(engine, prescan_cb);
cl_engine_set_clcb_pre_cache(engine, prescan_cb);
cl_engine_set_clcb_post_scan(engine, postscan_cb);
minimal_definitions = bLoadMinDefs;

@ -39,6 +39,7 @@ EXPORTS cl_engine_set_clcb_sigload @31
EXPORTS cl_scanfile_callback @32
EXPORTS cl_set_clcb_msg @33
EXPORTS cl_engine_set_clcb_hash @34
EXPORTS cl_engine_set_clcb_pre_cache @35
; path variables

Loading…
Cancel
Save