From 7f50a91cedc2366327055b18252d02062b1d46a1 Mon Sep 17 00:00:00 2001 From: Steven Morgan Date: Fri, 31 Jan 2014 17:50:48 -0500 Subject: [PATCH 01/19] allow xar processing to continue when there are file extraction errors. --- libclamav/xar.c | 112 ++++++++++++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 51 deletions(-) diff --git a/libclamav/xar.c b/libclamav/xar.c index de2f138c7..d5c03e8ff 100644 --- a/libclamav/xar.c +++ b/libclamav/xar.c @@ -290,7 +290,6 @@ static int xar_scan_subdocuments(xmlTextReaderPtr reader, cli_ctx *ctx) xmlTextReaderNext(reader); continue; } - // printf("subdoc:\n%s\n", subdoc); subdoc_len = xmlStrlen(subdoc); cli_dbgmsg("cli_scanxar: in-memory scan of xml subdocument, len %i.\n", subdoc_len); rc = cli_mem_scandesc(subdoc, subdoc_len, ctx); @@ -300,7 +299,7 @@ static int xar_scan_subdocuments(xmlTextReaderPtr reader, cli_ctx *ctx) /* make a file to leave if --leave-temps in effect */ if(ctx->engine->keeptmp) { if ((rc = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) { - cli_warnmsg("cli_scanxar: Can't create temporary file for subdocument.\n"); + cli_dbgmsg("cli_scanxar: Can't create temporary file for subdocument.\n"); } else { cli_dbgmsg("cli_scanxar: Writing subdoc to temp file %s.\n", tmpname); if (cli_writen(fd, subdoc, subdoc_len) < 0) { @@ -412,6 +411,7 @@ int cli_scanxar(cli_ctx *ctx) { int rc = CL_SUCCESS; unsigned int cksum_fails = 0; + unsigned int extract_errors = 0; #if HAVE_LIBXML2 int fd = -1; struct xar_header hdr; @@ -569,7 +569,8 @@ int cli_scanxar(cli_ctx *ctx) if ((rc = inflateInit(&strm)) != Z_OK) { cli_dbgmsg("cli_scanxar: InflateInit failed: %d\n", rc); rc = CL_EFORMAT; - goto exit_tmpfile; + extract_errors++; + break; } while (at < map->len && at < offset+hdr.toc_length_compressed+hdr.size+length) { @@ -577,7 +578,6 @@ int cli_scanxar(cli_ctx *ctx) void * next_in; unsigned int bytes = MIN(map->len - at, map->pgsz); bytes = MIN(length, bytes); - //cli_dbgmsg("cli_scanxar: fmap %u bytes\n", bytes); if(!(strm.next_in = next_in = (void*)fmap_need_off_once(map, at, bytes))) { cli_dbgmsg("cli_scanxar: Can't read %u bytes @ %lu.\n", bytes, (long unsigned)at); inflateEnd(&strm); @@ -591,13 +591,12 @@ int cli_scanxar(cli_ctx *ctx) unsigned char buff[FILEBUFF]; strm.avail_out = sizeof(buff); strm.next_out = buff; - //cli_dbgmsg("cli_scanxar: inflating.....\n"); inf = inflate(&strm, Z_SYNC_FLUSH); if (inf != Z_OK && inf != Z_STREAM_END && inf != Z_BUF_ERROR) { cli_dbgmsg("cli_scanxar: inflate error %i %s.\n", inf, strm.msg?strm.msg:""); - at = map->len; rc = CL_EFORMAT; - goto exit_tmpfile; + extract_errors++; + break; } bytes = sizeof(buff) - strm.avail_out; @@ -619,10 +618,13 @@ int cli_scanxar(cli_ctx *ctx) } } while (strm.avail_out == 0); + if (rc != CL_SUCCESS) + break; + avail_in -= strm.avail_in; xar_hash_update(a_hash_ctx, next_in, avail_in, a_hash); } - + inflateEnd(&strm); break; case CL_TYPE_7Z: @@ -664,9 +666,10 @@ int cli_scanxar(cli_ctx *ctx) cli_dbgmsg("cli_scanxar: cli_LzmaInit() fails: %i.\n", rc); rc = CL_EFORMAT; __lzma_wrap_free(NULL, buff); - goto exit_tmpfile; + extract_errors++; + break; } - + at += CLI_LZMA_HDR_SIZE; in_remaining -= CLI_LZMA_HDR_SIZE; while (at < map->len && at < offset+hdr.toc_length_compressed+hdr.size+length) { @@ -694,9 +697,8 @@ int cli_scanxar(cli_ctx *ctx) if (rc != LZMA_RESULT_OK && rc != LZMA_STREAM_END) { cli_dbgmsg("cli_scanxar: cli_LzmaDecode() fails: %i.\n", rc); rc = CL_EFORMAT; - __lzma_wrap_free(NULL, buff); - cli_LzmaShutdown(&lz); - goto exit_tmpfile; + extract_errors++; + break; } in_consumed = avail_in - lz.avail_in; @@ -715,7 +717,7 @@ int cli_scanxar(cli_ctx *ctx) /* cli_dbgmsg("Writing %li bytes to LZMA decompress temp file, " */ /* "consumed %li of %li available compressed bytes.\n", */ /* avail_out, in_consumed, avail_in); */ - + if (cli_writen(fd, buff, avail_out) < 0) { cli_dbgmsg("cli_scanxar: cli_writen error writing lzma temp file for %li bytes.\n", avail_out); @@ -724,18 +726,17 @@ int cli_scanxar(cli_ctx *ctx) rc = CL_EWRITE; goto exit_tmpfile; } - + /* Check file size limitation. */ out_size += avail_out; if (cli_checklimits("cli_scanxar", ctx, out_size, 0, 0) != CL_CLEAN) { break; } - + if (rc == LZMA_STREAM_END) break; } - cli_LzmaShutdown(&lz); __lzma_wrap_free(NULL, buff); } @@ -774,47 +775,54 @@ int cli_scanxar(cli_ctx *ctx) } } - xar_hash_final(a_hash_ctx, result, a_hash); - if (a_cksum != NULL) { - expected = cli_hex2str((char *)a_cksum); - if (xar_hash_check(a_hash, result, expected) != 0) { - cli_dbgmsg("cli_scanxar: archived-checksum missing or mismatch.\n"); - cksum_fails++; - } else { - cli_dbgmsg("cli_scanxar: archived-checksum matched.\n"); - } - free(expected); - xmlFree(a_cksum); - a_cksum = NULL; - } - if (e_cksum != NULL) { - if (do_extract_cksum) { - xar_hash_final(e_hash_ctx, result, e_hash); - expected = cli_hex2str((char *)e_cksum); - if (xar_hash_check(e_hash, result, expected) != 0) { - cli_dbgmsg("cli_scanxar: extracted-checksum missing or mismatch.\n"); + if (rc == CL_SUCCESS) { + xar_hash_final(a_hash_ctx, result, a_hash); + if (a_cksum != NULL) { + expected = cli_hex2str((char *)a_cksum); + if (xar_hash_check(a_hash, result, expected) != 0) { + cli_dbgmsg("cli_scanxar: archived-checksum missing or mismatch.\n"); cksum_fails++; } else { - cli_dbgmsg("cli_scanxar: extracted-checksum matched.\n"); + cli_dbgmsg("cli_scanxar: archived-checksum matched.\n"); } free(expected); } - xmlFree(e_cksum); - e_cksum = NULL; - } + if (e_cksum != NULL) { + if (do_extract_cksum) { + xar_hash_final(e_hash_ctx, result, e_hash); + expected = cli_hex2str((char *)e_cksum); + if (xar_hash_check(e_hash, result, expected) != 0) { + cli_dbgmsg("cli_scanxar: extracted-checksum missing or mismatch.\n"); + cksum_fails++; + } else { + cli_dbgmsg("cli_scanxar: extracted-checksum matched.\n"); + } + free(expected); + } + } - rc = cli_magic_scandesc(fd, ctx); - if (rc != CL_SUCCESS) { - if (rc == CL_VIRUS) { - cli_dbgmsg("cli_scanxar: Infected with %s\n", cli_get_last_virus(ctx)); - if (!SCAN_ALL) + rc = cli_magic_scandesc(fd, ctx); + if (rc != CL_SUCCESS) { + if (rc == CL_VIRUS) { + cli_dbgmsg("cli_scanxar: Infected with %s\n", cli_get_last_virus(ctx)); + if (!SCAN_ALL) + goto exit_tmpfile; + } else if (rc != CL_BREAK) { + cli_dbgmsg("cli_scanxar: cli_magic_scandesc error %i\n", rc); goto exit_tmpfile; - } else if (rc != CL_BREAK) { - cli_dbgmsg("cli_scanxar: cli_magic_scandesc error %i\n", rc); - goto exit_tmpfile; + } } } - } + + if (a_cksum != NULL) { + xmlFree(a_cksum); + a_cksum = NULL; + } + if (e_cksum != NULL) { + xmlFree(e_cksum); + e_cksum = NULL; + } + } exit_tmpfile: xar_cleanup_temp_file(ctx, fd, tmpname); @@ -834,8 +842,10 @@ int cli_scanxar(cli_ctx *ctx) #else cli_dbgmsg("cli_scanxar: can't scan xar files, need libxml2.\n"); #endif - if (cksum_fails != 0) - cli_warnmsg("cli_scanxar: %u checksums missing, mismatched, or unsupported - use --debug for more info.\n", cksum_fails); + if (cksum_fails + extract_errors != 0) { + cli_warnmsg("cli_scanxar: %u checksum errors and %u extraction errors, use --debug for more info.\n", + cksum_fails, extract_errors); + } return rc; } From 3be7f9a93dcec1822d3b2dba9c8e2dba9fffa9e5 Mon Sep 17 00:00:00 2001 From: Tom Judge Date: Sun, 2 Feb 2014 17:09:31 -0500 Subject: [PATCH 02/19] Add support for passing the CVD version number on the command line via --cvd-version rather than sigtool prompting for the version if the previous version of the database is not present. --- shared/optparser.c | 1 + sigtool/sigtool.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/shared/optparser.c b/shared/optparser.c index 3c8d7bab1..9c7d41cc7 100644 --- a/shared/optparser.c +++ b/shared/optparser.c @@ -112,6 +112,7 @@ const struct clam_option __clam_options[] = { { NULL, "build", 'b', TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" }, { NULL, "max-bad-sigs", 0, TYPE_NUMBER, MATCH_NUMBER, 3000, NULL, 0, OPT_SIGTOOL, "Maximum number of mismatched signatures when building a CVD. Zero disables this limit.", "3000" }, { NULL, "flevel", 0, TYPE_NUMBER, MATCH_NUMBER, CL_FLEVEL, NULL, 0, OPT_SIGTOOL, "Feature level to put in the CVD", "" }, + { NULL, "cvd-version", 0, TYPE_NUMBER, MATCH_NUMBER, 0, NULL, 0, OPT_SIGTOOL, "Version number of the CVD to build", "" }, { NULL, "unsigned", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", "" }, { NULL, "no-cdiff", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", "" }, { NULL, "server", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" }, diff --git a/sigtool/sigtool.c b/sigtool/sigtool.c index 735458ede..965c6e4f0 100644 --- a/sigtool/sigtool.c +++ b/sigtool/sigtool.c @@ -793,6 +793,8 @@ static int build(const struct optstruct *opts) version = oldcvd->version + 1; oldsigs = oldcvd->sigs; cl_cvdfree(oldcvd); + } else if (optget(opts, "cvd-version")->numarg != 0) { + version = optget(opts, "cvd-version")->numarg; } else { mprintf("Version number: "); if(scanf("%u", &version) == EOF) { @@ -2927,11 +2929,12 @@ static void help(void) mprintf(" --build=NAME [cvd] -b NAME build a CVD file\n"); mprintf(" --max-bad-sigs=NUMBER Maximum number of mismatched signatures when building a CVD. Default: 3000\n"); mprintf(" --flevel=FLEVEL Specify a custom flevel. Default: %u\n", cl_retflevel()); + mprintf(" --cvd-version=NUMBER Specify the version number to use for the build. Default is to prompt if no old CVD can me found\n"); mprintf(" --no-cdiff Don't generate .cdiff file\n"); mprintf(" --unsigned Create unsigned database file (.cud)\n"); mprintf(" --print-certs=FILE Print Authenticode details from a PE\n"); mprintf(" --server=ADDR ClamAV Signing Service address\n"); - mprintf(" --datadir=DIR Use DIR as default database directory\n"); + mprintf(" --datadir=DIR Use DIR as default database directory\n"); mprintf(" --unpack=FILE -u FILE Unpack a CVD/CLD file\n"); mprintf(" --unpack-current=SHORTNAME Unpack local CVD/CLD into cwd\n"); mprintf(" --list-sigs[=FILE] -l[FILE] List signature names\n"); From f8d05d6d9d9504f9d9ceb88deb1aa08d704a980f Mon Sep 17 00:00:00 2001 From: Tom Judge Date: Sun, 2 Feb 2014 20:48:24 -0500 Subject: [PATCH 03/19] Fix wording of --cvd-version and fix line lengths of other options while here. --- sigtool/sigtool.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/sigtool/sigtool.c b/sigtool/sigtool.c index 965c6e4f0..704772a74 100644 --- a/sigtool/sigtool.c +++ b/sigtool/sigtool.c @@ -2905,9 +2905,9 @@ static int dumpcerts(const struct optstruct *opts) static void help(void) { mprintf("\n"); - mprintf(" Clam AntiVirus: Signature Tool (sigtool) %s\n", get_version()); - printf(" By The ClamAV Team: http://www.clamav.net/team\n"); - printf(" (C) 2007-2009 Sourcefire, Inc. et al.\n\n"); + mprintf("Clam AntiVirus: Signature Tool (sigtool) %s\n", get_version()); + mprintf(" By The ClamAV Team: http://www.clamav.net/team\n"); + mprintf(" (C) 2007-2009 Sourcefire, Inc. et al.\n\n"); mprintf(" --help -h show help\n"); mprintf(" --version -V print version number and exit\n"); @@ -2927,9 +2927,19 @@ static void help(void) mprintf(" --utf16-decode=FILE decode UTF16 encoded files\n"); mprintf(" --info=FILE -i FILE print database information\n"); mprintf(" --build=NAME [cvd] -b NAME build a CVD file\n"); - mprintf(" --max-bad-sigs=NUMBER Maximum number of mismatched signatures when building a CVD. Default: 3000\n"); - mprintf(" --flevel=FLEVEL Specify a custom flevel. Default: %u\n", cl_retflevel()); - mprintf(" --cvd-version=NUMBER Specify the version number to use for the build. Default is to prompt if no old CVD can me found\n"); + mprintf(" --max-bad-sigs=NUMBER Maximum number of mismatched signatures\n"); + mprintf(" when building a CVD. Default: 3000\n"); + mprintf(" --flevel=FLEVEL Specify a custom flevel.\n"); + mprintf(" Default: %u\n", cl_retflevel()); + mprintf(" --cvd-version=NUMBER Specify the version number to use for\n"); + mprintf(" the build. Default is to use the value+1\n"); + mprintf(" from the current CVD in --datadir.\n"); + mprintf(" If no datafile is found the default\n"); + mprintf(" behaviour is to prompt for a version\n"); + mprintf(" number, this switch will prevent the\n"); + mprintf(" prompt. NOTE: If a CVD is found in the\n"); + mprintf(" --datadir its version+1 is used and\n"); + mprintf(" this value is ignored.\n"); mprintf(" --no-cdiff Don't generate .cdiff file\n"); mprintf(" --unsigned Create unsigned database file (.cud)\n"); mprintf(" --print-certs=FILE Print Authenticode details from a PE\n"); @@ -2940,11 +2950,13 @@ static void help(void) mprintf(" --list-sigs[=FILE] -l[FILE] List signature names\n"); mprintf(" --find-sigs=REGEX -fREGEX Find signatures matching REGEX\n"); mprintf(" --decode-sigs Decode signatures from stdin\n"); - mprintf(" --test-sigs=DATABASE TARGET_FILE Test signatures from DATABASE against TARGET_FILE\n"); + mprintf(" --test-sigs=DATABASE TARGET_FILE Test signatures from DATABASE against \n"); + mprintf(" TARGET_FILE\n"); mprintf(" --vba=FILE Extract VBA/Word6 macro code\n"); mprintf(" --vba-hex=FILE Extract Word6 macro code with hex values\n"); mprintf(" --diff=OLD NEW -d OLD NEW Create diff for OLD and NEW CVDs\n"); - mprintf(" --compare=OLD NEW -c OLD NEW Show diff between OLD and NEW files in cdiff format\n"); + mprintf(" --compare=OLD NEW -c OLD NEW Show diff between OLD and NEW files in\n"); + mprintf(" cdiff format\n"); mprintf(" --run-cdiff=FILE -r FILE Execute update script FILE in cwd\n"); mprintf(" --verify-cdiff=DIFF CVD/CLD Verify DIFF against CVD/CLD\n"); mprintf("\n"); From bfe26c4e49f55504a0d409dd2e8064266a0f7c35 Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Mon, 3 Feb 2014 11:46:21 -0500 Subject: [PATCH 04/19] Supress valgrind regression to make our debian 6.0 amd64 buildbot happy --- unit_tests/valgrind.supp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/unit_tests/valgrind.supp b/unit_tests/valgrind.supp index 815511081..6f55f1ded 100644 --- a/unit_tests/valgrind.supp +++ b/unit_tests/valgrind.supp @@ -23,6 +23,14 @@ fun:_ZN4llvm12PassRegistry12registerPassERKNS_8PassInfoE fun:* } +{ + llvm-03 + Memcheck:Leak + fun:_Znwm + ... + fun:_ZN4llvm12PassRegistry12registerPassERKNS_8PassInfoE + ... +} { dl_catch_error-leak-1 Memcheck:Leak From b86e39088b1a7fedc6a03025998727c4461830f5 Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Mon, 3 Feb 2014 11:51:13 -0500 Subject: [PATCH 05/19] Remove debugging statements from stats code --- libclamav/hostid.c | 2 -- libclamav/stats.c | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/libclamav/hostid.c b/libclamav/hostid.c index 38fc75d15..da00eb1e8 100644 --- a/libclamav/hostid.c +++ b/libclamav/hostid.c @@ -155,8 +155,6 @@ struct device *get_devices(void) /* This is the Linux version of getting the MAC addresses */ #if defined(SIOCGIFHWADDR) for (i=0; i < ndevices; i++) { - cli_warnmsg("devices[%lu]: %s\n", i, devices[i].name); - if (!(devices[i].name)) continue; diff --git a/libclamav/stats.c b/libclamav/stats.c index bae4d474c..7c42e0fff 100644 --- a/libclamav/stats.c +++ b/libclamav/stats.c @@ -31,7 +31,7 @@ #include "libclamav/hostid.h" #include "libclamav/www.h" -#define DEBUG_STATS 1 +#define DEBUG_STATS 0 static cli_flagged_sample_t *find_sample(cli_intel_t *intel, const char *virname, const unsigned char *md5, size_t size, stats_section_t *sections); void free_sample(cli_flagged_sample_t *sample); @@ -229,8 +229,6 @@ void clamav_stats_add_sample(const char *virname, const unsigned char *md5, size } } - cli_warnmsg("Added %s to the stats cache\n", (virname != NULL) ? virname: "[unknown]"); - sample->hits++; end: @@ -355,7 +353,6 @@ void clamav_stats_submit(struct cl_engine *engine, void *cbdata) } if (json) { - cli_warnmsg("====\tSUBMITTING STATS\t====\n"); submit_post(STATS_HOST, STATS_PORT, "PUT", "/clamav/1/submit/stats", json); free(json); } From 4e1236c8023026bec090388a80e17cafd5978ea3 Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Mon, 3 Feb 2014 17:23:26 -0500 Subject: [PATCH 06/19] Add option for configuring the timeout for stats submissions --- clamd/clamd.c | 4 ++++ clamscan/manager.c | 4 ++++ freshclam/freshclam.c | 4 ++++ libclamav/clamav.h | 3 ++- libclamav/others.c | 7 +++++++ libclamav/others.h | 1 + libclamav/stats.c | 2 +- libclamav/www.c | 10 +++++----- libclamav/www.h | 4 ++-- shared/optparser.c | 2 ++ 10 files changed, 32 insertions(+), 9 deletions(-) diff --git a/clamd/clamd.c b/clamd/clamd.c index c89808635..4752ebe76 100644 --- a/clamd/clamd.c +++ b/clamd/clamd.c @@ -438,6 +438,10 @@ int main(int argc, char **argv) cl_engine_set_num(engine, CL_ENGINE_DISABLE_PE_STATS, 1); } + if (optget(opts, "StatsTimeout")->enabled) { + cl_engine_set_num(engine, CL_ENGINE_STATS_TIMEOUT, optget(opts, "StatsTimeout")->numarg); + } + if (optget(opts, "StatsHostID")->enabled) { char *p = optget(opts, "StatsHostID")->strarg; diff --git a/clamscan/manager.c b/clamscan/manager.c index 04ebd8889..cb6c95118 100644 --- a/clamscan/manager.c +++ b/clamscan/manager.c @@ -582,6 +582,10 @@ int scanmanager(const struct optstruct *opts) cl_engine_set_clcb_stats_add_sample(engine, NULL); } + if (optget(opts, "stats-timeout")->enabled) { + cl_engine_set_num(engine, CL_ENGINE_STATS_TIMEOUT, optget(opts, "StatsTimeout")->numarg); + } + if (optget(opts, "stats-host-id")->enabled) { char *p = optget(opts, "stats-host-id")->strarg; diff --git a/freshclam/freshclam.c b/freshclam/freshclam.c index 93e4dbc72..7c7e21ad3 100644 --- a/freshclam/freshclam.c +++ b/freshclam/freshclam.c @@ -763,6 +763,10 @@ void submit_host_info(struct optstruct *opts) else if (strcmp(hostid, "default")) cl_engine_set_clcb_stats_get_hostid(engine, get_hostid); + if (optget(opts, "stats-timeout")->enabled) { + cl_engine_set_num(engine, CL_ENGINE_STATS_TIMEOUT, optget(opts, "StatsTimeout")->numarg); + } + cl_engine_free(engine); } diff --git a/libclamav/clamav.h b/libclamav/clamav.h index d291656ec..05bd8a3d9 100644 --- a/libclamav/clamav.h +++ b/libclamav/clamav.h @@ -204,7 +204,8 @@ enum cl_engine_field { CL_ENGINE_MAX_ZIPTYPERCG, /* uint64_t */ CL_ENGINE_FORCETODISK, /* uint32_t */ CL_ENGINE_DISABLE_CACHE, /* uint32_t */ - CL_ENGINE_DISABLE_PE_STATS /* uint32_t */ + CL_ENGINE_DISABLE_PE_STATS, /* uint32_t */ + CL_ENGINE_STATS_TIMEOUT /* uint32_t */ }; enum bytecode_security { diff --git a/libclamav/others.c b/libclamav/others.c index 554ef69b8..5359d71dc 100644 --- a/libclamav/others.c +++ b/libclamav/others.c @@ -400,6 +400,7 @@ struct cl_engine *cl_engine_new(void) intel->engine = new; intel->maxsamples = STATS_MAX_SAMPLES; intel->maxmem = STATS_MAX_MEM; + intel->timeout = 10; new->stats_data = intel; new->cb_stats_add_sample = clamav_stats_add_sample; new->cb_stats_submit = clamav_stats_submit; @@ -542,6 +543,12 @@ int cl_engine_set_num(struct cl_engine *engine, enum cl_engine_field field, long engine->engine_options &= ~(ENGINE_OPTIONS_DISABLE_PE_STATS); } break; + case CL_ENGINE_STATS_TIMEOUT: + if ((engine->stats_data)) { + cli_intel_t *intel = (cli_intel_t *)(engine->stats_data); + + intel->timeout = (uint32_t)num; + } default: cli_errmsg("cl_engine_set_num: Incorrect field number\n"); return CL_EARG; diff --git a/libclamav/others.h b/libclamav/others.h index 53446d9bf..37c45e148 100644 --- a/libclamav/others.h +++ b/libclamav/others.h @@ -164,6 +164,7 @@ typedef struct cli_clamav_intel { uint32_t nsamples; uint32_t maxsamples; uint32_t maxmem; + uint32_t timeout; time_t nextupdate; struct cl_engine *engine; #ifdef CL_THREAD_SAFE diff --git a/libclamav/stats.c b/libclamav/stats.c index 7c42e0fff..37df3ba84 100644 --- a/libclamav/stats.c +++ b/libclamav/stats.c @@ -353,7 +353,7 @@ void clamav_stats_submit(struct cl_engine *engine, void *cbdata) } if (json) { - submit_post(STATS_HOST, STATS_PORT, "PUT", "/clamav/1/submit/stats", json); + submit_post(STATS_HOST, STATS_PORT, "PUT", "/clamav/1/submit/stats", json, myintel.timeout); free(json); } diff --git a/libclamav/www.c b/libclamav/www.c index bd39469a2..7f1a17f79 100644 --- a/libclamav/www.c +++ b/libclamav/www.c @@ -24,7 +24,7 @@ #include "libclamav/clamav.h" #include "libclamav/www.h" -int connect_host(const char *host, const char *port, int useAsync) +int connect_host(const char *host, const char *port, uint32_t timeout, int useAsync) { int sockfd; struct addrinfo hints, *servinfo, *p; @@ -67,7 +67,7 @@ int connect_host(const char *host, const char *port, int useAsync) FD_SET(sockfd, &write_fds); /* TODO: Make this timeout configurable */ - tv.tv_sec = 10; + tv.tv_sec = timeout; tv.tv_usec = 0; if (select(sockfd + 1, &read_fds, &write_fds, NULL, &tv) <= 0) { close(sockfd); @@ -150,7 +150,7 @@ char *encode_data(const char *postdata) return buf; } -void submit_post(const char *host, const char *port, const char *method, const char *url, const char *postdata) +void submit_post(const char *host, const char *port, const char *method, const char *url, const char *postdata, uint32_t timeout) { int sockfd, n; unsigned int i; @@ -214,7 +214,7 @@ void submit_post(const char *host, const char *port, const char *method, const c free(encoded); } - sockfd = connect_host(host, port, 1); + sockfd = connect_host(host, port, timeout, 1); if (sockfd < 0) { free(buf); return; @@ -235,7 +235,7 @@ void submit_post(const char *host, const char *port, const char *method, const c * while it's being processed). Give a ten-second timeout so we don't have a major * impact on scanning. */ - tv.tv_sec = 10; + tv.tv_sec = timeout; tv.tv_usec = 0; if ((n = select(sockfd+1, &readfds, NULL, NULL, &tv)) <= 0) break; diff --git a/libclamav/www.h b/libclamav/www.h index 4ed388d0a..dd805c731 100644 --- a/libclamav/www.h +++ b/libclamav/www.h @@ -1,9 +1,9 @@ #if !defined(_LIBCLAMAV_WWW_H) #define _LIBCLAMAV_WWW_H -int connect_host(const char *host, const char *port, int useAsync); +int connect_host(const char *host, const char *port, uint32_t timeout, int useAsync); size_t encoded_size(const char *postdata); char *encode_data(const char *postdata); -void submit_post(const char *host, const char *port, const char *method, const char *url, const char *postdata); +void submit_post(const char *host, const char *port, const char *method, const char *url, const char *postdata, uint32_t timeout); #endif diff --git a/shared/optparser.c b/shared/optparser.c index 9c7d41cc7..68cca3b06 100644 --- a/shared/optparser.c +++ b/shared/optparser.c @@ -186,6 +186,8 @@ const struct clam_option __clam_options[] = { { "StatsPEDisabled", "disable-pe-stats", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Disable submission of PE section statistical data", "no" }, + { "StatsTimeout", "stats-timeout", 0, TYPE_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN | OPT_FRESHCLAM, "Timeout in seconds to timeout communication with the stats server.", "10" }, + { "LogFileUnlock", NULL, 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_MILTER, "By default the log file is locked for writing and only a single\ndaemon process can write to it. This option disables the lock.", "yes" }, { "LogFileMaxSize", NULL, 0, TYPE_SIZE, MATCH_SIZE, 1048576, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Maximum size of the log file.\nValue of 0 disables the limit.", "5M" }, From d4f90ad449ec25e332cf169ab3efe9a27076da39 Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Tue, 4 Feb 2014 10:08:19 -0500 Subject: [PATCH 07/19] Add DCONF support to the stats feature. --- libclamav/dconf.c | 622 +++++++++++++++++++++++--------------------- libclamav/dconf.h | 5 + libclamav/matcher.c | 2 +- libclamav/stats.c | 7 + 4 files changed, 337 insertions(+), 299 deletions(-) diff --git a/libclamav/dconf.c b/libclamav/dconf.c index df49fb1b7..2fd607c29 100644 --- a/libclamav/dconf.c +++ b/libclamav/dconf.c @@ -38,10 +38,10 @@ #include "mpool.h" struct dconf_module { - const char *mname; /* module name */ - const char *sname; /* submodule name */ - uint32_t bflag; /* bit flag */ - uint8_t state; /* default state (on/off) */ + const char *mname; /* module name */ + const char *sname; /* submodule name */ + uint32_t bflag; /* bit flag */ + uint8_t state; /* default state (on/off) */ }; #ifdef CL_EXPERIMENTAL @@ -52,73 +52,73 @@ struct dconf_module { static struct dconf_module modules[] = { - { "PE", "PARITE", PE_CONF_PARITE, 1 }, - { "PE", "KRIZ", PE_CONF_KRIZ, 1 }, - { "PE", "MAGISTR", PE_CONF_MAGISTR, 1 }, - { "PE", "POLIPOS", PE_CONF_POLIPOS, 1 }, - { "PE", "MD5SECT", PE_CONF_MD5SECT, 1 }, - { "PE", "UPX", PE_CONF_UPX, 1 }, - { "PE", "FSG", PE_CONF_FSG, 1 }, + { "PE", "PARITE", PE_CONF_PARITE, 1 }, + { "PE", "KRIZ", PE_CONF_KRIZ, 1 }, + { "PE", "MAGISTR", PE_CONF_MAGISTR, 1 }, + { "PE", "POLIPOS", PE_CONF_POLIPOS, 1 }, + { "PE", "MD5SECT", PE_CONF_MD5SECT, 1 }, + { "PE", "UPX", PE_CONF_UPX, 1 }, + { "PE", "FSG", PE_CONF_FSG, 1 }, { "PE", "SWIZZOR", PE_CONF_SWIZZOR, 1 }, - { "PE", "PETITE", PE_CONF_PETITE, 1 }, - { "PE", "PESPIN", PE_CONF_PESPIN, 1 }, - { "PE", "YC", PE_CONF_YC, 1 }, - { "PE", "WWPACK", PE_CONF_WWPACK, 1 }, + { "PE", "PETITE", PE_CONF_PETITE, 1 }, + { "PE", "PESPIN", PE_CONF_PESPIN, 1 }, + { "PE", "YC", PE_CONF_YC, 1 }, + { "PE", "WWPACK", PE_CONF_WWPACK, 1 }, - { "PE", "NSPACK", PE_CONF_NSPACK, 1 }, - { "PE", "MEW", PE_CONF_MEW, 1 }, - { "PE", "UPACK", PE_CONF_UPACK, 1 }, - { "PE", "ASPACK", PE_CONF_ASPACK, 1 }, - { "PE", "CATALOG", PE_CONF_CATALOG, 1 }, + { "PE", "NSPACK", PE_CONF_NSPACK, 1 }, + { "PE", "MEW", PE_CONF_MEW, 1 }, + { "PE", "UPACK", PE_CONF_UPACK, 1 }, + { "PE", "ASPACK", PE_CONF_ASPACK, 1 }, + { "PE", "CATALOG", PE_CONF_CATALOG, 1 }, { "PE", "DISABLECERT", PE_CONF_DISABLECERT, 0 }, { "PE", "DUMPCERT", PE_CONF_DUMPCERT, 0 }, - { "ELF", NULL, 0x1, 1 }, - - { "MACHO", NULL, 0x1, 1 }, - - { "ARCHIVE", "RAR", ARCH_CONF_RAR, 1 }, - { "ARCHIVE", "ZIP", ARCH_CONF_ZIP, 1 }, - { "ARCHIVE", "GZIP", ARCH_CONF_GZ, 1 }, - { "ARCHIVE", "BZIP", ARCH_CONF_BZ, 1 }, - { "ARCHIVE", "ARJ", ARCH_CONF_ARJ, 1 }, - { "ARCHIVE", "SZDD", ARCH_CONF_SZDD, 1 }, - { "ARCHIVE", "CAB", ARCH_CONF_CAB, 1 }, - { "ARCHIVE", "CHM", ARCH_CONF_CHM, 1 }, - { "ARCHIVE", "OLE2", ARCH_CONF_OLE2, 1 }, - { "ARCHIVE", "TAR", ARCH_CONF_TAR, 1 }, - { "ARCHIVE", "CPIO", ARCH_CONF_CPIO, 1 }, - { "ARCHIVE", "BINHEX", ARCH_CONF_BINHEX, 1 }, - { "ARCHIVE", "SIS", ARCH_CONF_SIS, 1 }, - { "ARCHIVE", "NSIS", ARCH_CONF_NSIS, 1 }, - { "ARCHIVE", "AUTOIT", ARCH_CONF_AUTOIT, 1 }, - { "ARCHIVE", "ISHIELD", ARCH_CONF_ISHIELD, 1 }, - { "ARCHIVE", "7zip", ARCH_CONF_7Z, 1 }, - { "ARCHIVE", "ISO9660", ARCH_CONF_ISO9660, 1 }, - { "ARCHIVE", "DMG", ARCH_CONF_DMG, 1 }, - { "ARCHIVE", "XAR", ARCH_CONF_XAR, 1 }, - { "ARCHIVE", "HFSPLUS", ARCH_CONF_HFSPLUS, 1 }, - { "ARCHIVE", "XZ", ARCH_CONF_XZ, 1 }, - - { "DOCUMENT", "HTML", DOC_CONF_HTML, 1 }, - { "DOCUMENT", "RTF", DOC_CONF_RTF, 1 }, - { "DOCUMENT", "PDF", DOC_CONF_PDF, 1 }, - { "DOCUMENT", "SCRIPT", DOC_CONF_SCRIPT, 1 }, + { "ELF", NULL, 0x1, 1 }, + + { "MACHO", NULL, 0x1, 1 }, + + { "ARCHIVE", "RAR", ARCH_CONF_RAR, 1 }, + { "ARCHIVE", "ZIP", ARCH_CONF_ZIP, 1 }, + { "ARCHIVE", "GZIP", ARCH_CONF_GZ, 1 }, + { "ARCHIVE", "BZIP", ARCH_CONF_BZ, 1 }, + { "ARCHIVE", "ARJ", ARCH_CONF_ARJ, 1 }, + { "ARCHIVE", "SZDD", ARCH_CONF_SZDD, 1 }, + { "ARCHIVE", "CAB", ARCH_CONF_CAB, 1 }, + { "ARCHIVE", "CHM", ARCH_CONF_CHM, 1 }, + { "ARCHIVE", "OLE2", ARCH_CONF_OLE2, 1 }, + { "ARCHIVE", "TAR", ARCH_CONF_TAR, 1 }, + { "ARCHIVE", "CPIO", ARCH_CONF_CPIO, 1 }, + { "ARCHIVE", "BINHEX", ARCH_CONF_BINHEX, 1 }, + { "ARCHIVE", "SIS", ARCH_CONF_SIS, 1 }, + { "ARCHIVE", "NSIS", ARCH_CONF_NSIS, 1 }, + { "ARCHIVE", "AUTOIT", ARCH_CONF_AUTOIT, 1 }, + { "ARCHIVE", "ISHIELD", ARCH_CONF_ISHIELD, 1 }, + { "ARCHIVE", "7zip", ARCH_CONF_7Z, 1 }, + { "ARCHIVE", "ISO9660", ARCH_CONF_ISO9660, 1 }, + { "ARCHIVE", "DMG", ARCH_CONF_DMG, 1 }, + { "ARCHIVE", "XAR", ARCH_CONF_XAR, 1 }, + { "ARCHIVE", "HFSPLUS", ARCH_CONF_HFSPLUS, 1 }, + { "ARCHIVE", "XZ", ARCH_CONF_XZ, 1 }, + + { "DOCUMENT", "HTML", DOC_CONF_HTML, 1 }, + { "DOCUMENT", "RTF", DOC_CONF_RTF, 1 }, + { "DOCUMENT", "PDF", DOC_CONF_PDF, 1 }, + { "DOCUMENT", "SCRIPT", DOC_CONF_SCRIPT, 1 }, { "DOCUMENT", "HTMLSKIPRAW", DOC_CONF_HTML_SKIPRAW, 1 }, { "DOCUMENT", "JSNORM", DOC_CONF_JSNORM, 1 }, - { "DOCUMENT", "SWF", DOC_CONF_SWF, 1 }, - - { "MAIL", "MBOX", MAIL_CONF_MBOX, 1 }, - { "MAIL", "TNEF", MAIL_CONF_TNEF, 1 }, - - { "OTHER", "UUENCODED", OTHER_CONF_UUENC, 1 }, - { "OTHER", "SCRENC", OTHER_CONF_SCRENC, 1 }, - { "OTHER", "RIFF", OTHER_CONF_RIFF, 1 }, - { "OTHER", "JPEG", OTHER_CONF_JPEG, 1 }, - { "OTHER", "CRYPTFF", OTHER_CONF_CRYPTFF, 1 }, - { "OTHER", "DLP", OTHER_CONF_DLP, 1 }, - { "OTHER", "MYDOOMLOG", OTHER_CONF_MYDOOMLOG, 1 }, + { "DOCUMENT", "SWF", DOC_CONF_SWF, 1 }, + + { "MAIL", "MBOX", MAIL_CONF_MBOX, 1 }, + { "MAIL", "TNEF", MAIL_CONF_TNEF, 1 }, + + { "OTHER", "UUENCODED", OTHER_CONF_UUENC, 1 }, + { "OTHER", "SCRENC", OTHER_CONF_SCRENC, 1 }, + { "OTHER", "RIFF", OTHER_CONF_RIFF, 1 }, + { "OTHER", "JPEG", OTHER_CONF_JPEG, 1 }, + { "OTHER", "CRYPTFF", OTHER_CONF_CRYPTFF, 1 }, + { "OTHER", "DLP", OTHER_CONF_DLP, 1 }, + { "OTHER", "MYDOOMLOG", OTHER_CONF_MYDOOMLOG, 1 }, { "OTHER", "PREFILTERING", OTHER_CONF_PREFILTERING,1 }, { "OTHER", "PDFNAMEOBJ", OTHER_CONF_PDFNAMEOBJ, 1 }, @@ -130,7 +130,10 @@ static struct dconf_module modules[] = { { "BYTECODE", "JIT PPC", BYTECODE_JIT_PPC, 1 }, { "BYTECODE", "JIT ARM", BYTECODE_JIT_ARM, 0 }, - { NULL, NULL, 0, 0 } + { "STATS", "DISABLED", DCONF_STATS_DISABLED, 0 }, + { "STATS", "PESECTION DISABLED", DCONF_STATS_PE_SECTION_DISABLED, 0 }, + + { NULL, NULL, 0, 0 } }; #ifdef USE_MPOOL @@ -139,48 +142,51 @@ struct cli_dconf *cli_dconf_init(mpool_t *mempool) struct cli_dconf *cli_dconf_init(void) #endif { - unsigned int i; - struct cli_dconf *dconf; + unsigned int i; + struct cli_dconf *dconf; dconf = (struct cli_dconf *) mpool_calloc(mempool, sizeof(struct cli_dconf), 1); if(!dconf) - return NULL; + return NULL; for(i = 0; modules[i].mname; i++) { - if(!strcmp(modules[i].mname, "PE")) { - if(modules[i].state) - dconf->pe |= modules[i].bflag; - - } else if(!strcmp(modules[i].mname, "ELF")) { - if(modules[i].state) - dconf->elf |= modules[i].bflag; - - } else if(!strcmp(modules[i].mname, "MACHO")) { - if(modules[i].state) - dconf->macho |= modules[i].bflag; - - } else if(!strcmp(modules[i].mname, "ARCHIVE")) { - if(modules[i].state) - dconf->archive |= modules[i].bflag; - - } else if(!strcmp(modules[i].mname, "DOCUMENT")) { - if(modules[i].state) - dconf->doc |= modules[i].bflag; - - } else if(!strcmp(modules[i].mname, "MAIL")) { - if(modules[i].state) - dconf->mail |= modules[i].bflag; - - } else if(!strcmp(modules[i].mname, "OTHER")) { - if(modules[i].state) - dconf->other |= modules[i].bflag; - } else if(!strcmp(modules[i].mname, "PHISHING")) { - if(modules[i].state) - dconf->phishing |= modules[i].bflag; - } else if(!strcmp(modules[i].mname, "BYTECODE")) { - if (modules[i].state) - dconf->bytecode |= modules[i].bflag; - } + if(!strcmp(modules[i].mname, "PE")) { + if(modules[i].state) + dconf->pe |= modules[i].bflag; + + } else if(!strcmp(modules[i].mname, "ELF")) { + if(modules[i].state) + dconf->elf |= modules[i].bflag; + + } else if(!strcmp(modules[i].mname, "MACHO")) { + if(modules[i].state) + dconf->macho |= modules[i].bflag; + + } else if(!strcmp(modules[i].mname, "ARCHIVE")) { + if(modules[i].state) + dconf->archive |= modules[i].bflag; + + } else if(!strcmp(modules[i].mname, "DOCUMENT")) { + if(modules[i].state) + dconf->doc |= modules[i].bflag; + + } else if(!strcmp(modules[i].mname, "MAIL")) { + if(modules[i].state) + dconf->mail |= modules[i].bflag; + + } else if(!strcmp(modules[i].mname, "OTHER")) { + if(modules[i].state) + dconf->other |= modules[i].bflag; + } else if(!strcmp(modules[i].mname, "PHISHING")) { + if(modules[i].state) + dconf->phishing |= modules[i].bflag; + } else if(!strcmp(modules[i].mname, "BYTECODE")) { + if (modules[i].state) + dconf->bytecode |= modules[i].bflag; + } else if (!strcmp(modules[i].mname, "STATS")) { + if (modules[i].state) + dconf->stats |= modules[i].bflag; + } } return dconf; @@ -188,128 +194,139 @@ struct cli_dconf *cli_dconf_init(void) void cli_dconf_print(struct cli_dconf *dconf) { - unsigned int pe = 0, elf = 0, macho = 0, arch = 0, doc = 0, mail = 0; - unsigned int other = 0, phishing = 0, i, bytecode=0; + unsigned int pe = 0, elf = 0, macho = 0, arch = 0, doc = 0, mail = 0; + unsigned int other = 0, phishing = 0, i, bytecode=0, stats=0; cli_dbgmsg("Dynamic engine configuration settings:\n"); cli_dbgmsg("--------------------------------------\n"); for(i = 0; modules[i].mname; i++) { - if(!strcmp(modules[i].mname, "PE")) { - if(!pe) { - cli_dbgmsg("Module PE: %s\n", dconf->pe ? "On" : "Off"); - pe = 1; - } - if(dconf->pe) - cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->pe & modules[i].bflag) ? "On" : "** Off **"); - else - continue; - - } else if(!strcmp(modules[i].mname, "ELF")) { - if(!elf) { - cli_dbgmsg("Module ELF: %s\n", dconf->elf ? "On" : "Off"); - elf = 1; - } - - } else if(!strcmp(modules[i].mname, "MACHO")) { - if(!macho) { - cli_dbgmsg("Module MACHO: %s\n", dconf->elf ? "On" : "Off"); - macho = 1; - } - - } else if(!strcmp(modules[i].mname, "ARCHIVE")) { - if(!arch) { - cli_dbgmsg("Module ARCHIVE: %s\n", dconf->archive ? "On" : "Off"); - arch = 1; - } - if(dconf->archive) - cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->archive & modules[i].bflag) ? "On" : "** Off **"); - else - continue; - - } else if(!strcmp(modules[i].mname, "DOCUMENT")) { - if(!doc) { - cli_dbgmsg("Module DOCUMENT: %s\n", dconf->doc ? "On" : "Off"); - doc = 1; - } - if(dconf->doc) - cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->doc & modules[i].bflag) ? "On" : "** Off **"); - else - continue; - - } else if(!strcmp(modules[i].mname, "MAIL")) { - if(!mail) { - cli_dbgmsg("Module MAIL: %s\n", dconf->mail ? "On" : "Off"); - mail = 1; - } - if(dconf->mail) - cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->mail & modules[i].bflag) ? "On" : "** Off **"); - else - continue; - - } else if(!strcmp(modules[i].mname, "OTHER")) { - if(!other) { - cli_dbgmsg("Module OTHER: %s\n", dconf->other ? "On" : "Off"); - other = 1; - } - if(dconf->other) - cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->other & modules[i].bflag) ? "On" : "** Off **"); - else - continue; - } else if(!strcmp(modules[i].mname, "PHISHING")) { - if(!phishing) { - cli_dbgmsg("Module PHISHING %s\n", dconf->phishing ? "On" : "Off"); - phishing = 1; - } - if(dconf->phishing) - cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->phishing & modules[i].bflag) ? "On" : "** Off **"); - else - continue; - } else if(!strcmp(modules[i].mname, "BYTECODE")) { - if(!bytecode) { - cli_dbgmsg("Module BYTECODE %s\n", dconf->bytecode ? "On" : "Off"); - bytecode = 1; - } - if(dconf->bytecode) - cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->bytecode & modules[i].bflag) ? "On" : "** Off **"); - else - continue; - } + if(!strcmp(modules[i].mname, "PE")) { + if(!pe) { + cli_dbgmsg("Module PE: %s\n", dconf->pe ? "On" : "Off"); + pe = 1; + } + + if(dconf->pe) + cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->pe & modules[i].bflag) ? "On" : "** Off **"); + else + continue; + } else if(!strcmp(modules[i].mname, "ELF")) { + if(!elf) { + cli_dbgmsg("Module ELF: %s\n", dconf->elf ? "On" : "Off"); + elf = 1; + } + } else if(!strcmp(modules[i].mname, "MACHO")) { + if(!macho) { + cli_dbgmsg("Module MACHO: %s\n", dconf->elf ? "On" : "Off"); + macho = 1; + } + } else if(!strcmp(modules[i].mname, "ARCHIVE")) { + if(!arch) { + cli_dbgmsg("Module ARCHIVE: %s\n", dconf->archive ? "On" : "Off"); + arch = 1; + } + + if(dconf->archive) + cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->archive & modules[i].bflag) ? "On" : "** Off **"); + else + continue; + } else if(!strcmp(modules[i].mname, "DOCUMENT")) { + if(!doc) { + cli_dbgmsg("Module DOCUMENT: %s\n", dconf->doc ? "On" : "Off"); + doc = 1; + } + + if(dconf->doc) + cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->doc & modules[i].bflag) ? "On" : "** Off **"); + else + continue; + } else if(!strcmp(modules[i].mname, "MAIL")) { + if(!mail) { + cli_dbgmsg("Module MAIL: %s\n", dconf->mail ? "On" : "Off"); + mail = 1; + } + + if(dconf->mail) + cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->mail & modules[i].bflag) ? "On" : "** Off **"); + else + continue; + } else if(!strcmp(modules[i].mname, "OTHER")) { + if(!other) { + cli_dbgmsg("Module OTHER: %s\n", dconf->other ? "On" : "Off"); + other = 1; + } + + if(dconf->other) + cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->other & modules[i].bflag) ? "On" : "** Off **"); + else + continue; + } else if(!strcmp(modules[i].mname, "PHISHING")) { + if(!phishing) { + cli_dbgmsg("Module PHISHING %s\n", dconf->phishing ? "On" : "Off"); + phishing = 1; + } + + if(dconf->phishing) + cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->phishing & modules[i].bflag) ? "On" : "** Off **"); + else + continue; + } else if(!strcmp(modules[i].mname, "BYTECODE")) { + if(!bytecode) { + cli_dbgmsg("Module BYTECODE %s\n", dconf->bytecode ? "On" : "Off"); + bytecode = 1; + } + + if(dconf->bytecode) + cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->bytecode & modules[i].bflag) ? "On" : "** Off **"); + else + continue; + } else if (!strcmp(modules[i].mname, "STATS")) { + if (!stats) { + cli_dbgmsg("Module STATS %s\n", dconf->stats ? "On" : "Off"); + stats = 1; + } + + if (dconf->stats) + cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->stats & modules[i].bflag) ? "On" : "** Off **"); + else + continue; + } } } static int chkflevel(const char *entry, int field) { - char *pt; + char *pt; if((pt = cli_strtok(entry, field, ":"))) { /* min version */ - if(!isdigit(*pt)) { - free(pt); - return 0; - } - - if((unsigned int) atoi(pt) > CL_FLEVEL_DCONF) { - free(pt); - return 0; - } - - free(pt); - - if((pt = cli_strtok(entry, field + 1, ":"))) { /* max version */ - if(!isdigit(*pt)) { - free(pt); - return 0; - } - - if((unsigned int) atoi(pt) < CL_FLEVEL_DCONF) { - free(pt); - return 0; - } - - free(pt); - } + if(!isdigit(*pt)) { + free(pt); + return 0; + } + + if((unsigned int) atoi(pt) > CL_FLEVEL_DCONF) { + free(pt); + return 0; + } + + free(pt); + + if((pt = cli_strtok(entry, field + 1, ":"))) { /* max version */ + if(!isdigit(*pt)) { + free(pt); + return 0; + } + + if((unsigned int) atoi(pt) < CL_FLEVEL_DCONF) { + free(pt); + return 0; + } + + free(pt); + } } return 1; @@ -317,101 +334,110 @@ static int chkflevel(const char *entry, int field) int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio) { - char buffer[FILEBUFF]; - unsigned int line = 0; - int ret = 0; - uint32_t val; + char buffer[FILEBUFF]; + unsigned int line = 0; + int ret = 0; + uint32_t val; while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) { - line++; - cli_chomp(buffer); - - if(!strncmp(buffer, "PE:", 3) && chkflevel(buffer, 2)) { - if(sscanf(buffer + 3, "0x%x", &val) == 1) { - engine->dconf->pe = val; - } else { - ret = CL_EMALFDB; - break; - } - } - - if(!strncmp(buffer, "ELF:", 4) && chkflevel(buffer, 2)) { - if(sscanf(buffer + 4, "0x%x", &val) == 1) { - engine->dconf->elf = val; - } else { - ret = CL_EMALFDB; - break; - } - } - - if(!strncmp(buffer, "MACHO:", 4) && chkflevel(buffer, 2)) { - if(sscanf(buffer + 4, "0x%x", &val) == 1) { - engine->dconf->macho = val; - } else { - ret = CL_EMALFDB; - break; - } - } - - if(!strncmp(buffer, "ARCHIVE:", 8) && chkflevel(buffer, 2)) { - if(sscanf(buffer + 8, "0x%x", &val) == 1) { - engine->dconf->archive = val; - } else { - ret = CL_EMALFDB; - break; - } - } - - if(!strncmp(buffer, "DOCUMENT:", 9) && chkflevel(buffer, 2)) { - if(sscanf(buffer + 9, "0x%x", &val) == 1) { - engine->dconf->doc = val; - } else { - ret = CL_EMALFDB; - break; - } - } - - if(!strncmp(buffer, "MAIL:", 5) && chkflevel(buffer, 2)) { - if(sscanf(buffer + 5, "0x%x", &val) == 1) { - engine->dconf->mail = val; - } else { - ret = CL_EMALFDB; - break; - } - } - - if(!strncmp(buffer, "OTHER:", 6) && chkflevel(buffer, 2)) { - if(sscanf(buffer + 6, "0x%x", &val) == 1) { - engine->dconf->other = val; - } else { - ret = CL_EMALFDB; - break; - } - } - - if(!strncmp(buffer, "PHISHING:", 9) && chkflevel(buffer, 2)) { - if(sscanf(buffer + 9, "0x%x", &val) == 1) { - engine->dconf->phishing = val; - } else { - ret = CL_EMALFDB; - break; - } - } - - if(!strncmp(buffer, "BYTECODE:", 9) && chkflevel(buffer, 2)) { - if(sscanf(buffer + 9, "0x%x", &val) == 1) { - engine->dconf->bytecode = val; - } else { - ret = CL_EMALFDB; - break; - } - } + line++; + cli_chomp(buffer); + + if(!strncmp(buffer, "PE:", 3) && chkflevel(buffer, 2)) { + if(sscanf(buffer + 3, "0x%x", &val) == 1) { + engine->dconf->pe = val; + } else { + ret = CL_EMALFDB; + break; + } + } + + if(!strncmp(buffer, "ELF:", 4) && chkflevel(buffer, 2)) { + if(sscanf(buffer + 4, "0x%x", &val) == 1) { + engine->dconf->elf = val; + } else { + ret = CL_EMALFDB; + break; + } + } + + if(!strncmp(buffer, "MACHO:", 4) && chkflevel(buffer, 2)) { + if(sscanf(buffer + 4, "0x%x", &val) == 1) { + engine->dconf->macho = val; + } else { + ret = CL_EMALFDB; + break; + } + } + + if(!strncmp(buffer, "ARCHIVE:", 8) && chkflevel(buffer, 2)) { + if(sscanf(buffer + 8, "0x%x", &val) == 1) { + engine->dconf->archive = val; + } else { + ret = CL_EMALFDB; + break; + } + } + + if(!strncmp(buffer, "DOCUMENT:", 9) && chkflevel(buffer, 2)) { + if(sscanf(buffer + 9, "0x%x", &val) == 1) { + engine->dconf->doc = val; + } else { + ret = CL_EMALFDB; + break; + } + } + + if(!strncmp(buffer, "MAIL:", 5) && chkflevel(buffer, 2)) { + if(sscanf(buffer + 5, "0x%x", &val) == 1) { + engine->dconf->mail = val; + } else { + ret = CL_EMALFDB; + break; + } + } + + if(!strncmp(buffer, "OTHER:", 6) && chkflevel(buffer, 2)) { + if(sscanf(buffer + 6, "0x%x", &val) == 1) { + engine->dconf->other = val; + } else { + ret = CL_EMALFDB; + break; + } + } + + if(!strncmp(buffer, "PHISHING:", 9) && chkflevel(buffer, 2)) { + if(sscanf(buffer + 9, "0x%x", &val) == 1) { + engine->dconf->phishing = val; + } else { + ret = CL_EMALFDB; + break; + } + } + + if(!strncmp(buffer, "BYTECODE:", 9) && chkflevel(buffer, 2)) { + if(sscanf(buffer + 9, "0x%x", &val) == 1) { + engine->dconf->bytecode = val; + } else { + ret = CL_EMALFDB; + break; + } + } + + if(!strncmp(buffer, "STATS:", 6) && chkflevel(buffer, 2)) { + if(sscanf(buffer + 6, "0x%x", &val) == 1) { + engine->dconf->stats = val; + } else { + ret = CL_EMALFDB; + break; + } + } } if(ret) { - cli_errmsg("Problem parsing configuration file at line %u\n", line); - return ret; + cli_errmsg("Problem parsing configuration file at line %u\n", line); + return ret; } return CL_SUCCESS; diff --git a/libclamav/dconf.h b/libclamav/dconf.h index 020941b7e..07c650c8a 100644 --- a/libclamav/dconf.h +++ b/libclamav/dconf.h @@ -40,6 +40,7 @@ struct cli_dconf { uint32_t other; uint32_t phishing; uint32_t bytecode; + uint32_t stats; }; /* PE flags */ @@ -121,6 +122,10 @@ struct cli_dconf { #define BYTECODE_JIT_PPC 0x4 #define BYTECODE_JIT_ARM 0x8 +/* Stats/Intel flags */ +#define DCONF_STATS_DISABLED 0x1 +#define DCONF_STATS_PE_SECTION_DISABLED 0x2 + #define BYTECODE_ENGINE_MASK (BYTECODE_INTERPRETER | BYTECODE_JIT_X86 | BYTECODE_JIT_PPC | BYTECODE_JIT_ARM) #ifdef USE_MPOOL diff --git a/libclamav/matcher.c b/libclamav/matcher.c index 7693fe8ac..76f350f6c 100644 --- a/libclamav/matcher.c +++ b/libclamav/matcher.c @@ -526,7 +526,7 @@ int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx) memset(§ions, 0x00, sizeof(stats_section_t)); if(do_dsig_check || ctx->engine->cb_stats_add_sample) { uint32_t flags = (do_dsig_check ? CL_CHECKFP_PE_FLAG_AUTHENTICODE : 0); - if (!(ctx->engine->engine_options & ENGINE_OPTIONS_DISABLE_PE_STATS)) + if (!(ctx->engine->engine_options & ENGINE_OPTIONS_DISABLE_PE_STATS) && !(ctx->engine->dconf->stats & (DCONF_STATS_DISABLED | DCONF_STATS_PE_SECTION_DISABLED))) flags |= CL_CHECKFP_PE_FLAG_STATS; switch(cli_checkfp_pe(ctx, shash1, §ions, flags)) { diff --git a/libclamav/stats.c b/libclamav/stats.c index 37df3ba84..9902a78d2 100644 --- a/libclamav/stats.c +++ b/libclamav/stats.c @@ -26,6 +26,7 @@ #include "libclamav/others.h" #include "libclamav/clamav.h" +#include "libclamav/dconf.h" #include "libclamav/json.h" #include "libclamav/stats.h" #include "libclamav/hostid.h" @@ -123,6 +124,9 @@ void clamav_stats_add_sample(const char *virname, const unsigned char *md5, size if (!(intel->engine)) return; + if (intel->engine->dconf->stats & DCONF_STATS_DISABLED) + return; + /* First check if we need to submit stats based on memory/number limits */ if ((intel->engine->cb_stats_get_size)) submit = (intel->engine->cb_stats_get_size(cbdata) >= intel->maxmem); @@ -309,6 +313,9 @@ void clamav_stats_submit(struct cl_engine *engine, void *cbdata) if (!(intel) || !(engine)) return; + if (engine->dconf->stats & DCONF_STATS_DISABLED) + return; + if (!(engine->cb_stats_get_hostid)) { /* Submitting stats is disabled due to HostID being turned off */ if ((engine->cb_stats_flush)) From 1bdaf8138938b786ea709e789867d5a0b423c3ab Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Tue, 4 Feb 2014 10:14:25 -0500 Subject: [PATCH 08/19] Update copyrights --- libclamav/dconf.c | 3 ++- libclamav/dconf.h | 3 ++- libclamav/hostid.c | 20 ++++++++++++++++++++ libclamav/hostid.h | 20 ++++++++++++++++++++ libclamav/json.c | 20 ++++++++++++++++++++ libclamav/json.h | 20 ++++++++++++++++++++ libclamav/stats.c | 20 ++++++++++++++++++++ libclamav/stats.h | 20 ++++++++++++++++++++ libclamav/www.c | 20 ++++++++++++++++++++ libclamav/www.h | 20 ++++++++++++++++++++ 10 files changed, 164 insertions(+), 2 deletions(-) diff --git a/libclamav/dconf.c b/libclamav/dconf.c index 2fd607c29..a81475501 100644 --- a/libclamav/dconf.c +++ b/libclamav/dconf.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2007-2008 Sourcefire, Inc. + * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. + * Copyright (C) 2007-2013 Sourcefire, Inc. * * Authors: Tomasz Kojm * diff --git a/libclamav/dconf.h b/libclamav/dconf.h index 07c650c8a..f44815a12 100644 --- a/libclamav/dconf.h +++ b/libclamav/dconf.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2007-2008 Sourcefire, Inc. + * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. + * Copyright (C) 2007-2013 Sourcefire, Inc. * * Authors: Tomasz Kojm * diff --git a/libclamav/hostid.c b/libclamav/hostid.c index da00eb1e8..dbd90fbf1 100644 --- a/libclamav/hostid.c +++ b/libclamav/hostid.c @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. + * + * Author: Shawn Webb + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + #if HAVE_CONFIG_H #include "clamav-config.h" #endif diff --git a/libclamav/hostid.h b/libclamav/hostid.h index 71c86fecf..1a5bd7cb2 100644 --- a/libclamav/hostid.h +++ b/libclamav/hostid.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. + * + * Author: Shawn Webb + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + #if !defined(_LIBCLAMAV_HOSTID_H) #define _LIBCLAMAV_HOSTID_H diff --git a/libclamav/json.c b/libclamav/json.c index 4edf3d6ec..b3684f52d 100644 --- a/libclamav/json.c +++ b/libclamav/json.c @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. + * + * Author: Shawn Webb + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + #include #include #include diff --git a/libclamav/json.h b/libclamav/json.h index 442bd3715..118f09d6c 100644 --- a/libclamav/json.h +++ b/libclamav/json.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. + * + * Author: Shawn Webb + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + #if !defined(_LIBCLAMAV_JSON_H) #define _LIBCLAMAV_JSON_H diff --git a/libclamav/stats.c b/libclamav/stats.c index 9902a78d2..4f30e4858 100644 --- a/libclamav/stats.c +++ b/libclamav/stats.c @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. + * + * Author: Shawn Webb + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + #if HAVE_CONFIG_H #include "clamav-config.h" #endif diff --git a/libclamav/stats.h b/libclamav/stats.h index 75e00ffad..402c06cf2 100644 --- a/libclamav/stats.h +++ b/libclamav/stats.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. + * + * Author: Shawn Webb + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + #if !defined(_LIBCLAMAV_STATS_H) #define _LIBCLAMAV_STATS_H diff --git a/libclamav/www.c b/libclamav/www.c index 7f1a17f79..f20065a7c 100644 --- a/libclamav/www.c +++ b/libclamav/www.c @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. + * + * Author: Shawn Webb + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + #include #include #include diff --git a/libclamav/www.h b/libclamav/www.h index dd805c731..334f0c047 100644 --- a/libclamav/www.h +++ b/libclamav/www.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. + * + * Author: Shawn Webb + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + #if !defined(_LIBCLAMAV_WWW_H) #define _LIBCLAMAV_WWW_H From 5fc847736c336eed6733d284c446404428632867 Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Tue, 4 Feb 2014 13:46:12 -0500 Subject: [PATCH 09/19] Fix a typo. Add support for getting the stats timeout from the engine --- libclamav/others.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libclamav/others.c b/libclamav/others.c index 5359d71dc..1781e0abd 100644 --- a/libclamav/others.c +++ b/libclamav/others.c @@ -549,6 +549,7 @@ int cl_engine_set_num(struct cl_engine *engine, enum cl_engine_field field, long intel->timeout = (uint32_t)num; } + break; default: cli_errmsg("cl_engine_set_num: Incorrect field number\n"); return CL_EARG; @@ -616,6 +617,8 @@ long long cl_engine_get_num(const struct cl_engine *engine, enum cl_engine_field return engine->bytecode_mode; case CL_ENGINE_DISABLE_CACHE: return engine->engine_options & ENGINE_OPTIONS_DISABLE_CACHE; + case CL_ENGINE_STATS_TIMEOUT: + return ((cli_intel_t *)(engine->stats_data))->timeout; default: cli_errmsg("cl_engine_get: Incorrect field number\n"); if(err) From 2e4613432eb8f951cc4dac934139601514fd4860 Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Wed, 5 Feb 2014 09:41:53 -0500 Subject: [PATCH 10/19] Don't free the options list too early --- clamd/clamd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/clamd/clamd.c b/clamd/clamd.c index 4752ebe76..e1e0b64c4 100644 --- a/clamd/clamd.c +++ b/clamd/clamd.c @@ -451,7 +451,6 @@ int main(int argc, char **argv) } else { if (strlen(p) > 36) { logg("!Invalid HostID\n"); - optfree(opts); cl_engine_set_clcb_stats_submit(engine, NULL); cl_engine_free(engine); ret = 1; From 06e02797fd549f7d6dfcefd74d97ec058ffdd938 Mon Sep 17 00:00:00 2001 From: Steven Morgan Date: Wed, 5 Feb 2014 10:58:16 -0500 Subject: [PATCH 11/19] additional manpage info for max-scansize. --- docs/man/clamd.conf.5.in | 2 +- docs/man/clamscan.1.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/man/clamd.conf.5.in b/docs/man/clamd.conf.5.in index 921e1be89..4c37c9117 100644 --- a/docs/man/clamd.conf.5.in +++ b/docs/man/clamd.conf.5.in @@ -505,7 +505,7 @@ Default: no Default: no .TP \fBMaxScanSize SIZE\fR -Sets the maximum amount of data to be scanned for each input file. Archives and other containers are recursively extracted and scanned up to this value. \fBWarning: disabling this limit or setting it too high may result in severe damage to the system.\fR +Sets the maximum amount of data to be scanned for each input file. Archives and other containers are recursively extracted and scanned up to this value. The size of an archive plus the sum of the sizes of all files within archive count toward the scan size. For example, a 1M uncompressed archive containing a single 1M inner file counts as 2M toward the max scan size. \fBWarning: disabling this limit or setting it too high may result in severe damage to the system.\fR .br Default: 100M .TP diff --git a/docs/man/clamscan.1.in b/docs/man/clamscan.1.in index 90253e615..b9b088412 100644 --- a/docs/man/clamscan.1.in +++ b/docs/man/clamscan.1.in @@ -178,7 +178,7 @@ Mark encrypted archives as viruses (Encrypted.Zip, Encrypted.RAR). Extract and scan at most #n bytes from each archive. You may pass the value in kilobytes in format xK or xk, or megabytes in format xM or xm, where x is a number. This option protects your system against DoS attacks (default: 25 MB, max: <4 GB) .TP \fB\-\-max\-scansize=#n\fR -Extract and scan at most #n bytes from each archive. You may pass the value in kilobytes in format xK or xk, or megabytes in format xM or xm, where x is a number. This option protects your system against DoS attacks (default: 100 MB, max: <4 GB) +Extract and scan at most #n bytes from each archive. The size the archive plus the sum of the sizes of all files within archive count toward the scan size. For example, a 1M uncompressed archive containing a single 1M inner file counts as 2M toward max-scansize. You may pass the value in kilobytes in format xK or xk, or megabytes in format xM or xm, where x is a number. This option protects your system against DoS attacks (default: 100 MB, max: <4 GB) .TP \fB\-\-max\-files=#n\fR Extract at most #n files from each scanned file (when this is an archive, a document or another kind of container). This option protects your system against DoS attacks (default: 10000) From 374f21dde95d1a799542826dc36e119b4f7abab8 Mon Sep 17 00:00:00 2001 From: Steven Morgan Date: Wed, 5 Feb 2014 11:00:23 -0500 Subject: [PATCH 12/19] xar: free up some xml memory. --- libclamav/xar.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libclamav/xar.c b/libclamav/xar.c index d5c03e8ff..20da56750 100644 --- a/libclamav/xar.c +++ b/libclamav/xar.c @@ -117,6 +117,8 @@ static void xar_get_checksum_values(xmlTextReaderPtr reader, unsigned char ** ck *hash = XAR_CKSUM_OTHER; } } + if (style != NULL) + xmlFree(style); if (xmlTextReaderRead(reader) == 1 && xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT) { xmlval = xmlTextReaderConstValue(reader); @@ -216,6 +218,8 @@ static int xar_get_toc_data_values(xmlTextReaderPtr reader, long *length, long * cli_dbgmsg("cli_scaxar: unknown style value=%s for encoding element\n", style); *encoding = CL_TYPE_ANY; } + if (style != NULL) + xmlFree(style); } else if (indata && xmlStrEqual(name, (const xmlChar *)"data") && xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT) { From 3fc1fc6985f4ea9056643c3d58448d6c2435e3a2 Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Wed, 5 Feb 2014 12:35:16 -0500 Subject: [PATCH 13/19] Fix accessing an array --- libclamav/stats.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/libclamav/stats.c b/libclamav/stats.c index 4f30e4858..a719bead9 100644 --- a/libclamav/stats.c +++ b/libclamav/stats.c @@ -198,6 +198,17 @@ void clamav_stats_add_sample(const char *virname, const unsigned char *md5, size if ((sample->virus_name)) { for (i=0; sample->virus_name[i] != NULL; i++) ; + p = realloc(sample->virus_name, sizeof(char **) * (i + 1)); + if (!(p)) { + free(sample->virus_name); + free(sample); + if (sample == intel->samples) + intel->samples = NULL; + + goto end; + } + + sample->virus_name = p; } else { i=0; sample->virus_name = calloc(1, sizeof(char **)); @@ -220,7 +231,7 @@ void clamav_stats_add_sample(const char *virname, const unsigned char *md5, size goto end; } - p = realloc(sample->virus_name, sizeof(char **) * (i == 0 ? 2 : i+1)); + p = realloc(sample->virus_name, sizeof(char **) * (i+2)); if (!(p)) { free(sample->virus_name); free(sample); From cd5ba2e93d4b0881c3e53dad563466e827bb6969 Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Wed, 5 Feb 2014 13:16:35 -0500 Subject: [PATCH 14/19] Add a Valgrind suppression rule for a known glibc bug in Ubuntu 13.10. Ubuntu introduced a non-critical bug in glibc that causes Valgrind to think that there's a problem. Sources: https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/1096826 https://sourceware.org/bugzilla/show_bug.cgi?id=14687 --- unit_tests/valgrind.supp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/unit_tests/valgrind.supp b/unit_tests/valgrind.supp index 6f55f1ded..079ffc1fd 100644 --- a/unit_tests/valgrind.supp +++ b/unit_tests/valgrind.supp @@ -57,3 +57,10 @@ fun:parseEmailHeader ... } +{ + ubuntu-libc-getaddrinfo-01 + Memcheck:Param + sendmsg(mmsg[0].msg_hdr) + fun:sendmmsg + ... +} From c50982c442b724cb571b53499847511027bbbdd5 Mon Sep 17 00:00:00 2001 From: David Raynor Date: Wed, 5 Feb 2014 16:37:24 -0500 Subject: [PATCH 15/19] bb#9156/10335: switch fanotify support to use sys/fanotify.h instead of coded syscalls --- ChangeLog | 4 ++++ clamd/fan-syscalllib.h | 28 ---------------------------- clamd/fan.c | 3 +-- configure | 4 ++-- configure.ac | 2 +- 5 files changed, 8 insertions(+), 33 deletions(-) delete mode 100644 clamd/fan-syscalllib.h diff --git a/ChangeLog b/ChangeLog index a19c3c015..62286952f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Wed Feb 5 14:30:24 2013 EDT 2013 (dar) +------------------------------------ + * bb#9156/10335: switch fanotify support to use sys/fanotify.h instead of coded syscalls + Mon Dec 5 18:10:24 2013 EDT 2013 (morgan) ------------------------------------ * bb#9595 fix for sigs targeted for ascii files containing offsets of the form EOF-n. diff --git a/clamd/fan-syscalllib.h b/clamd/fan-syscalllib.h deleted file mode 100644 index 288cd9926..000000000 --- a/clamd/fan-syscalllib.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __FANOTIFY_SYSCALL_LIB -#define __FANOTIFY_SYSCALL_LIB - -#include -#include - -#if defined(__x86_64__) -# define __NR_fanotify_init 300 -# define __NR_fanotify_mark 301 -#elif defined(__i386__) -# define __NR_fanotify_init 338 -# define __NR_fanotify_mark 339 -#else -# error "System call numbers not defined for this architecture" -#endif - -static inline int fanotify_init(unsigned int flags, unsigned int event_f_flags) -{ - return syscall(__NR_fanotify_init, flags, event_f_flags); -} - -static inline int fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, - int dfd, const char *pathname) -{ - return syscall(__NR_fanotify_mark, fanotify_fd, flags, mask, - dfd, pathname); -} -#endif diff --git a/clamd/fan.c b/clamd/fan.c index e4ec5a367..70da61d62 100644 --- a/clamd/fan.c +++ b/clamd/fan.c @@ -34,8 +34,7 @@ #include #include -#include -#include "fan-syscalllib.h" +#include #include "fan.h" #include "libclamav/clamav.h" diff --git a/configure b/configure index 717c216e6..941b43c9e 100755 --- a/configure +++ b/configure @@ -17890,8 +17890,8 @@ $as_echo "#define C_LINUX 1" >>confdefs.h THREAD_LIBS="-lpthread" TH_SAFE="-thread-safe" if test "$want_fanotify" = "yes"; then - ac_fn_c_check_header_mongrel "$LINENO" "linux/fanotify.h" "ac_cv_header_linux_fanotify_h" "$ac_includes_default" -if test "x$ac_cv_header_linux_fanotify_h" = xyes; then : + ac_fn_c_check_header_mongrel "$LINENO" "sys/fanotify.h" "ac_cv_header_sys_fanotify_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_fanotify_h" = xyes; then : $as_echo "#define FANOTIFY 1" >>confdefs.h diff --git a/configure.ac b/configure.ac index 4c0b8ed36..bd8c39f8e 100644 --- a/configure.ac +++ b/configure.ac @@ -1072,7 +1072,7 @@ linux*) THREAD_LIBS="-lpthread" TH_SAFE="-thread-safe" if test "$want_fanotify" = "yes"; then - AC_CHECK_HEADER([linux/fanotify.h],AC_DEFINE([FANOTIFY],1,[use fanotify]),) + AC_CHECK_HEADER([sys/fanotify.h],AC_DEFINE([FANOTIFY],1,[use fanotify]),) fi fi ;; From 3a65b26b39dcafc8eb449437b5f0216ff656d685 Mon Sep 17 00:00:00 2001 From: David Raynor Date: Wed, 5 Feb 2014 16:38:21 -0500 Subject: [PATCH 16/19] readdb: add comments with field layouts for LDB and FTM sigs --- libclamav/readdb.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libclamav/readdb.c b/libclamav/readdb.c index de8de1fe9..b6ecac9bd 100644 --- a/libclamav/readdb.c +++ b/libclamav/readdb.c @@ -1227,6 +1227,10 @@ static int lsigattribs(char *attribs, struct cli_lsig_tdb *tdb) mpool_free(x.mempool, x.macro_ptids);\ } while(0); +/* 0 1 2 3 4 5 ... (max 66) + * VirusName:Attributes:Logic:SubSig1[:SubSig2[:SubSig3 ... ]] + * NOTE: Maximum of 64 subsignatures (last would be token 66) + */ #define LDB_TOKENS 67 static int load_oneldb(char *buffer, int chkpua, struct cl_engine *engine, unsigned int options, const char *dbname, unsigned int line, unsigned int *sigs, unsigned bc_idx, const char *buffer_cpy, int *skip) { @@ -1580,6 +1584,9 @@ static int cli_loadcbc(FILE *fs, struct cl_engine *engine, unsigned int *signo, return CL_SUCCESS; } +/* 0 1 2 3 4 5 6 7 + * MagicType:Offset:HexSig:Name:RequiredType:DetectedType[:MinFL[:MaxFL]] + */ #define FTM_TOKENS 8 static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options, unsigned int internal, struct cli_dbio *dbio) { From 3e9e5e9041c10b71b9b0ab8fdab15ed527b58bc9 Mon Sep 17 00:00:00 2001 From: David Raynor Date: Thu, 6 Feb 2014 10:39:41 -0500 Subject: [PATCH 17/19] bb#9156/10335: update clamd autojunk for fanotify fix --- clamd/Makefile.am | 3 +-- clamd/Makefile.in | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/clamd/Makefile.am b/clamd/Makefile.am index 2955283c0..f3bec2387 100644 --- a/clamd/Makefile.am +++ b/clamd/Makefile.am @@ -46,8 +46,7 @@ clamd_SOURCES = \ others.h \ shared.h \ fan.c \ - fan.h \ - fan-syscalllib.h + fan.h AM_CFLAGS=@WERR_CFLAGS@ diff --git a/clamd/Makefile.in b/clamd/Makefile.in index c00dbbd76..8870bd4af 100644 --- a/clamd/Makefile.in +++ b/clamd/Makefile.in @@ -100,7 +100,7 @@ am__clamd_SOURCES_DIST = $(top_srcdir)/shared/output.c \ $(top_srcdir)/shared/misc.h clamd.c tcpserver.c tcpserver.h \ localserver.c localserver.h session.c session.h thrmgr.c \ thrmgr.h server-th.c server.h scanner.c scanner.h others.c \ - others.h shared.h fan.c fan.h fan-syscalllib.h + others.h shared.h fan.c fan.h @BUILD_CLAMD_TRUE@am_clamd_OBJECTS = output.$(OBJEXT) \ @BUILD_CLAMD_TRUE@ optparser.$(OBJEXT) getopt.$(OBJEXT) \ @BUILD_CLAMD_TRUE@ misc.$(OBJEXT) clamd.$(OBJEXT) \ From 0c58ddd290d63f65f4449d2470b7009e1a3e7b9c Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Thu, 6 Feb 2014 12:17:00 -0500 Subject: [PATCH 18/19] Fix some bugs --- clamd/clamd.c | 3 --- freshclam/notify.c | 9 ++++++--- libclamav/hostid.c | 9 +++------ libclamav/others.c | 1 + libclamav/stats.c | 2 +- libclamav/www.c | 5 ++++- 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/clamd/clamd.c b/clamd/clamd.c index e1e0b64c4..974511798 100644 --- a/clamd/clamd.c +++ b/clamd/clamd.c @@ -604,9 +604,6 @@ int main(int argc, char **argv) t = realloc(lsockets, sizeof(int) * (nlsockets + 1)); if (!(t)) { - if ((lsockets)) - free(lsockets); - ret = 1; break; } diff --git a/freshclam/notify.c b/freshclam/notify.c index 7bb24d712..6f234e6db 100644 --- a/freshclam/notify.c +++ b/freshclam/notify.c @@ -96,6 +96,8 @@ clamd_connect (const char *cfgfile, const char *option) return -11; } + return sockd; + } else #endif @@ -143,6 +145,7 @@ clamd_connect (const char *cfgfile, const char *option) optfree(opts); freeaddrinfo(res); + return sockd; } @@ -190,8 +193,8 @@ clamd_connect (const char *cfgfile, const char *option) return -1; } + return sockd; #endif - } else { @@ -202,7 +205,7 @@ clamd_connect (const char *cfgfile, const char *option) } optfree (opts); - return sockd; + return -1; } int @@ -229,7 +232,7 @@ notify (const char *cfgfile) { logg ("!NotifyClamd: Unknown answer from clamd: '%s'\n", buff); closesocket (sockd); - return 1; + return -1; } } diff --git a/libclamav/hostid.c b/libclamav/hostid.c index dbd90fbf1..5a026589f 100644 --- a/libclamav/hostid.c +++ b/libclamav/hostid.c @@ -202,8 +202,6 @@ struct device *get_devices(void) } #endif - close(sock); - p = realloc(devices, sizeof(struct device) * (ndevices + 1)); if (!(p)) goto err; @@ -215,9 +213,6 @@ struct device *get_devices(void) return devices; err: - if (addrs) - freeifaddrs(addrs); - if (devices) { for (i=0; i < ndevices; i++) if (devices[i].name) @@ -253,8 +248,10 @@ char *internal_get_host_id(void) return NULL; printable_md5 = calloc(1, 37); - if (!(printable_md5)) + if (!(printable_md5)) { + free(devices); return NULL; + } cli_md5_init(&ctx); for (i=0; devices[i].name != NULL; i++) diff --git a/libclamav/others.c b/libclamav/others.c index 1781e0abd..8aa371726 100644 --- a/libclamav/others.c +++ b/libclamav/others.c @@ -394,6 +394,7 @@ struct cl_engine *cl_engine_new(void) mpool_destroy(new->mempool); #endif free(new); + free(intel); return NULL; } #endif diff --git a/libclamav/stats.c b/libclamav/stats.c index a719bead9..dbc3375ed 100644 --- a/libclamav/stats.c +++ b/libclamav/stats.c @@ -223,8 +223,8 @@ void clamav_stats_add_sample(const char *virname, const unsigned char *md5, size sample->virus_name[i] = strdup((virname != NULL) ? virname : "[unknown]"); if (!(sample->virus_name[i])) { - free(sample); free(sample->virus_name); + free(sample); if (sample == intel->samples) intel->samples = NULL; diff --git a/libclamav/www.c b/libclamav/www.c index f20065a7c..2f65b0668 100644 --- a/libclamav/www.c +++ b/libclamav/www.c @@ -117,7 +117,8 @@ int connect_host(const char *host, const char *port, uint32_t timeout, int useAs if (!(p)) { freeaddrinfo(servinfo); - close(sockfd); + if (sockfd >= 0) + close(sockfd); return -1; } @@ -265,6 +266,8 @@ void submit_post(const char *host, const char *port, const char *method, const c if ((recvsz = recv(sockfd, buf, bufsz-1, 0) <= 0)) break; + buf[bufsz-1] = '\0'; + if (strstr(buf, "STATOK")) break; } From 33a3a88461f81777ad3131134b638f1a7033c5d9 Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Thu, 6 Feb 2014 16:54:29 -0500 Subject: [PATCH 19/19] Add IPv6 support to clamdtop --- clamdtop/clamdtop.c | 354 ++++++++++++++++++++++++-------------------- 1 file changed, 191 insertions(+), 163 deletions(-) diff --git a/clamdtop/clamdtop.c b/clamdtop/clamdtop.c index 80ff01f24..e4fb7d07d 100644 --- a/clamdtop/clamdtop.c +++ b/clamdtop/clamdtop.c @@ -510,77 +510,97 @@ static void print_con_info(conn_t *conn, const char *fmt, ...) static int make_connection_real(const char *soname, conn_t *conn) { - int s; - struct timeval tv; - conn->tcp = 0; -#ifdef _WIN32 - { -#else - if(cli_is_abspath(soname) || (access(soname, F_OK) == 0)) { - struct sockaddr_un addr; - s = socket(AF_UNIX, SOCK_STREAM, 0); - if(s < 0) { - perror("socket"); - return -1; - } - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, soname, sizeof(addr.sun_path)); - addr.sun_path[sizeof(addr.sun_path) - 1] = 0x0; - print_con_info(conn, "Connecting to: %s\n", soname); - if (connect(s, (struct sockaddr *)&addr, sizeof(addr))) { - perror("connect"); + int s; + struct timeval tv; + char *port; + char *name, *pt = strdup(soname); + const char *host = pt; + struct addrinfo hints, *res=NULL, *p; + + conn->tcp = 0; + +#ifndef _WIN32 + if(cli_is_abspath(soname) || (access(soname, F_OK) == 0)) { + struct sockaddr_un addr; + + s = socket(AF_UNIX, SOCK_STREAM, 0); + if(s < 0) { + perror("socket"); + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, soname, sizeof(addr.sun_path)); + addr.sun_path[sizeof(addr.sun_path) - 1] = 0x0; + + print_con_info(conn, "Connecting to: %s\n", soname); + if (connect(s, (struct sockaddr *)&addr, sizeof(addr))) { + perror("connect"); close(s); - return -1; - } - } else { + return -1; + } + + goto end; + } #endif - struct sockaddr_in server; - struct hostent *hp; - unsigned port = 0; - char *name, *pt = strdup(soname); - const char *host = pt; - memset(&server, 0x00, sizeof(struct sockaddr_in)); - conn->tcp=1; - name = strchr(pt, ':'); - if(name) { - *name++ = '\0'; - port = atoi(name); - } - if(!port) - port = 3310; - print_con_info(conn, "Looking up: %s\n", host); - if((hp = gethostbyname(host)) == NULL) { - fprintf(stderr, "Cannot find host"); - return -1; - } - free(pt); - s = socket(AF_INET, SOCK_STREAM, 0); - if(s < 0) { - perror("socket"); - return -1; - } - server.sin_family = AF_INET; - server.sin_port = htons(port); - server.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr))->s_addr; - print_con_info(conn, "Connecting to: %s:%u\n", inet_ntoa(server.sin_addr), port); - if (connect(s, (struct sockaddr *)&server, (socklen_t)sizeof(server))) { - perror("connect"); + + memset(&hints, 0x00, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + + conn->tcp=1; + name = strchr(pt, '/'); + if(name) { + *name = '\0'; + port = name+1; + } else { + port = NULL; + } + + print_con_info(conn, "Looking up: %s\n", host); + if (getaddrinfo(host, (port != NULL) ? port : "3310", &hints, &res)) + return -1; + + for (p = res; p != NULL; p = p->ai_next) { + if ((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) { + perror("socket"); + continue; + } + + print_con_info(conn, "Connecting to: %s:%s\n", host, port); + if (connect(s, p->ai_addr, p->ai_addrlen)) { + perror("connect"); close(s); - return -1; - } - } - if (conn->remote != soname) { - /* when we reconnect, they are the same */ - if (conn->remote) free(conn->remote); - conn->remote = strdup(soname); - } - conn->sd = s; - gettimeofday(&conn->tv_conn, NULL); - tv.tv_sec = 30; - tv.tv_usec = 0; - setsockopt(conn->sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); - return 0; + continue; + } + + break; + } + + free(pt); + + if (res) + freeaddrinfo(res); + + if (p == NULL) + return -1; + +end: + if (conn->remote != soname) { + /* when we reconnect, they are the same */ + if (conn->remote) + free(conn->remote); + + conn->remote = strdup(soname); + } + conn->sd = s; + gettimeofday(&conn->tv_conn, NULL); + tv.tv_sec = 30; + tv.tv_usec = 0; + setsockopt(conn->sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + return 0; } static int make_connection(const char *soname, conn_t *conn) @@ -588,20 +608,23 @@ static int make_connection(const char *soname, conn_t *conn) int rc; if ((rc = make_connection_real(soname, conn))) - return rc; + return rc; + send_string(conn, "nIDSESSION\nnVERSION\n"); free(conn->version); conn->version = NULL; if (!read_version(conn)) - return 0; + return 0; /* clamd < 0.95 */ if ((rc = make_connection_real(soname, conn))) - return rc; + return rc; + send_string(conn, "nSESSION\nnVERSION\n"); conn->version = NULL; if (!read_version(conn)) - return 0; + return 0; + return -1; } @@ -1109,7 +1132,7 @@ static void help(void) printf(" --version -V Show version\n"); printf(" --config-file=FILE -c FILE Read clamd's configuration files from FILE\n"); printf(" --defaultcolors -d Use default terminal colors\n"); - printf(" host[:port] Connect to clamd on host at port (default 3310)\n"); + printf(" host[/port] Connect to clamd on host at port (default 3310)\n"); printf(" /path/to/clamd.socket Connect to clamd over a local socket\n"); printf("\n"); return; @@ -1118,100 +1141,105 @@ static int default_colors=0; /* -------------------------- Initialization ---------------- */ static void setup_connections(int argc, char *argv[]) { - struct optstruct *opts; - struct optstruct *clamd_opts; - unsigned i; - char *conn = NULL; - - opts = optparse(NULL, argc, argv, 1, OPT_CLAMDTOP, 0, NULL); - if (!opts) { - fprintf(stderr, "ERROR: Can't parse command line options\n"); - EXIT_PROGRAM(FAIL_CMDLINE); - } - - if(optget(opts, "help")->enabled) { - optfree(opts); - help(); - normal_exit = 1; - exit(0); - } - - if(optget(opts, "version")->enabled) { - printf("Clam AntiVirus Monitoring Tool %s\n", get_version()); - optfree(opts); - normal_exit = 1; - exit(0); - } - - if(optget(opts, "defaultcolors")->enabled) - default_colors = 1; - memset(&global, 0, sizeof(global)); - if (!opts->filename || !opts->filename[0]) { - const struct optstruct *opt; - const char *clamd_conf = optget(opts, "config-file")->strarg; - - if ((clamd_opts = optparse(clamd_conf, 0, NULL, 1, OPT_CLAMD, 0, NULL)) == NULL) { - fprintf(stderr, "Can't parse clamd configuration file %s\n", clamd_conf); - EXIT_PROGRAM(FAIL_CMDLINE); - } - - if((opt = optget(clamd_opts, "LocalSocket"))->enabled) { - conn = strdup(opt->strarg); - if (!conn) { - fprintf(stderr, "Can't strdup LocalSocket value\n"); - EXIT_PROGRAM(FAIL_INITIAL_CONN); - } - } else if ((opt = optget(clamd_opts, "TCPSocket"))->enabled) { - char buf[512]; - const struct optstruct *opt_addr; - const char *host = "localhost"; - if ((opt_addr = optget(clamd_opts, "TCPAddr"))->enabled) { - host = opt_addr->strarg; - } - snprintf(buf, sizeof(buf), "%s:%llu", host, opt->numarg); - conn = strdup(buf); - } else { - fprintf(stderr, "Can't find how to connect to clamd\n"); - EXIT_PROGRAM(FAIL_INITIAL_CONN); - } - optfree(clamd_opts); - global.num_clamd = 1; - } else { - unsigned i = 0; - while (opts->filename[i]) { i++; } - global.num_clamd = i; - } + struct optstruct *opts; + struct optstruct *clamd_opts; + unsigned i; + char *conn = NULL; + + opts = optparse(NULL, argc, argv, 1, OPT_CLAMDTOP, 0, NULL); + if (!opts) { + fprintf(stderr, "ERROR: Can't parse command line options\n"); + EXIT_PROGRAM(FAIL_CMDLINE); + } + + if(optget(opts, "help")->enabled) { + optfree(opts); + help(); + normal_exit = 1; + exit(0); + } + + if(optget(opts, "version")->enabled) { + printf("Clam AntiVirus Monitoring Tool %s\n", get_version()); + optfree(opts); + normal_exit = 1; + exit(0); + } + + if(optget(opts, "defaultcolors")->enabled) + default_colors = 1; + + memset(&global, 0, sizeof(global)); + if (!opts->filename || !opts->filename[0]) { + const struct optstruct *opt; + const char *clamd_conf = optget(opts, "config-file")->strarg; + + if ((clamd_opts = optparse(clamd_conf, 0, NULL, 1, OPT_CLAMD, 0, NULL)) == NULL) { + fprintf(stderr, "Can't parse clamd configuration file %s\n", clamd_conf); + EXIT_PROGRAM(FAIL_CMDLINE); + } + + if((opt = optget(clamd_opts, "LocalSocket"))->enabled) { + conn = strdup(opt->strarg); + if (!conn) { + fprintf(stderr, "Can't strdup LocalSocket value\n"); + EXIT_PROGRAM(FAIL_INITIAL_CONN); + } + } else if ((opt = optget(clamd_opts, "TCPSocket"))->enabled) { + char buf[512]; + const struct optstruct *opt_addr; + const char *host = "localhost"; + if ((opt_addr = optget(clamd_opts, "TCPAddr"))->enabled) { + host = opt_addr->strarg; + } + snprintf(buf, sizeof(buf), "%s/%llu", host, opt->numarg); + conn = strdup(buf); + } else { + fprintf(stderr, "Can't find how to connect to clamd\n"); + EXIT_PROGRAM(FAIL_INITIAL_CONN); + } + + optfree(clamd_opts); + global.num_clamd = 1; + } else { + unsigned i = 0; + while (opts->filename[i]) { i++; } + global.num_clamd = i; + } #ifdef _WIN32 - WSADATA wsaData; - if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) { - fprintf(stderr, "Error at WSAStartup(): %d\n", WSAGetLastError()); - EXIT_PROGRAM(FAIL_INITIAL_CONN); - } + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) { + fprintf(stderr, "Error at WSAStartup(): %d\n", WSAGetLastError()); + EXIT_PROGRAM(FAIL_INITIAL_CONN); + } #endif - /* clamdtop */ - puts( " __ ____"); - puts(" _____/ /___ _____ ___ ____/ / /_____ ____"); - puts(" / ___/ / __ `/ __ `__ \\/ __ / __/ __ \\/ __ \\"); - puts("/ /__/ / /_/ / / / / / / /_/ / /_/ /_/ / /_/ /"); - puts("\\___/_/\\__,_/_/ /_/ /_/\\__,_/\\__/\\____/ .___/"); - puts(" /_/"); - global.all_stats = calloc(global.num_clamd, sizeof(*global.all_stats)); - OOM_CHECK(global.all_stats); - global.conn = calloc(global.num_clamd, sizeof(*global.conn)); - OOM_CHECK(global.conn); - for (i=0;i < global.num_clamd;i++) { - const char *soname = conn ? conn : opts->filename[i]; - global.conn[i].line = i+1; - if (make_connection(soname, &global.conn[i]) < 0) { - EXIT_PROGRAM(FAIL_INITIAL_CONN); - } - } - optfree(opts); - free(conn); + /* clamdtop */ + puts( " __ ____"); + puts(" _____/ /___ _____ ___ ____/ / /_____ ____"); + puts(" / ___/ / __ `/ __ `__ \\/ __ / __/ __ \\/ __ \\"); + puts("/ /__/ / /_/ / / / / / / /_/ / /_/ /_/ / /_/ /"); + puts("\\___/_/\\__,_/_/ /_/ /_/\\__,_/\\__/\\____/ .___/"); + puts(" /_/"); + + global.all_stats = calloc(global.num_clamd, sizeof(*global.all_stats)); + OOM_CHECK(global.all_stats); + global.conn = calloc(global.num_clamd, sizeof(*global.conn)); + OOM_CHECK(global.conn); + + for (i=0;i < global.num_clamd;i++) { + const char *soname = conn ? conn : opts->filename[i]; + global.conn[i].line = i+1; + if (make_connection(soname, &global.conn[i]) < 0) { + EXIT_PROGRAM(FAIL_INITIAL_CONN); + } + } + + optfree(opts); + free(conn); #ifndef _WIN32 - signal(SIGPIPE, SIG_IGN); - signal(SIGINT, sigint); + signal(SIGPIPE, SIG_IGN); + signal(SIGINT, sigint); #endif }