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/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) \ diff --git a/clamd/clamd.c b/clamd/clamd.c index c89808635..974511798 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; @@ -447,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; @@ -601,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/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/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 } diff --git a/clamscan/manager.c b/clamscan/manager.c index 955431198..d7a32c3c5 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/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 ;; 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) 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/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/clamav.h b/libclamav/clamav.h index 855991831..e1c3f74ad 100644 --- a/libclamav/clamav.h +++ b/libclamav/clamav.h @@ -206,6 +206,7 @@ enum cl_engine_field { CL_ENGINE_FORCETODISK, /* uint32_t */ CL_ENGINE_DISABLE_CACHE, /* uint32_t */ CL_ENGINE_DISABLE_PE_STATS, /* uint32_t */ + CL_ENGINE_STATS_TIMEOUT, /* uint32_t */ CL_ENGINE_MAX_PARTITIONS /* uint32_t */ }; diff --git a/libclamav/dconf.c b/libclamav/dconf.c index df49fb1b7..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 * @@ -38,10 +39,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 +53,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 +131,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 +143,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 +195,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 +335,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..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 * @@ -40,6 +41,7 @@ struct cli_dconf { uint32_t other; uint32_t phishing; uint32_t bytecode; + uint32_t stats; }; /* PE flags */ @@ -121,6 +123,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/hostid.c b/libclamav/hostid.c index 38fc75d15..5a026589f 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 @@ -155,8 +175,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; @@ -184,8 +202,6 @@ struct device *get_devices(void) } #endif - close(sock); - p = realloc(devices, sizeof(struct device) * (ndevices + 1)); if (!(p)) goto err; @@ -197,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) @@ -235,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/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/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/others.c b/libclamav/others.c index cd69a2388..b9ff0b253 100644 --- a/libclamav/others.c +++ b/libclamav/others.c @@ -394,12 +394,14 @@ struct cl_engine *cl_engine_new(void) mpool_destroy(new->mempool); #endif free(new); + free(intel); return NULL; } #endif 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; @@ -529,25 +531,32 @@ int cl_engine_set_num(struct cl_engine *engine, enum cl_engine_field field, long if (num == CL_BYTECODE_MODE_TEST) cli_infomsg(NULL, "bytecode engine in test mode\n"); break; - case CL_ENGINE_DISABLE_CACHE: - if (num) { - engine->engine_options |= ENGINE_OPTIONS_DISABLE_CACHE; - } else { - engine->engine_options &= ~(ENGINE_OPTIONS_DISABLE_CACHE); - if (!(engine->cache)) - cli_cache_init(engine); - } - break; - case CL_ENGINE_DISABLE_PE_STATS: - if (num) { - engine->engine_options |= ENGINE_OPTIONS_DISABLE_PE_STATS; - } else { - engine->engine_options &= ~(ENGINE_OPTIONS_DISABLE_PE_STATS); - } - break; - case CL_ENGINE_MAX_PARTITIONS: - engine->maxpartitions = (uint32_t)num; - break; + case CL_ENGINE_DISABLE_CACHE: + if (num) { + engine->engine_options |= ENGINE_OPTIONS_DISABLE_CACHE; + } else { + engine->engine_options &= ~(ENGINE_OPTIONS_DISABLE_CACHE); + if (!(engine->cache)) + cli_cache_init(engine); + } + break; + case CL_ENGINE_DISABLE_PE_STATS: + if (num) { + engine->engine_options |= ENGINE_OPTIONS_DISABLE_PE_STATS; + } else { + 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; + } + break; + case CL_ENGINE_MAX_PARTITIONS: + engine->maxpartitions = (uint32_t)num; + break; default: cli_errmsg("cl_engine_set_num: Incorrect field number\n"); return CL_EARG; @@ -613,10 +622,12 @@ long long cl_engine_get_num(const struct cl_engine *engine, enum cl_engine_field return engine->bytecode_timeout; case CL_ENGINE_BYTECODE_MODE: return engine->bytecode_mode; - case CL_ENGINE_DISABLE_CACHE: - return engine->engine_options & ENGINE_OPTIONS_DISABLE_CACHE; - case CL_ENGINE_MAX_PARTITIONS: - return engine->maxpartitions; + 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; + case CL_ENGINE_MAX_PARTITIONS: + return engine->maxpartitions; default: cli_errmsg("cl_engine_get: Incorrect field number\n"); if(err) diff --git a/libclamav/others.h b/libclamav/others.h index 74e09e828..88a4c841d 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/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) { diff --git a/libclamav/stats.c b/libclamav/stats.c index bae4d474c..dbc3375ed 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 @@ -26,12 +46,13 @@ #include "libclamav/others.h" #include "libclamav/clamav.h" +#include "libclamav/dconf.h" #include "libclamav/json.h" #include "libclamav/stats.h" #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); @@ -123,6 +144,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); @@ -174,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 **)); @@ -188,15 +223,15 @@ 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; 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); @@ -229,8 +264,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: @@ -311,6 +344,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)) @@ -355,8 +391,7 @@ 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); + submit_post(STATS_HOST, STATS_PORT, "PUT", "/clamav/1/submit/stats", json, myintel.timeout); free(json); } 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 bd39469a2..2f65b0668 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 @@ -24,7 +44,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 +87,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); @@ -97,7 +117,8 @@ int connect_host(const char *host, const char *port, int useAsync) if (!(p)) { freeaddrinfo(servinfo); - close(sockfd); + if (sockfd >= 0) + close(sockfd); return -1; } @@ -150,7 +171,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 +235,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 +256,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; @@ -245,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; } diff --git a/libclamav/www.h b/libclamav/www.h index 4ed388d0a..334f0c047 100644 --- a/libclamav/www.h +++ b/libclamav/www.h @@ -1,9 +1,29 @@ +/* + * 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 -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/libclamav/xar.c b/libclamav/xar.c index de2f138c7..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) { @@ -290,7 +294,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 +303,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 +415,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 +573,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 +582,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 +595,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 +622,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 +670,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 +701,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 +721,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 +730,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 +779,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 +846,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; } diff --git a/shared/optparser.c b/shared/optparser.c index c48830727..a34750554 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, "", "" }, @@ -185,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" }, diff --git a/sigtool/sigtool.c b/sigtool/sigtool.c index 735458ede..704772a74 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) { @@ -2903,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"); @@ -2925,23 +2927,36 @@ 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(" --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"); 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"); 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"); diff --git a/unit_tests/valgrind.supp b/unit_tests/valgrind.supp index 815511081..079ffc1fd 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 @@ -49,3 +57,10 @@ fun:parseEmailHeader ... } +{ + ubuntu-libc-getaddrinfo-01 + Memcheck:Param + sendmsg(mmsg[0].msg_hdr) + fun:sendmmsg + ... +}