clamd: add ExtendedDetectionInfo (bb#1228, #1626)

This commit is contained in:
Tomasz Kojm 2010-07-06 19:46:55 +02:00
parent fd45238eb6
commit edbba730b3
18 changed files with 128 additions and 24 deletions

View file

@ -1,3 +1,7 @@
Tue Jul 6 19:19:39 CEST 2010 (tk)
----------------------------------
* clamd: add ExtendedDetectionInfo (bb#1228, #1626)
Mon Jul 5 17:30:11 CEST 2010 (tk)
----------------------------------
* libclamav: fix some error messages (bb#2083)

View file

@ -33,6 +33,7 @@
#include <string.h>
#include "libclamav/clamav.h"
#include "libclamav/scanners.h"
#include "shared/optparser.h"
#include "shared/output.h"
@ -73,8 +74,10 @@ static void *clamukolegacyth(void *arg)
unsigned long mask = 0;
const struct optstruct *pt;
short int scan;
int sizelimit = 0;
int sizelimit = 0, extinfo;
struct stat sb;
char virhash[33];
unsigned int virsize;
clamuko_scanning = 0;
@ -166,6 +169,8 @@ static void *clamukolegacyth(void *arg)
else
logg("Clamuko: File size limit disabled.\n");
extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled;
while(1) {
if(dazukoGetAccess(&acc) == 0) {
@ -180,8 +185,11 @@ static void *clamukolegacyth(void *arg)
}
}
if(scan && cl_scanfile(acc->filename, &virname, NULL, tharg->engine, tharg->options) == CL_VIRUS) {
logg("Clamuko: %s: %s FOUND\n", acc->filename, virname);
if(scan && cli_scanfile_stats(acc->filename, &virname, virhash, &virsize, NULL, tharg->engine, tharg->options) == CL_VIRUS) {
if(extinfo && virsize)
logg("Clamuko: %s: %s(%s:%u) FOUND\n", acc->filename, virname, virhash, virsize);
else
logg("Clamuko: %s: %s FOUND\n", acc->filename, virname);
virusaction(acc->filename, virname, tharg->opts);
acc->deny = 1;
} else

View file

@ -32,6 +32,7 @@
#include <pthread.h>
#include "libclamav/clamav.h"
#include "libclamav/scanners.h"
#include "shared/optparser.h"
#include "shared/output.h"
@ -82,14 +83,14 @@ static void *clamuko_scanth(void *arg)
{
struct thrarg *tharg = (struct thrarg *) arg;
sigset_t sigset;
unsigned int sizelimit = 0;
unsigned int sizelimit = 0, virsize;
struct stat sb;
dazukofs_handle_t scan_hndl;
struct dazukofs_access acc;
const char *groupname = "ClamAV";
int skip_scan = 0;
int skip_scan = 0, extinfo;
const char *virname;
char filename[4096];
char filename[4096], virhash[33];
/* ignore all signals */
sigfillset(&sigset);
@ -130,6 +131,8 @@ static void *clamuko_scanth(void *arg)
else
logg("Clamuko: File size limit disabled.\n");
extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled;
while(1) {
if(dazukofs_get_access(scan_hndl, &acc)) {
if(!shutdown_hndl)
@ -152,10 +155,13 @@ static void *clamuko_scanth(void *arg)
acc.deny = 0;
/* reset skip flag */
skip_scan = 0;
} else if(cl_scandesc(acc.fd, &virname, NULL, tharg->engine,
} else if(cli_scandesc_stats(acc.fd, &virname, virhash, &virsize, NULL, tharg->engine,
tharg->options) == CL_VIRUS) {
dazukofs_get_filename(&acc, filename, sizeof(filename));
logg("Clamuko: %s: %s FOUND\n", filename, virname);
if(extinfo && virsize)
logg("Clamuko: %s: %s(%s:%u) FOUND\n", filename, virname, virhash, virsize);
else
logg("Clamuko: %s: %s FOUND\n", filename, virname);
/* we can not perform any special action because it will
* trigger DazukoFS recursively */
acc.deny = 1;

View file

@ -51,6 +51,7 @@
#include "libclamav/clamav.h"
#include "libclamav/others.h"
#include "libclamav/scanners.h"
#include "shared/optparser.h"
#include "shared/output.h"
@ -77,6 +78,8 @@ int scan_callback(struct stat *sb, char *filename, const char *msg, enum cli_ftw
const char *virname;
int ret;
int type = scandata->type;
char virhash[33];
unsigned int virsize;
/* detect disconnected socket,
* this should NOT detect half-shutdown sockets (SHUT_WR) */
@ -193,7 +196,7 @@ int scan_callback(struct stat *sb, char *filename, const char *msg, enum cli_ftw
thrmgr_setactivetask(filename,
type == TYPE_MULTISCAN ? "MULTISCANFILE" : NULL);
ret = cl_scanfile(filename, &virname, &scandata->scanned, scandata->engine, scandata->options);
ret = cli_scanfile_stats(filename, &virname, virhash, &virsize, &scandata->scanned, scandata->engine, scandata->options);
thrmgr_setactivetask(NULL, NULL);
if (thrmgr_group_need_terminate(scandata->conn->group)) {
@ -204,11 +207,16 @@ int scan_callback(struct stat *sb, char *filename, const char *msg, enum cli_ftw
if (ret == CL_VIRUS) {
scandata->infected++;
if (conn_reply(scandata->conn, filename, virname, "FOUND") == -1) {
if(!optget(scandata->opts, "ExtendedDetectionInfo")->enabled)
virsize = 0;
if (conn_reply_virus(scandata->conn, filename, virname, virhash, virsize) == -1) {
free(filename);
return CL_ETIMEOUT;
}
logg("~%s: %s FOUND\n", filename, virname);
if(virsize)
logg("~%s: %s(%s:%u) FOUND\n", filename, virname, virhash, virsize);
else
logg("~%s: %s FOUND\n", filename, virname);
virusaction(filename, virname, scandata->opts);
} else if (ret != CL_CLEAN) {
scandata->errors++;
@ -271,7 +279,8 @@ int scanfd(const int fd, const client_conn_t *conn, unsigned long int *scanned,
int ret;
const char *virname;
struct stat statbuf;
char fdstr[32];
char fdstr[32], virhash[33];
unsigned int virsize;
if (stream)
strncpy(fdstr, "stream", sizeof(fdstr));
@ -285,7 +294,7 @@ int scanfd(const int fd, const client_conn_t *conn, unsigned long int *scanned,
}
thrmgr_setactivetask(fdstr, NULL);
ret = cl_scandesc(fd, &virname, scanned, engine, options);
ret = cli_scandesc_stats(fd, &virname, virhash, &virsize, scanned, engine, options);
thrmgr_setactivetask(NULL, NULL);
if (thrmgr_group_need_terminate(conn->group)) {
@ -294,9 +303,14 @@ int scanfd(const int fd, const client_conn_t *conn, unsigned long int *scanned,
}
if(ret == CL_VIRUS) {
if (conn_reply(conn, fdstr, virname, "FOUND") == -1)
if(!optget(opts, "ExtendedDetectionInfo")->enabled)
virsize = 0;
if (conn_reply_virus(conn, fdstr, virname, virhash, virsize) == -1)
ret = CL_ETIMEOUT;
logg("%s: %s FOUND\n", fdstr, virname);
if(virsize)
logg("%s: %s(%s:%u) FOUND\n", fdstr, virname, virhash, virsize);
else
logg("%s: %s FOUND\n", fdstr, virname);
virusaction(fdstr, virname, opts);
} else if(ret != CL_CLEAN) {
if (conn_reply(conn, fdstr, cl_strerror(ret), "ERROR") == -1)
@ -315,12 +329,12 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_engine *en
{
int ret, sockfd, acceptd;
int tmpd, bread, retval, firsttimeout, timeout, btread;
unsigned int port = 0, portscan, min_port, max_port;
unsigned int port = 0, portscan, min_port, max_port, virsize;
unsigned long int quota = 0, maxsize = 0;
short bound = 0;
const char *virname;
char buff[FILEBUFF];
char peer_addr[32];
char peer_addr[32], virhash[33];
struct sockaddr_in server;
struct sockaddr_in peer;
socklen_t addrlen;
@ -448,7 +462,7 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_engine *en
if(retval == 1) {
lseek(tmpd, 0, SEEK_SET);
thrmgr_setactivetask(peer_addr, NULL);
ret = cl_scandesc(tmpd, &virname, scanned, engine, options);
ret = cli_scandesc_stats(tmpd, &virname, virhash, &virsize, scanned, engine, options);
thrmgr_setactivetask(NULL, NULL);
} else {
ret = -1;
@ -462,8 +476,13 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_engine *en
closesocket(sockfd);
if(ret == CL_VIRUS) {
mdprintf(odesc, "stream: %s FOUND%c", virname, term);
logg("stream(%s@%u): %s FOUND\n", peer_addr, port, virname);
if(optget(opts, "ExtendedDetectionInfo")->enabled && virsize) {
mdprintf(odesc, "stream: %s(%s:%u) FOUND%c", virname, virhash, virsize, term);
logg("stream(%s@%u): %s(%s:%u) FOUND\n", peer_addr, port, virname, virhash, virsize);
} else {
mdprintf(odesc, "stream: %s FOUND%c", virname, term);
logg("stream(%s@%u): %s FOUND\n", peer_addr, port, virname);
}
virusaction("stream", virname, opts);
} else if(ret != CL_CLEAN) {
if(retval == 1) {

View file

@ -154,6 +154,22 @@ int conn_reply(const client_conn_t *conn, const char *path,
return mdprintf(conn->sd, "%s %s%c", msg, status, conn->term);
}
int conn_reply_virus(const client_conn_t *conn, const char *file,
const char *virname, const char *virhash, unsigned int virsize)
{
if (conn->id) {
if (virsize)
return mdprintf(conn->sd, "%u: %s: %s(%s:%u) FOUND%c", conn->id, file,
virname, virhash, virsize, conn->term);
return mdprintf(conn->sd, "%u: %s: %s FOUND%c", conn->id, file, virname,
conn->term);
}
if (virsize)
return mdprintf(conn->sd, "%s: %s(%s:%u) FOUND%c", file, virname, virhash,
virsize, conn->term);
return mdprintf(conn->sd, "%s: %s FOUND%c", file, virname, conn->term);
}
int conn_reply_error(const client_conn_t *conn, const char *msg)
{
return conn_reply(conn, NULL, msg, "ERROR");

View file

@ -92,6 +92,7 @@ int execute_or_dispatch_command(client_conn_t *conn, enum commands command, cons
int conn_reply(const client_conn_t *conn, const char *path, const char *msg, const char *status);
int conn_reply_single(const client_conn_t *conn, const char *path, const char *status);
int conn_reply_virus(const client_conn_t *conn, const char *file, const char *virname, const char *virhash, unsigned int virsize);
int conn_reply_error(const client_conn_t *conn, const char *msg);
int conn_reply_errno(const client_conn_t *conn, const char *path, const char *msg);
#endif

View file

@ -66,6 +66,11 @@ Enable verbose logging.
.br
Default: no
.TP
\fBExtendedDetectionInfo BOOL\fR
Provide additional information about the infected file, such as its size and hash, together with the virus name. It's recommended to enable this option along with SubmitDetectionStats in freshclam.conf.
.br
Default: no
.TP
\fBPidFile STRING\fR
Save the process identifier of a listening daemon (main thread) to a specified file.
.br

View file

@ -155,7 +155,7 @@ Timeout in seconds when reading from database server.
Default: 30
.TP
\fBSubmitDetectionStats STRING\fR
When enabled freshclam will submit statistics to the ClamAV Project about the latest virus detections in your environment. The ClamAV maintainers will then use this data to determine what types of malware are the most detected in the field and in what geographic area they are. This feature requires LogTime and LogFile to be enabled in clamd.conf. The path for clamd.conf file must be provided.
When enabled freshclam will submit statistics to the ClamAV Project about the latest virus detections in your environment. The ClamAV maintainers will then use this data to determine what types of malware are the most detected in the field and in what geographic area they are. This feature requires LogTime and LogFile to be enabled in clamd.conf, it's also recommended to turn on ExtendedDetectionInfo. The path for clamd.conf file must be provided.
.br
Default: disabled
.TP

View file

@ -51,6 +51,11 @@ Example
# Default: no
#LogVerbose yes
# Provide additional information about the infected file, such as its
# size and hash, together with the virus name. It's recommended to enable
# this option along with SubmitDetectionStats in freshclam.conf.
#ExtendedDetectionInfo yes
# This option allows you to save a process identifier of the listening
# daemon (main thread).
# Default: disabled

View file

@ -152,7 +152,8 @@ DatabaseMirror database.clamav.net
# the latest virus detections in your environment. The ClamAV maintainers
# will then use this data to determine what types of malware are the most
# detected in the field and in what geographic area they are.
# This feature requires LogTime and LogFile to be enabled in clamd.conf.
# This feature requires LogTime and LogFile to be enabled in clamd.conf,
# it's also recommended to turn on ExtendedDetectionInfo.
# Default: no
#SubmitDetectionStats /path/to/clamd.conf

View file

@ -582,6 +582,7 @@ int submitstats(const char *clamdcfg, const struct optstruct *opts)
if(!(opt = optget(clamdopt, "LogFile"))->enabled) {
logg("!SubmitDetectionStats: LogFile needs to be enabled in %s\n", clamdcfg);
logg("SubmitDetectionStats: Please consider enabling ExtendedDetectionInfo\n");
optfree(clamdopt);
return 56;
}

View file

@ -128,6 +128,8 @@ CLAMAV_PRIVATE {
cli_initroots;
cli_scanbuff;
cli_fmap_scandesc;
cli_scandesc_stats;
cli_scanfile_stats;
html_screnc_decode;
mpool_create;
mpool_calloc;

View file

@ -419,6 +419,13 @@ int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx)
}
#endif
if(ctx->virsize && !*ctx->virsize) {
if(ctx->virsize)
*ctx->virsize = size;
if(ctx->virhash)
strcpy(ctx->virhash, md5);
}
return CL_VIRUS;
}

View file

@ -109,6 +109,8 @@ typedef struct bitset_tag
/* internal clamav context */
typedef struct cli_ctx_tag {
const char **virname;
char *virhash;
unsigned int *virsize;
unsigned long int *scanned;
const struct cli_matcher *root;
const struct cl_engine *engine;

View file

@ -2368,7 +2368,7 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
}
}
int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions)
int cli_scandesc_stats(int desc, const char **virname, char *virhash, unsigned int *virsize, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions)
{
cli_ctx ctx;
int rc;
@ -2376,6 +2376,11 @@ int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, cons
memset(&ctx, '\0', sizeof(cli_ctx));
ctx.engine = engine;
ctx.virname = virname;
if(virsize) {
*virsize = 0;
ctx.virsize = virsize;
ctx.virhash = virhash;
}
ctx.scanned = scanned;
ctx.options = scanoptions;
ctx.found_possibly_unwanted = 0;
@ -2414,6 +2419,11 @@ int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, cons
return rc;
}
int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions)
{
return cli_scandesc_stats(desc, virname, NULL, NULL, scanned, engine, scanoptions);
}
int cli_found_possibly_unwanted(cli_ctx* ctx)
{
if(ctx->virname) {
@ -2463,6 +2473,19 @@ int cl_scanfile(const char *filename, const char **virname, unsigned long int *s
return ret;
}
int cli_scanfile_stats(const char *filename, const char **virname, char *virhash, unsigned int *virsize, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions)
{
int fd, ret;
if((fd = safe_open(filename, O_RDONLY|O_BINARY)) == -1)
return CL_EOPEN;
ret = cli_scandesc_stats(fd, virname, virhash, virsize, scanned, engine, scanoptions);
close(fd);
return ret;
}
/*
Local Variables:
c-basic-offset: 4

View file

@ -26,5 +26,7 @@
int cli_magic_scandesc(int desc, cli_ctx *ctx);
int cli_found_possibly_unwanted(cli_ctx* ctx);
int cli_scandesc_stats(int desc, const char **virname, char *virhash, unsigned int *virsize, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions);
int cli_scanfile_stats(const char *filename, const char **virname, char *virhash, unsigned int *virsize, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions);
#endif

View file

@ -177,6 +177,8 @@ const struct clam_option __clam_options[] = {
{ "LogVerbose", NULL, 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Enable verbose logging.", "yes" },
{ "ExtendedDetectionInfo", NULL, 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Provide additional information about the infected file, such as its\nsize and hash, together with the virus name.", "yes" },
{ "PidFile", "pid", 'p', TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Save the process ID to a file.", "/var/run/clam.pid" },
{ "TemporaryDirectory", "tempdir", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD | OPT_MILTER | OPT_CLAMSCAN | OPT_SIGTOOL, "This option allows you to change the default temporary directory.", "/tmp" },

View file

@ -502,7 +502,7 @@
/* #undef USE_SYSLOG */
/* Version number of package */
#define VERSION "devel-clamav-0.96-186-g5f12eac"
#define VERSION "devel-clamav-0.96-192-gfd45238"
/* Version suffix for package */
#define VERSION_SUFFIX ""