Browse code

clamd: add new commands DETSTATS and DETSTATSCLEAR (part of bb#2312)

Tomasz Kojm authored on 2010/11/03 21:41:06
Showing 9 changed files
... ...
@@ -1,3 +1,7 @@
1
+Wed Nov  3 13:38:47 CET 2010 (tk)
2
+---------------------------------
3
+ * clamd: add new commands DETSTATS and DETSTATSCLEAR (part of bb#2312)
4
+
1 5
 Tue Nov  2 13:01:14 EET 2010 (edwin)
2 6
 ------------------------------------
3 7
  * libclamav/7z.c: fix file descriptor leak (bb #2347)
... ...
@@ -426,9 +426,8 @@ int main(int argc, char **argv)
426 426
 	}
427 427
     }
428 428
 
429
-    if(optget(opts, "ExtendedDetectionInfo")->enabled)
430
-	cl_engine_set_clcb_hash(engine, hash_callback);
431
-
429
+    cl_engine_set_clcb_hash(engine, hash_callback);
430
+    detstats_clear();
432 431
 
433 432
     if(optget(opts, "LeaveTemporaryFiles")->enabled)
434 433
 	cl_engine_set_num(engine, CL_ENGINE_KEEPTMP, 1);
... ...
@@ -189,6 +189,8 @@ static void *clamukolegacyth(void *arg)
189 189
 	    context.virsize = 0;
190 190
 	    if(scan && cl_scanfile_callback(acc->filename, &virname, NULL, tharg->engine, tharg->options, &context) == CL_VIRUS) {
191 191
 		if(context.virsize)
192
+		    detstats_add(virname, acc->filename, context.virsize, context.virhash);
193
+		if(extinfo && context.virsize)
192 194
 		    logg("Clamuko: %s: %s(%s:%llu) FOUND\n", acc->filename, virname, context.virhash, context.virsize);
193 195
 		else
194 196
 		    logg("Clamuko: %s: %s FOUND\n", acc->filename, virname);
... ...
@@ -163,6 +163,8 @@ static void *clamuko_scanth(void *arg)
163 163
 			      tharg->options, &context) == CL_VIRUS) {
164 164
 	    dazukofs_get_filename(&acc, filename, sizeof(filename));
165 165
 	    if(context.virsize)
166
+		detstats_add(virname, filename, context.virsize, context.virhash);
167
+	    if(extinfo && context.virsize)
166 168
 		logg("Clamuko: %s: %s(%s:%llu) FOUND\n", filename, virname, context.virhash, context.virsize);
167 169
 	    else
168 170
 		logg("Clamuko: %s: %s FOUND\n", filename, virname);
... ...
@@ -87,6 +87,7 @@ void virusaction(const char *filename, const char *virname, const struct optstru
87 87
 #define VE_VIRUSNAME "CLAM_VIRUSEVENT_VIRUSNAME"
88 88
 
89 89
 static pthread_mutex_t virusaction_lock = PTHREAD_MUTEX_INITIALIZER;
90
+static pthread_mutex_t detstats_lock = PTHREAD_MUTEX_INITIALIZER;
90 91
 
91 92
 void virusaction(const char *filename, const char *virname, const struct optstruct *opts)
92 93
 {
... ...
@@ -670,3 +671,54 @@ void fds_free(struct fd_data *data)
670 670
     data->nfds = 0;
671 671
     fds_unlock(data);
672 672
 }
673
+
674
+struct detstats_s {
675
+    char virname[128];
676
+    char fname[128];
677
+    char md5[33];
678
+    unsigned int fsize;
679
+    unsigned int time;
680
+};
681
+#define DETSTATS_MAX 50
682
+static struct detstats_s detstats_data[DETSTATS_MAX];
683
+static unsigned int detstats_idx = 0, detstats_total = 0;
684
+
685
+void detstats_clear(void)
686
+{
687
+    pthread_mutex_lock(&detstats_lock);
688
+    detstats_idx = detstats_total = 0;
689
+    pthread_mutex_unlock(&detstats_lock);
690
+}
691
+
692
+void detstats_add(const char *virname, const char *fname, unsigned int fsize, const char *md5)
693
+{
694
+    pthread_mutex_lock(&detstats_lock);
695
+
696
+    strncpy(detstats_data[detstats_idx].virname, virname, sizeof(detstats_data[detstats_idx].virname));
697
+    detstats_data[detstats_idx].virname[sizeof(detstats_data[detstats_idx].virname) - 1] = 0;
698
+
699
+    if((fname = strrchr(fname, *PATHSEP)))
700
+	fname++;
701
+    strncpy(detstats_data[detstats_idx].fname, (fname || !strlen(fname)) ? "NOFNAME" : fname, sizeof(detstats_data[detstats_idx].fname));
702
+    detstats_data[detstats_idx].fname[sizeof(detstats_data[detstats_idx].fname) - 1] = 0;
703
+
704
+    strncpy(detstats_data[detstats_idx].md5, md5, sizeof(detstats_data[detstats_idx].md5));
705
+    detstats_data[detstats_idx].md5[sizeof(detstats_data[detstats_idx].md5) - 1] = 0;
706
+
707
+    detstats_data[detstats_idx].fsize = fsize;
708
+    detstats_data[detstats_idx++].time = time(NULL);
709
+    if(detstats_idx == DETSTATS_MAX)
710
+	detstats_idx = 0;
711
+    detstats_total++;
712
+    pthread_mutex_unlock(&detstats_lock);
713
+}
714
+
715
+void detstats_print(int desc, char term)
716
+{
717
+	unsigned int i;
718
+
719
+    pthread_mutex_lock(&detstats_lock);
720
+    for(i = 0; i < DETSTATS_MAX && i < detstats_total; i++)
721
+	mdprintf(desc, "%u:%s:%u:%s:%s%c", detstats_data[i].time, detstats_data[i].md5, detstats_data[i].fsize, detstats_data[i].virname, detstats_data[i].fname, term);
722
+    pthread_mutex_unlock(&detstats_lock);
723
+}
... ...
@@ -82,4 +82,8 @@ void fds_cleanup(struct fd_data *data);
82 82
 int fds_poll_recv(struct fd_data *data, int timeout, int check_signals, void *event);
83 83
 void fds_free(struct fd_data *data);
84 84
 
85
+void detstats_clear(void);
86
+void detstats_add(const char *virname, const char *fname, unsigned int fsize, const char *md5);
87
+void detstats_print(int desc, char term);
88
+
85 89
 #endif
... ...
@@ -244,6 +244,8 @@ int scan_callback(struct stat *sb, char *filename, const char *msg, enum cli_ftw
244 244
 	    return CL_ETIMEOUT;
245 245
 	}
246 246
 	if(context.virsize)
247
+	    detstats_add(virname, filename, context.virsize, context.virhash);
248
+	if(context.virsize && optget(scandata->opts, "ExtendedDetectionInfo")->enabled)
247 249
 	    logg("~%s: %s(%s:%llu) FOUND\n", filename, virname, context.virhash, context.virsize);
248 250
 	else
249 251
 	    logg("~%s: %s FOUND\n", filename, virname);
... ...
@@ -338,6 +340,8 @@ int scanfd(const int fd, const client_conn_t *conn, unsigned long int *scanned,
338 338
 		if (conn_reply_virus(conn, fdstr, virname, context.virhash, context.virsize) == -1)
339 339
 		    ret = CL_ETIMEOUT;
340 340
 		if(context.virsize)
341
+		    detstats_add(virname, "NOFNAME", context.virsize, context.virhash);
342
+		if(context.virsize && optget(opts, "ExtendedDetectionInfo")->enabled)
341 343
 		    logg("%s: %s(%s:%llu) FOUND\n", fdstr, virname, context.virhash, context.virsize);
342 344
 		else
343 345
 		    logg("%s: %s FOUND\n", fdstr, virname);
... ...
@@ -509,7 +513,9 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_engine *en
509 509
     closesocket(sockfd);
510 510
 
511 511
     if(ret == CL_VIRUS) {
512
-	if(context.virsize) {
512
+	if(context.virsize)
513
+	    detstats_add(virname, "NOFNAME", context.virsize, context.virhash);
514
+	if(context.virsize && optget(opts, "ExtendedDetectionInfo")->enabled) {
513 515
 	    mdprintf(odesc, "stream: %s(%s:%llu) FOUND%c", virname, context.virhash, context.virsize, term);
514 516
 	    logg("stream(%s@%u): %s(%s:%llu) FOUND\n", peer_addr, port, virname, context.virhash, context.virsize);
515 517
 	} else {
... ...
@@ -92,10 +92,11 @@ static struct {
92 92
     {CMD14, sizeof(CMD14)-1,	COMMAND_FILDES,	    0,	1, FEATURE_FDPASSING},
93 93
     {CMD15, sizeof(CMD15)-1,	COMMAND_STATS,	    0,	0, 1},
94 94
     {CMD16, sizeof(CMD16)-1,	COMMAND_IDSESSION,  0,	0, 1},
95
-    {CMD17, sizeof(CMD17)-1,	COMMAND_INSTREAM,   0,	0, 1}
95
+    {CMD17, sizeof(CMD17)-1,	COMMAND_INSTREAM,   0,	0, 1},
96
+    {CMD19, sizeof(CMD19)-1,	COMMAND_DETSTATSCLEAR,	0, 1, 1},
97
+    {CMD20, sizeof(CMD20)-1,	COMMAND_DETSTATS,   0, 1, 1}
96 98
 };
97 99
 
98
-
99 100
 enum commands parse_command(const char *cmd, const char **argument, int oldstyle)
100 101
 {
101 102
     size_t i;
... ...
@@ -571,6 +572,16 @@ int execute_or_dispatch_command(client_conn_t *conn, enum commands cmd, const ch
571 571
 		print_commands(desc, conn->term, engine);
572 572
 		return conn->group ? 0 : 1;
573 573
 	    }
574
+	case COMMAND_DETSTATSCLEAR:
575
+	    {
576
+		detstats_clear();
577
+		return 1;
578
+	    }
579
+	case COMMAND_DETSTATS:
580
+	    {
581
+		detstats_print(desc, conn->term);
582
+		return 1;
583
+	    }
574 584
 	case COMMAND_INSTREAM:
575 585
 	    {
576 586
 		int rc = cli_gentempfd(optget(conn->opts, "TemporaryDirectory")->strarg, &conn->filename, &conn->scanfd);
... ...
@@ -40,6 +40,8 @@
40 40
 #define CMD16 "IDSESSION"
41 41
 #define CMD17 "INSTREAM"
42 42
 #define CMD18 "VERSIONCOMMANDS"
43
+#define CMD19 "DETSTATSCLEAR"
44
+#define CMD20 "DETSTATS"
43 45
 
44 46
 #include "libclamav/clamav.h"
45 47
 #include "shared/optparser.h"
... ...
@@ -64,6 +66,8 @@ enum commands {
64 64
     COMMAND_IDSESSION,
65 65
     COMMAND_INSTREAM,
66 66
     COMMAND_COMMANDS,
67
+    COMMAND_DETSTATSCLEAR,
68
+    COMMAND_DETSTATS,
67 69
     /* internal commands */
68 70
     COMMAND_MULTISCANFILE,
69 71
     COMMAND_INSTREAMSCAN