Conflicts:
libclamav/stats.h
... | ... |
@@ -220,7 +220,15 @@ enum bytecode_mode { |
220 | 220 |
CL_BYTECODE_MODE_OFF /* for query only, not settable */ |
221 | 221 |
}; |
222 | 222 |
|
223 |
-typedef enum cli_intel_sample_type { WHOLEFILE = 0, PESECTION = 1 } cli_intel_sample_type_t; /* For stats/intel gathering */ |
|
223 |
+struct cli_section_hash { |
|
224 |
+ unsigned char md5[16]; |
|
225 |
+ size_t len; |
|
226 |
+}; |
|
227 |
+ |
|
228 |
+typedef struct cli_stats_sections { |
|
229 |
+ size_t nsections; |
|
230 |
+ struct cli_section_hash *sections; |
|
231 |
+} stats_section_t; |
|
224 | 232 |
|
225 | 233 |
extern int cl_engine_set_num(struct cl_engine *engine, enum cl_engine_field field, long long num); |
226 | 234 |
|
... | ... |
@@ -360,13 +368,13 @@ extern void cl_engine_set_clcb_meta(struct cl_engine *engine, clcb_meta callback |
360 | 360 |
/* Statistics/intelligence gathering callbacks */ |
361 | 361 |
extern void cl_engine_set_stats_set_cbdata(struct cl_engine *engine, void *cbdata); |
362 | 362 |
|
363 |
-typedef void (*clcb_stats_add_sample)(const char *virname, const unsigned char *md5, size_t size, cli_intel_sample_type_t type, void *cbdata); |
|
363 |
+typedef void (*clcb_stats_add_sample)(const char *virname, const unsigned char *md5, size_t size, stats_section_t *sections, void *cbdata); |
|
364 | 364 |
extern void cl_engine_set_clcb_stats_add_sample(struct cl_engine *engine, clcb_stats_add_sample callback); |
365 | 365 |
|
366 |
-typedef void (*clcb_stats_remove_sample)(const char *virname, const unsigned char *md5, size_t size, cli_intel_sample_type_t type, void *cbdata); |
|
366 |
+typedef void (*clcb_stats_remove_sample)(const char *virname, const unsigned char *md5, size_t size, void *cbdata); |
|
367 | 367 |
extern void cl_engine_set_clcb_stats_remove_sample(struct cl_engine *engine, clcb_stats_remove_sample callback); |
368 | 368 |
|
369 |
-typedef void (*clcb_stats_decrement_count)(const char *virname, const unsigned char *md5, size_t size, cli_intel_sample_type_t type, void *cbdata); |
|
369 |
+typedef void (*clcb_stats_decrement_count)(const char *virname, const unsigned char *md5, size_t size, void *cbdata); |
|
370 | 370 |
extern void cl_engine_set_clcb_stats_decrement_count(struct cl_engine *engine, clcb_stats_decrement_count callback); |
371 | 371 |
|
372 | 372 |
typedef void (*clcb_stats_submit)(struct cl_engine *engine, void *cbdata); |
... | ... |
@@ -30,18 +30,6 @@ char *hex_encode(char *buf, char *data, size_t len) |
30 | 30 |
return p; |
31 | 31 |
} |
32 | 32 |
|
33 |
-const char *get_sample_type(cli_intel_sample_type_t type) |
|
34 |
-{ |
|
35 |
- switch (type) { |
|
36 |
- case WHOLEFILE: |
|
37 |
- return "whole-file"; |
|
38 |
- case PESECTION: |
|
39 |
- return "PE section"; |
|
40 |
- default: |
|
41 |
- return NULL; |
|
42 |
- } |
|
43 |
-} |
|
44 |
- |
|
45 | 33 |
char *ensure_bufsize(char *buf, size_t *oldsize, size_t used, size_t additional) |
46 | 34 |
{ |
47 | 35 |
char *p=buf; |
... | ... |
@@ -106,19 +94,6 @@ char *export_stats_to_json(struct cl_engine *engine, cli_intel_t *intel) |
106 | 106 |
snprintf(buf+curused, bufsz-curused, "\t\t\t\"hash\": \"%s\",\n", md5); |
107 | 107 |
curused += strlen(buf+curused); |
108 | 108 |
|
109 |
- type = get_sample_type(sample->type); |
|
110 |
- if (!(type)) { |
|
111 |
- free(buf); |
|
112 |
- return NULL; |
|
113 |
- } |
|
114 |
- |
|
115 |
- buf = ensure_bufsize(buf, &bufsz, curused, sizeof("type") + strlen(type) + 15); |
|
116 |
- if (!(buf)) |
|
117 |
- return NULL; |
|
118 |
- |
|
119 |
- snprintf(buf+curused, bufsz-curused, "\t\t\t\"type\": \"%s\",\n", type); |
|
120 |
- curused += strlen(buf+curused); |
|
121 |
- |
|
122 | 109 |
/* Reuse the md5 variable for serializing the number of hits */ |
123 | 110 |
snprintf(md5, sizeof(md5), "%u", sample->hits); |
124 | 111 |
|
... | ... |
@@ -428,6 +428,7 @@ int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx) |
428 | 428 |
uint8_t shash1[SHA1_HASH_SIZE*2+1]; |
429 | 429 |
uint8_t shash256[SHA256_HASH_SIZE*2+1]; |
430 | 430 |
int have_sha1, have_sha256, do_dsig_check = 1; |
431 |
+ stats_section_t sections; |
|
431 | 432 |
|
432 | 433 |
if(cli_hm_scan(digest, size, &virname, ctx->engine->hm_fp, CLI_HASH_MD5) == CL_VIRUS) { |
433 | 434 |
cli_dbgmsg("cli_checkfp(md5): Found false positive detection (fp sig: %s), size: %d\n", virname, (int)size); |
... | ... |
@@ -522,8 +523,11 @@ int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx) |
522 | 522 |
} |
523 | 523 |
#endif |
524 | 524 |
|
525 |
- if(do_dsig_check) { |
|
526 |
- switch(cli_checkfp_pe(ctx, shash1)) { |
|
525 |
+ memset(§ions, 0x00, sizeof(stats_section_t)); |
|
526 |
+ if(do_dsig_check || ctx->engine->cb_stats_add_sample) { |
|
527 |
+ uint32_t flags = (do_dsig_check ? CL_CHECKFP_PE_FLAG_AUTHENTICODE : 0) | (ctx->engine->cb_stats_add_sample ? CL_CHECKFP_PE_FLAG_STATS : 0); |
|
528 |
+ |
|
529 |
+ switch(cli_checkfp_pe(ctx, shash1, §ions, flags)) { |
|
527 | 530 |
case CL_CLEAN: |
528 | 531 |
cli_dbgmsg("cli_checkfp(pe): PE file whitelisted due to valid embedded digital signature\n"); |
529 | 532 |
return CL_CLEAN; |
... | ... |
@@ -540,7 +544,7 @@ int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx) |
540 | 540 |
ctx->engine->cb_hash(fmap_fd(*ctx->fmap), size, md5, cli_get_last_virus(ctx), ctx->cb_ctx); |
541 | 541 |
|
542 | 542 |
if (ctx->engine->cb_stats_add_sample) |
543 |
- ctx->engine->cb_stats_add_sample(cli_get_last_virus(ctx), digest, size, WHOLEFILE, ctx->engine->stats_data); |
|
543 |
+ ctx->engine->cb_stats_add_sample(cli_get_last_virus(ctx), digest, size, §ions, ctx->engine->stats_data); |
|
544 | 544 |
|
545 | 545 |
return CL_VIRUS; |
546 | 546 |
} |
... | ... |
@@ -149,9 +149,9 @@ typedef struct cli_ctx_tag { |
149 | 149 |
typedef struct cli_flagged_sample { |
150 | 150 |
char **virus_name; |
151 | 151 |
char md5[16]; |
152 |
- cli_intel_sample_type_t type; |
|
153 | 152 |
size_t size; /* A size of zero means size is unavailable (why would this ever happen?) */ |
154 | 153 |
uint32_t hits; |
154 |
+ stats_section_t *sections; |
|
155 | 155 |
|
156 | 156 |
struct cli_flagged_sample *prev; |
157 | 157 |
struct cli_flagged_sample *next; |
... | ... |
@@ -60,6 +60,7 @@ |
60 | 60 |
#include "ishield.h" |
61 | 61 |
#include "asn1.h" |
62 | 62 |
#include "sha1.h" |
63 |
+#include "libclamav/md5.h" |
|
63 | 64 |
|
64 | 65 |
#define DCONF ctx->dconf->pe |
65 | 66 |
|
... | ... |
@@ -2796,7 +2797,7 @@ static int sort_sects(const void *first, const void *second) { |
2796 | 2796 |
return (a->raw - b->raw); |
2797 | 2797 |
} |
2798 | 2798 |
|
2799 |
-int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) { |
|
2799 |
+int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1, stats_section_t *hashes, uint32_t flags) { |
|
2800 | 2800 |
uint16_t e_magic; /* DOS signature ("MZ") */ |
2801 | 2801 |
uint16_t nsections; |
2802 | 2802 |
uint32_t e_lfanew; /* address of new exe header */ |
... | ... |
@@ -2814,6 +2815,14 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) { |
2814 | 2814 |
struct pe_image_data_dir *dirs; |
2815 | 2815 |
fmap_t *map = *ctx->fmap; |
2816 | 2816 |
SHA1Context sha1; |
2817 |
+ cli_md5_ctx md5ctx; |
|
2818 |
+ |
|
2819 |
+ if (flags & CL_CHECKFP_PE_FLAG_STATS) |
|
2820 |
+ if (!(hashes)) |
|
2821 |
+ return CL_EFORMAT; |
|
2822 |
+ |
|
2823 |
+ if (flags == CL_CHECKFP_PE_FLAG_NONE) |
|
2824 |
+ return 0; |
|
2817 | 2825 |
|
2818 | 2826 |
if(!(DCONF & PE_CONF_CATALOG)) |
2819 | 2827 |
return CL_EFORMAT; |
... | ... |
@@ -2903,6 +2912,15 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) { |
2903 | 2903 |
|
2904 | 2904 |
hdr_size = PESALIGN(hdr_size, falign); /* Aligned headers virtual size */ |
2905 | 2905 |
|
2906 |
+ if (flags & CL_CHECKFP_PE_FLAG_STATS) { |
|
2907 |
+ hashes->nsections = nsections; |
|
2908 |
+ hashes->sections = cli_calloc(nsections, sizeof(struct cli_section_hash)); |
|
2909 |
+ if (!(hashes->sections)) { |
|
2910 |
+ free(exe_sections); |
|
2911 |
+ return CL_EMEM; |
|
2912 |
+ } |
|
2913 |
+ } |
|
2914 |
+ |
|
2906 | 2915 |
for(i = 0; i < nsections; i++) { |
2907 | 2916 |
exe_sections[i].rva = PEALIGN(EC32(section_hdr[i].VirtualAddress), valign); |
2908 | 2917 |
exe_sections[i].vsz = PESALIGN(EC32(section_hdr[i].VirtualSize), valign); |
... | ... |
@@ -2928,9 +2946,10 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) { |
2928 | 2928 |
|
2929 | 2929 |
cli_qsort(exe_sections, nsections, sizeof(*exe_sections), sort_sects); |
2930 | 2930 |
|
2931 |
- SHA1Init(&sha1); |
|
2931 |
+ if (flags & CL_CHECKFP_PE_FLAG_AUTHENTICODE) |
|
2932 |
+ SHA1Init(&sha1); |
|
2932 | 2933 |
|
2933 |
-#define hash_chunk(where, size) \ |
|
2934 |
+#define hash_chunk(where, size, isStatAble, section) \ |
|
2934 | 2935 |
do { \ |
2935 | 2936 |
const uint8_t *hptr; \ |
2936 | 2937 |
if(!(size)) break; \ |
... | ... |
@@ -2938,13 +2957,20 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) { |
2938 | 2938 |
free(exe_sections); \ |
2939 | 2939 |
return CL_EFORMAT; \ |
2940 | 2940 |
} \ |
2941 |
- SHA1Update(&sha1, hptr, size); \ |
|
2941 |
+ if (flags & CL_CHECKFP_PE_FLAG_AUTHENTICODE) \ |
|
2942 |
+ SHA1Update(&sha1, hptr, size); \ |
|
2943 |
+ if (isStatAble && flags & CL_CHECKFP_PE_FLAG_STATS) { \ |
|
2944 |
+ cli_md5_init(&md5ctx); \ |
|
2945 |
+ cli_md5_update(&md5ctx, hptr, size); \ |
|
2946 |
+ cli_md5_final(hashes->sections[section].md5, &md5ctx); \ |
|
2947 |
+ hashes->sections[section].len = size; \ |
|
2948 |
+ } \ |
|
2942 | 2949 |
} while(0) |
2943 | 2950 |
|
2944 | 2951 |
/* MZ to checksum */ |
2945 | 2952 |
at = 0; |
2946 | 2953 |
hlen = e_lfanew + sizeof(struct pe_image_file_hdr) + (pe_plus ? offsetof(struct pe_image_optional_hdr64, CheckSum) : offsetof(struct pe_image_optional_hdr32, CheckSum)); |
2947 |
- hash_chunk(0, hlen); |
|
2954 |
+ hash_chunk(0, hlen, 0, 0); |
|
2948 | 2955 |
at = hlen + 4; |
2949 | 2956 |
|
2950 | 2957 |
/* Checksum to security */ |
... | ... |
@@ -2952,7 +2978,7 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) { |
2952 | 2952 |
hlen = offsetof(struct pe_image_optional_hdr64, DataDirectory[4]) - offsetof(struct pe_image_optional_hdr64, CheckSum) - 4; |
2953 | 2953 |
else |
2954 | 2954 |
hlen = offsetof(struct pe_image_optional_hdr32, DataDirectory[4]) - offsetof(struct pe_image_optional_hdr32, CheckSum) - 4; |
2955 |
- hash_chunk(at, hlen); |
|
2955 |
+ hash_chunk(at, hlen, 0, 0); |
|
2956 | 2956 |
at += hlen + 8; |
2957 | 2957 |
|
2958 | 2958 |
if(at > hdr_size) { |
... | ... |
@@ -2962,7 +2988,7 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) { |
2962 | 2962 |
|
2963 | 2963 |
/* Security to End of header */ |
2964 | 2964 |
hlen = hdr_size - at; |
2965 |
- hash_chunk(at, hlen); |
|
2965 |
+ hash_chunk(at, hlen, 0, 0); |
|
2966 | 2966 |
|
2967 | 2967 |
/* Sections */ |
2968 | 2968 |
at = hdr_size; |
... | ... |
@@ -2970,7 +2996,7 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) { |
2970 | 2970 |
if(!exe_sections[i].rsz) |
2971 | 2971 |
continue; |
2972 | 2972 |
|
2973 |
- hash_chunk(exe_sections[i].raw, exe_sections[i].rsz); |
|
2973 |
+ hash_chunk(exe_sections[i].raw, exe_sections[i].rsz, 1, i); |
|
2974 | 2974 |
at += exe_sections[i].rsz; |
2975 | 2975 |
} |
2976 | 2976 |
|
... | ... |
@@ -2982,7 +3008,7 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) { |
2982 | 2982 |
} |
2983 | 2983 |
|
2984 | 2984 |
hlen -= dirs[4].Size; |
2985 |
- hash_chunk(at, hlen); |
|
2985 |
+ hash_chunk(at, hlen, 0, 0); |
|
2986 | 2986 |
at += hlen; |
2987 | 2987 |
} |
2988 | 2988 |
free(exe_sections); |
... | ... |
@@ -160,8 +160,12 @@ struct cli_pe_hook_data { |
160 | 160 |
|
161 | 161 |
int cli_scanpe(cli_ctx *ctx); |
162 | 162 |
|
163 |
+#define CL_CHECKFP_PE_FLAG_NONE 0x00000000 |
|
164 |
+#define CL_CHECKFP_PE_FLAG_STATS 0x00000001 |
|
165 |
+#define CL_CHECKFP_PE_FLAG_AUTHENTICODE 0x00000002 |
|
166 |
+ |
|
163 | 167 |
int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo); |
164 |
-int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1); |
|
168 |
+int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1, stats_section_t *hashes, uint32_t flags); |
|
165 | 169 |
|
166 | 170 |
uint32_t cli_rawaddr(uint32_t, const struct cli_exe_section *, uint16_t, unsigned int *, size_t, uint32_t); |
167 | 171 |
void findres(uint32_t, uint32_t, uint32_t, fmap_t *map, struct cli_exe_section *, uint16_t, uint32_t, int (*)(void *, uint32_t, uint32_t, uint32_t, uint32_t), void *); |
... | ... |
@@ -31,10 +31,84 @@ |
31 | 31 |
#include "libclamav/hostid.h" |
32 | 32 |
#include "libclamav/www.h" |
33 | 33 |
|
34 |
-static cli_flagged_sample_t *find_sample(cli_intel_t *intel, const char *virname, const unsigned char *md5, size_t size, cli_intel_sample_type_t type); |
|
34 |
+#define DEBUG_STATS 1 |
|
35 |
+ |
|
36 |
+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); |
|
35 | 37 |
void free_sample(cli_flagged_sample_t *sample); |
36 | 38 |
|
37 |
-void clamav_stats_add_sample(const char *virname, const unsigned char *md5, size_t size, cli_intel_sample_type_t type, void *cbdata) |
|
39 |
+#if DEBUG_STATS |
|
40 |
+char *get_hash(unsigned char *md5) |
|
41 |
+{ |
|
42 |
+ char *hash; |
|
43 |
+ int i; |
|
44 |
+ |
|
45 |
+ hash = calloc(1, 33); |
|
46 |
+ if (!(hash)) |
|
47 |
+ return NULL; |
|
48 |
+ |
|
49 |
+ for (i=0; i<16; i++) |
|
50 |
+ sprintf(hash+(i*2), "%02x", md5[i]); |
|
51 |
+ |
|
52 |
+ return hash; |
|
53 |
+} |
|
54 |
+ |
|
55 |
+char *get_sample_names(char **names) |
|
56 |
+{ |
|
57 |
+ char *ret; |
|
58 |
+ size_t n, i, sz; |
|
59 |
+ |
|
60 |
+ sz = 0; |
|
61 |
+ for (n=0; names[n] != NULL; n++) |
|
62 |
+ sz += strlen(names[n]); |
|
63 |
+ |
|
64 |
+ ret = calloc(1, sz + n + 1); |
|
65 |
+ if (!(ret)) |
|
66 |
+ return NULL; |
|
67 |
+ |
|
68 |
+ for (i=0; names[i] != NULL; i++) |
|
69 |
+ sprintf(ret+strlen(ret), "%s%s", (i==0) ? "" : " ", names[i]); |
|
70 |
+ |
|
71 |
+ return ret; |
|
72 |
+} |
|
73 |
+ |
|
74 |
+void print_sample(cli_flagged_sample_t *sample) |
|
75 |
+{ |
|
76 |
+ char *hash, *names; |
|
77 |
+ size_t i; |
|
78 |
+ |
|
79 |
+ if (!(sample)) |
|
80 |
+ return; |
|
81 |
+ |
|
82 |
+ hash = get_hash(sample->md5); |
|
83 |
+ if (!(hash)) |
|
84 |
+ return; |
|
85 |
+ |
|
86 |
+ cli_warnmsg("Sample[%s]:\n", hash); |
|
87 |
+ cli_warnmsg(" * Size: %zu\n", sample->size); |
|
88 |
+ cli_warnmsg(" * Hits: %u\n", sample->hits); |
|
89 |
+ |
|
90 |
+ free(hash); |
|
91 |
+ |
|
92 |
+ names = get_sample_names(sample->virus_name); |
|
93 |
+ if ((names)) |
|
94 |
+ cli_warnmsg(" * Names: %s\n", names); |
|
95 |
+ |
|
96 |
+ if (sample->sections && sample->sections->nsections) { |
|
97 |
+ for (i=0; i < sample->sections->nsections; i++) { |
|
98 |
+ hash = get_hash(sample->sections->sections[i].md5); |
|
99 |
+ if ((hash)) { |
|
100 |
+ cli_warnmsg(" * Section[%zu] (%zu): %s\n", i, sample->sections->sections[i].len, hash); |
|
101 |
+ free(hash); |
|
102 |
+ } |
|
103 |
+ } |
|
104 |
+ } |
|
105 |
+ |
|
106 |
+ if ((names)) |
|
107 |
+ free(names); |
|
108 |
+} |
|
109 |
+#endif |
|
110 |
+ |
|
111 |
+void clamav_stats_add_sample(const char *virname, const unsigned char *md5, size_t size, stats_section_t *sections, void *cbdata) |
|
38 | 112 |
{ |
39 | 113 |
cli_intel_t *intel; |
40 | 114 |
cli_flagged_sample_t *sample; |
... | ... |
@@ -81,7 +155,7 @@ void clamav_stats_add_sample(const char *virname, const unsigned char *md5, size |
81 | 81 |
} |
82 | 82 |
#endif |
83 | 83 |
|
84 |
- sample = find_sample(intel, virname, md5, size, type); |
|
84 |
+ sample = find_sample(intel, virname, md5, size, sections); |
|
85 | 85 |
if (!(sample)) { |
86 | 86 |
if (!(intel->samples)) { |
87 | 87 |
sample = intel->samples = calloc(1, sizeof(cli_flagged_sample_t)); |
... | ... |
@@ -136,9 +210,15 @@ void clamav_stats_add_sample(const char *virname, const unsigned char *md5, size |
136 | 136 |
sample->virus_name[i+1] = NULL; |
137 | 137 |
|
138 | 138 |
memcpy(sample->md5, md5, sizeof(sample->md5)); |
139 |
- sample->type = type; |
|
140 | 139 |
sample->size = size; |
141 | 140 |
intel->nsamples++; |
141 |
+ |
|
142 |
+ if (sections && sections->nsections && !(sample->sections)) { |
|
143 |
+ /* Copy the section data that has already been allocated. We don't care if calloc fails; just skip copying if it does. */ |
|
144 |
+ sample->sections = calloc(1, sizeof(stats_section_t)); |
|
145 |
+ if ((sample->sections)) |
|
146 |
+ memcpy(sample->sections, sections, sizeof(stats_section_t)); |
|
147 |
+ } |
|
142 | 148 |
} |
143 | 149 |
|
144 | 150 |
cli_warnmsg("Added %s to the stats cache\n", (virname != NULL) ? virname: "[unknown]"); |
... | ... |
@@ -249,6 +329,9 @@ void clamav_stats_submit(struct cl_engine *engine, void *cbdata) |
249 | 249 |
#endif |
250 | 250 |
|
251 | 251 |
for (sample=myintel.samples; sample != NULL; sample = next) { |
252 |
+#if DEBUG_STATS |
|
253 |
+ print_sample(sample); |
|
254 |
+#endif |
|
252 | 255 |
next = sample->next; |
253 | 256 |
|
254 | 257 |
free_sample(sample); |
... | ... |
@@ -261,7 +344,7 @@ void clamav_stats_submit(struct cl_engine *engine, void *cbdata) |
261 | 261 |
} |
262 | 262 |
} |
263 | 263 |
|
264 |
-void clamav_stats_remove_sample(const char *virname, const unsigned char *md5, size_t size, cli_intel_sample_type_t type, void *cbdata) |
|
264 |
+void clamav_stats_remove_sample(const char *virname, const unsigned char *md5, size_t size, void *cbdata) |
|
265 | 265 |
{ |
266 | 266 |
cli_intel_t *intel; |
267 | 267 |
cli_flagged_sample_t *sample; |
... | ... |
@@ -279,19 +362,17 @@ void clamav_stats_remove_sample(const char *virname, const unsigned char *md5, s |
279 | 279 |
} |
280 | 280 |
#endif |
281 | 281 |
|
282 |
- sample = find_sample(intel, virname, md5, size, type); |
|
283 |
- if (!(sample)) |
|
284 |
- return; |
|
285 |
- |
|
286 |
- if (sample->prev) |
|
287 |
- sample->prev->next = sample->next; |
|
288 |
- if (sample->next) |
|
289 |
- sample->next->prev = sample; |
|
290 |
- if (sample == intel->samples) |
|
291 |
- intel->samples = sample->next; |
|
282 |
+ while ((sample = find_sample(intel, virname, md5, size, NULL))) { |
|
283 |
+ if (sample->prev) |
|
284 |
+ sample->prev->next = sample->next; |
|
285 |
+ if (sample->next) |
|
286 |
+ sample->next->prev = sample->prev; |
|
287 |
+ if (sample == intel->samples) |
|
288 |
+ intel->samples = sample->next; |
|
292 | 289 |
|
293 |
- free_sample(sample); |
|
294 |
- intel->nsamples--; |
|
290 |
+ free_sample(sample); |
|
291 |
+ intel->nsamples--; |
|
292 |
+ } |
|
295 | 293 |
|
296 | 294 |
#ifdef CL_THREAD_SAFE |
297 | 295 |
err = pthread_mutex_unlock(&(intel->mutex)); |
... | ... |
@@ -301,7 +382,7 @@ void clamav_stats_remove_sample(const char *virname, const unsigned char *md5, s |
301 | 301 |
#endif |
302 | 302 |
} |
303 | 303 |
|
304 |
-void clamav_stats_decrement_count(const char *virname, const unsigned char *md5, size_t size, cli_intel_sample_type_t type, void *cbdata) |
|
304 |
+void clamav_stats_decrement_count(const char *virname, const unsigned char *md5, size_t size, void *cbdata) |
|
305 | 305 |
{ |
306 | 306 |
cli_intel_t *intel; |
307 | 307 |
cli_flagged_sample_t *sample; |
... | ... |
@@ -319,15 +400,15 @@ void clamav_stats_decrement_count(const char *virname, const unsigned char *md5, |
319 | 319 |
} |
320 | 320 |
#endif |
321 | 321 |
|
322 |
- sample = find_sample(intel, virname, md5, size, type); |
|
322 |
+ sample = find_sample(intel, virname, md5, size, NULL); |
|
323 | 323 |
if (!(sample)) |
324 | 324 |
return; |
325 | 325 |
|
326 | 326 |
if (sample->hits == 1) { |
327 | 327 |
if ((intel->engine->cb_stats_remove_sample)) |
328 |
- intel->engine->cb_stats_remove_sample(virname, md5, size, type, intel); |
|
328 |
+ intel->engine->cb_stats_remove_sample(virname, md5, size, intel); |
|
329 | 329 |
else |
330 |
- clamav_stats_remove_sample(virname, md5, size, type, intel); |
|
330 |
+ clamav_stats_remove_sample(virname, md5, size, intel); |
|
331 | 331 |
|
332 | 332 |
return; |
333 | 333 |
} |
... | ... |
@@ -444,14 +525,13 @@ char *clamav_stats_get_hostid(void *cbdata) |
444 | 444 |
} |
445 | 445 |
#endif |
446 | 446 |
|
447 |
-static cli_flagged_sample_t *find_sample(cli_intel_t *intel, const char *virname, const unsigned char *md5, size_t size, cli_intel_sample_type_t type) |
|
447 |
+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) |
|
448 | 448 |
{ |
449 | 449 |
cli_flagged_sample_t *sample; |
450 | 450 |
size_t i; |
451 | 451 |
|
452 | 452 |
for (sample = intel->samples; sample != NULL; sample = sample->next) { |
453 |
- if (sample->type != type) |
|
454 |
- continue; |
|
453 |
+ int foundSections = 0; |
|
455 | 454 |
|
456 | 455 |
if (sample->size != size) |
457 | 456 |
continue; |
... | ... |
@@ -462,9 +542,24 @@ static cli_flagged_sample_t *find_sample(cli_intel_t *intel, const char *virname |
462 | 462 |
if (!(virname)) |
463 | 463 |
return sample; |
464 | 464 |
|
465 |
- for (i=0; sample->virus_name[i] != NULL; i++) |
|
466 |
- if (!strcmp(sample->virus_name[i], virname)) |
|
467 |
- return sample; |
|
465 |
+ if ((sections) && (sample->sections)) { |
|
466 |
+ if (sections->nsections == sample->sections->nsections) { |
|
467 |
+ for (i=0; i < sections->nsections; i++) |
|
468 |
+ if (sections->sections[i].len == sample->sections->sections[i].len) |
|
469 |
+ if (memcmp(sections->sections[i].md5, sample->sections->sections[i].md5, sizeof(stats_section_t))) |
|
470 |
+ break; |
|
471 |
+ |
|
472 |
+ if (i == sections->nsections) |
|
473 |
+ foundSections = 1; |
|
474 |
+ } |
|
475 |
+ } else { |
|
476 |
+ foundSections = 1; |
|
477 |
+ } |
|
478 |
+ |
|
479 |
+ if (foundSections) |
|
480 |
+ for (i=0; sample->virus_name[i] != NULL; i++) |
|
481 |
+ if (!strcmp(sample->virus_name[i], virname)) |
|
482 |
+ return sample; |
|
468 | 483 |
} |
469 | 484 |
|
470 | 485 |
return NULL; |
... | ... |
@@ -4,11 +4,11 @@ |
4 | 4 |
#define STATS_HOST "stats.clamav.dev" /* Change this before release! */ |
5 | 5 |
#define STATS_PORT "8080" |
6 | 6 |
|
7 |
-void clamav_stats_add_sample(const char *virname, const unsigned char *md5, uint64_t size, cli_intel_sample_type_t type, void *cbdata); |
|
7 |
+void clamav_stats_add_sample(const char *virname, const unsigned char *md5, size_t size, stats_section_t *sections, void *cbdata); |
|
8 | 8 |
void clamav_stats_submit(struct cl_engine *engine, void *cbdata); |
9 | 9 |
void clamav_stats_flush(struct cl_engine *engine, void *cbdata); |
10 |
-void clamav_stats_remove_sample(const char *virname, const unsigned char *md5, size_t size, cli_intel_sample_type_t type, void *cbdata); |
|
11 |
-void clamav_stats_decrement_count(const char *virname, const unsigned char *md5, size_t size, cli_intel_sample_type_t type, void *cbdata); |
|
10 |
+void clamav_stats_remove_sample(const char *virname, const unsigned char *md5, size_t size, void *cbdata); |
|
11 |
+void clamav_stats_decrement_count(const char *virname, const unsigned char *md5, size_t size, void *cbdata); |
|
12 | 12 |
size_t clamav_stats_get_num(void *cbdata); |
13 | 13 |
size_t clamav_stats_get_size(void *cbdata); |
14 | 14 |
char *clamav_stats_get_hostid(void *cbdata); |
... | ... |
@@ -2873,7 +2873,7 @@ static int dumpcerts(const struct optstruct *opts) |
2873 | 2873 |
SHA1Update(&sha1, fmptr, sb.st_size); |
2874 | 2874 |
SHA1Final(&sha1, shash1); |
2875 | 2875 |
|
2876 |
- ret = cli_checkfp_pe(&ctx, shash1); |
|
2876 |
+ ret = cli_checkfp_pe(&ctx, shash1, NULL, CL_CHECKFP_PE_FLAG_AUTHENTICODE); |
|
2877 | 2877 |
|
2878 | 2878 |
switch(ret) { |
2879 | 2879 |
case CL_CLEAN: |