Commit 5d1660e82 for clamav.net
commit 5d1660e829ce9d9e65027e8e8ddab41e3be92ed5
Author: Val S. <valsnyde@cisco.com>
Date: Mon Jun 8 13:07:43 2026 -0400
CLAM-3005: Retire stats submission code (#1732)
Remove the legacy ClamAV stats submission implementation that sent telemetry to the discontinued clamintel service.
Delete the built-in stats data model, host ID helpers, JSON report generation, HTTP submission helper, and matcher code that gathered PE section metadata only for telemetry reporting. Remove the associated libclamav stats callback API, engine fields and settings, dynamic-config STATS entries, and exported symbols.
Bump the libclamav ABI version tuple from the 1.5.x 13:0:1 value to 14:0:0 so the generated soname changes for the incompatible exported-symbol and API removals.
Keep the sigtool PE hash generation path working by preserving cli_genhash_pe() for --mdb and --imp without the retired stats-output parameter. Update the generated Rust bindings to match the changed C struct layout and add a NEWS entry for the removed API.
The command-line and configuration options for stats submission were removed in earlier releases, so this change cleans up the remaining library-side implementation and ABI surface.
CLAM-3005
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 72acce71e..3a53e9ead 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -36,9 +36,9 @@ set(PACKAGE_URL "https://www.clamav.net/")
HexVersion(PACKAGE_VERSION_NUM ${PROJECT_VERSION_MAJOR} ${PROJECT_VERSION_MINOR} ${PROJECT_VERSION_PATCH})
# libtool library versioning rules: http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
-set(LIBCLAMAV_CURRENT 13)
+set(LIBCLAMAV_CURRENT 14)
set(LIBCLAMAV_REVISION 0)
-set(LIBCLAMAV_AGE 1)
+set(LIBCLAMAV_AGE 0)
math(EXPR LIBCLAMAV_SOVERSION "${LIBCLAMAV_CURRENT} - ${LIBCLAMAV_AGE}")
set(LIBCLAMAV_VERSION "${LIBCLAMAV_SOVERSION}.${LIBCLAMAV_AGE}.${LIBCLAMAV_REVISION}")
diff --git a/NEWS.md b/NEWS.md
index cb9f3e809..adec76bc2 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -9,6 +9,10 @@ ClamAV 1.6.0 includes the following improvements and changes:
### Major changes
+- Retired the legacy ClamAV stats submission code used to send telemetry to
+ the discontinued clamintel service. This removes the related libclamav stats
+ callback API.
+
### Other improvements
### Bug fixes
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 9370c5294..1d49fd220 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -18,7 +18,6 @@ target_sources( common
actions.c
clamdcom.c
getopt.c
- hostid.c
idmef_logging.c
misc.c
optparser.c
@@ -30,7 +29,6 @@ target_sources( common
clamdcom.h
fdpassing.h
getopt.h
- hostid.h
idmef_logging.h
misc.h
optparser.h
diff --git a/common/hostid.c b/common/hostid.c
deleted file mode 100644
index 774c3066e..000000000
--- a/common/hostid.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2014-2026 Cisco Systems, Inc. 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 <string.h>
-
-// libclamav
-#include "others.h"
-
-#include "output.h"
-
-char hostid[37];
-
-int is_valid_hostid(void)
-{
- int count, i;
-
- if (strlen(hostid) != 36)
- return 0;
-
- count = 0;
- for (i = 0; i < 36; i++)
- if (hostid[i] == '-')
- count++;
-
- if (count != 4)
- return 0;
-
- if (hostid[8] != '-' || hostid[13] != '-' || hostid[18] != '-' || hostid[23] != '-')
- return 0;
-
- return 1;
-}
-
-char *get_hostid(void *cbdata)
-{
- UNUSEDPARAM(cbdata);
-
- if (!strcmp(hostid, "none"))
- return NULL;
-
- if (!is_valid_hostid())
- return strdup(STATS_ANON_UUID);
-
- logg(LOGG_INFO, "HostID is valid: %s\n", hostid);
-
- return strdup(hostid);
-}
diff --git a/common/hostid.h b/common/hostid.h
deleted file mode 100644
index 187e6a869..000000000
--- a/common/hostid.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2014-2026 Cisco Systems, Inc. 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.
- */
-
-#ifndef __LIBFRESHCLAM_H
-#define __LIBFRESHCLAM_H
-
-extern char hostid[37];
-
-/**
- * @brief
- *
- * @return int
- */
-int is_valid_hostid(void);
-
-/**
- * @brief Get the hostid object
- *
- * @param cbdata
- * @return char*
- */
-char *get_hostid(void *cbdata);
-
-#endif //__LIBFRESHCLAM_H
diff --git a/libclamav/CMakeLists.txt b/libclamav/CMakeLists.txt
index bcee81b7c..7cbe63103 100644
--- a/libclamav/CMakeLists.txt
+++ b/libclamav/CMakeLists.txt
@@ -218,7 +218,6 @@ set(LIBCLAMAV_SOURCES
table.c table.h
text.c text.h
uniq.c uniq.h
- www.c www.h
# Utils Disasm
disasm-common.h disasm.c disasm.h disasmpriv.h
# Matcher
@@ -260,10 +259,6 @@ set(LIBCLAMAV_SOURCES
# heuristics (hardcoded exploit/malware detection)
partition_intersection.c partition_intersection.h
special.c special.h
- # clamav statistics
- hostid_internal.c hostid_internal.h
- stats_json.c stats_json.h
- stats.c stats.h
# clamav bytecode support
bcfeatures.h
builtin_bytecodes.h
diff --git a/libclamav/clamav.h b/libclamav/clamav.h
index 815438377..8a3767f78 100644
--- a/libclamav/clamav.h
+++ b/libclamav/clamav.h
@@ -237,7 +237,7 @@ struct cl_scan_options {
#define ENGINE_OPTIONS_NONE 0x0
#define ENGINE_OPTIONS_DISABLE_CACHE 0x1
#define ENGINE_OPTIONS_FORCE_TO_DISK 0x2
-#define ENGINE_OPTIONS_DISABLE_PE_STATS 0x4
+/* 0x4 was ENGINE_OPTIONS_DISABLE_PE_STATS; keep later bits stable. */
#define ENGINE_OPTIONS_DISABLE_PE_CERTS 0x8
#define ENGINE_OPTIONS_PE_DUMPCERTS 0x10
#define ENGINE_OPTIONS_TMPDIR_RECURSION 0x20
@@ -331,8 +331,6 @@ enum cl_engine_field {
CL_ENGINE_FORCETODISK, /** uint32_t */
CL_ENGINE_CACHE_SIZE, /** 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 */
CL_ENGINE_MAX_ICONSPE, /** uint32_t */
CL_ENGINE_MAX_RECHWP3, /** uint32_t */
@@ -361,16 +359,6 @@ enum bytecode_mode {
CL_BYTECODE_MODE_OFF /** for query only, not settable */
};
-struct cli_section_hash {
- unsigned char md5[16];
- size_t len;
-};
-
-typedef struct cli_stats_sections {
- size_t nsections;
- struct cli_section_hash *sections;
-} stats_section_t;
-
/**
* @brief Set a numerical engine option.
*
@@ -1403,181 +1391,6 @@ typedef int (*clcb_generic_data)(const unsigned char *const data, const size_t d
*/
extern void cl_engine_set_clcb_vba(struct cl_engine *engine, clcb_generic_data callback);
-/* ----------------------------------------------------------------------------
- * Statistics/telemetry gathering callbacks.
- *
- * The statistics callback functions may be used to implement a telemetry
- * gathering feature.
- *
- * The structure definition for `cbdata` is entirely up to the caller, as are
- * the implementations of each of the callback functions defined below.
- */
-
-/**
- * @brief Set a pointer the caller-defined cbdata structure.
- *
- * The data must persist at least until `clcb_stats_submit()` is called, or
- * `clcb_stats_flush()` is called (optional).
- *
- * Caution: changing options for an engine that is in-use is not thread-safe!
- *
- * @param engine The scanning engine.
- * @param cbdata The statistics data. Probably a pointer to a malloc'd struct.
- */
-extern void cl_engine_set_stats_set_cbdata(struct cl_engine *engine, void *cbdata);
-
-/**
- * @brief Add sample metadata to the statistics for a sample that matched on a signature.
- *
- * @param virname Name of the signature that matched.
- * @param md5 Sample hash.
- * @param size Sample size.
- * @param sections PE section data, if applicable.
- * @param cbdata The statistics data. Probably a pointer to a malloc'd struct.
- */
-typedef void (*clcb_stats_add_sample)(
- const char *virname,
- const unsigned char *md5,
- size_t size,
- stats_section_t *sections,
- void *cbdata);
-/**
- * @brief Set a custom callback function to add sample metadata to a statistics report.
- *
- * Caution: changing options for an engine that is in-use is not thread-safe!
- *
- * @param engine The initialized scanning engine.
- * @param callback The callback function pointer.
- */
-extern void cl_engine_set_clcb_stats_add_sample(struct cl_engine *engine, clcb_stats_add_sample callback);
-
-/**
- * @brief Remove a specific sample from the statistics report.
- *
- * @param virname Name of the signature that matched.
- * @param md5 Sample hash.
- * @param size Sample size.
- * @param cbdata The statistics data. Probably a pointer to a malloc'd struct.
- */
-typedef void (*clcb_stats_remove_sample)(const char *virname, const unsigned char *md5, size_t size, void *cbdata);
-/**
- * @brief Set a custom callback function to remove sample metadata from a statistics report.
- *
- * Caution: changing options for an engine that is in-use is not thread-safe!
- *
- * @param engine The initialized scanning engine.
- * @param callback The callback function pointer.
- */
-extern void cl_engine_set_clcb_stats_remove_sample(struct cl_engine *engine, clcb_stats_remove_sample callback);
-
-/**
- * @brief Decrement the hit count listed in the statistics report for a specific sample.
- *
- * @param virname Name of the signature that matched.
- * @param md5 Sample hash.
- * @param size Sample size.
- * @param cbdata The statistics data. Probably a pointer to a malloc'd struct.
- */
-typedef void (*clcb_stats_decrement_count)(const char *virname, const unsigned char *md5, size_t size, void *cbdata);
-/**
- * @brief Set a custom callback function to decrement the hit count listed in the statistics report for a specific sample.
- *
- * This function may remove the sample from the report if the hit count is decremented to 0.
- *
- * @param engine The initialized scanning engine.
- * @param callback The callback function pointer.
- */
-extern void cl_engine_set_clcb_stats_decrement_count(struct cl_engine *engine, clcb_stats_decrement_count callback);
-
-/**
- * @brief Function to submit a statistics report.
- *
- * @param engine The initialized scanning engine.
- * @param cbdata The statistics data. Probably a pointer to a malloc'd struct.
- */
-typedef void (*clcb_stats_submit)(struct cl_engine *engine, void *cbdata);
-/**
- * @brief Set a custom callback function to submit the statistics report.
- *
- * Caution: changing options for an engine that is in-use is not thread-safe!
- *
- * @param engine The initialized scanning engine.
- * @param callback The callback function pointer.
- */
-extern void cl_engine_set_clcb_stats_submit(struct cl_engine *engine, clcb_stats_submit callback);
-
-/**
- * @brief Function to flush/free the statistics report data.
- *
- * @param engine The initialized scanning engine.
- * @param cbdata The statistics data. Probably a pointer to a malloc'd struct.
- */
-typedef void (*clcb_stats_flush)(struct cl_engine *engine, void *cbdata);
-/**
- * @brief Set a custom callback function to flush/free the statistics report data.
- *
- * Caution: changing options for an engine that is in-use is not thread-safe!
- *
- * @param engine The initialized scanning engine.
- * @param callback The callback function pointer.
- */
-extern void cl_engine_set_clcb_stats_flush(struct cl_engine *engine, clcb_stats_flush callback);
-
-/**
- * @brief Function to get the number of samples listed in the statistics report.
- *
- * @param cbdata The statistics data. Probably a pointer to a malloc'd struct.
- */
-typedef size_t (*clcb_stats_get_num)(void *cbdata);
-/**
- * @brief Set a custom callback function to get the number of samples listed in the statistics report.
- *
- * Caution: changing options for an engine that is in-use is not thread-safe!
- *
- * @param engine The initialized scanning engine.
- * @param callback The callback function pointer.
- */
-extern void cl_engine_set_clcb_stats_get_num(struct cl_engine *engine, clcb_stats_get_num callback);
-
-/**
- * @brief Function to get the size of memory used to store the statistics report.
- *
- * @param cbdata The statistics data. Probably a pointer to a malloc'd struct.
- */
-typedef size_t (*clcb_stats_get_size)(void *cbdata);
-/**
- * @brief Set a custom callback function to get the size of memory used to store the statistics report.
- *
- * Caution: changing options for an engine that is in-use is not thread-safe!
- *
- * @param engine The initialized scanning engine.
- * @param callback The callback function pointer.
- */
-extern void cl_engine_set_clcb_stats_get_size(struct cl_engine *engine, clcb_stats_get_size callback);
-
-/**
- * @brief Function to get the machine's unique host ID.
- *
- * @param cbdata The statistics data. Probably a pointer to a malloc'd struct.
- */
-typedef char *(*clcb_stats_get_hostid)(void *cbdata);
-/**
- * @brief Set a custom callback function to get the machine's unique host ID.
- *
- * Caution: changing options for an engine that is in-use is not thread-safe!
- *
- * @param engine The initialized scanning engine.
- * @param callback The callback function pointer.
- */
-extern void cl_engine_set_clcb_stats_get_hostid(struct cl_engine *engine, clcb_stats_get_hostid callback);
-
-/**
- * @brief Function enables the built-in statistics reporting feature.
- *
- * @param engine The initialized scanning engine.
- */
-extern void cl_engine_stats_enable(struct cl_engine *engine);
-
/* ----------------------------------------------------------------------------
* File scanning.
*/
diff --git a/libclamav/cvd.c b/libclamav/cvd.c
index 029dd6ed7..ea79419de 100644
--- a/libclamav/cvd.c
+++ b/libclamav/cvd.c
@@ -429,8 +429,6 @@ cl_error_t cl_cvdverify_ex(const char *file, const char *certs_directory, uint32
ret = CL_EMEM;
goto done;
}
- engine->cb_stats_submit = NULL; /* Don't submit stats if we're just verifying a CVD */
-
if (!!cli_strbcasestr(file, ".cvd")) {
dbtype = CVD_TYPE_CVD;
} else if (!!cli_strbcasestr(file, ".cld")) {
diff --git a/libclamav/dconf.c b/libclamav/dconf.c
index c5e448454..fc7a80eac 100644
--- a/libclamav/dconf.c
+++ b/libclamav/dconf.c
@@ -149,9 +149,6 @@ static struct dconf_module modules[] = {
{"BYTECODE", "JIT PPC", BYTECODE_JIT_PPC, 1},
{"BYTECODE", "JIT ARM", BYTECODE_JIT_ARM, 0},
- {"STATS", "DISABLED", DCONF_STATS_DISABLED, 0},
- {"STATS", "PESECTION DISABLED", DCONF_STATS_PE_SECTION_DISABLED, 0},
-
{"PCRE", "SUPPORT", PCRE_CONF_SUPPORT, 1},
{"PCRE", "OPTIONS", PCRE_CONF_OPTIONS, 1},
{"PCRE", "GLOBAL", PCRE_CONF_GLOBAL, 1},
@@ -199,9 +196,6 @@ struct cli_dconf *cli_dconf_init(void)
} 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;
} else if (!strcmp(modules[i].mname, "PCRE")) {
if (modules[i].state)
dconf->pcre |= modules[i].bflag;
@@ -214,7 +208,7 @@ 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, stats = 0, pcre = 0;
+ unsigned int other = 0, phishing = 0, i, bytecode = 0, pcre = 0;
cli_dbgmsg("Dynamic engine configuration settings:\n");
cli_dbgmsg("--------------------------------------\n");
@@ -300,16 +294,6 @@ void cli_dconf_print(struct cli_dconf *dconf)
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;
} else if (!strcmp(modules[i].mname, "PCRE")) {
if (!pcre) {
cli_dbgmsg("Module PCRE %s\n", dconf->pcre ? "On" : "Off");
@@ -453,15 +437,6 @@ int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, str
}
}
- 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 (!strncmp(buffer, "PCRE:", 5) && chkflevel(buffer, 2)) {
if (sscanf(buffer + 5, "0x%x", &val) == 1) {
engine->dconf->pcre = val;
diff --git a/libclamav/dconf.h b/libclamav/dconf.h
index 0b6bb7562..714e984fa 100644
--- a/libclamav/dconf.h
+++ b/libclamav/dconf.h
@@ -40,7 +40,6 @@ struct cli_dconf {
uint32_t other;
uint32_t phishing;
uint32_t bytecode;
- uint32_t stats;
uint32_t pcre;
};
@@ -144,10 +143,6 @@ 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
-
/* PCRE flags */
#define PCRE_CONF_SUPPORT 0x1
#define PCRE_CONF_OPTIONS 0x2
diff --git a/libclamav/hostid_internal.c b/libclamav/hostid_internal.c
deleted file mode 100644
index bb4d09db8..000000000
--- a/libclamav/hostid_internal.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * 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
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <sys/types.h>
-#include <fcntl.h>
-
-#if !defined(_WIN32)
-#include <sys/socket.h>
-#include <netdb.h>
-#include <sys/ioctl.h>
-#endif
-
-#if defined(HAVE_GETIFADDRS)
-#include <net/if.h>
-#if defined(HAVE_NET_IF_DL_H)
-#include <net/if_dl.h>
-#endif
-#include <ifaddrs.h>
-#endif
-
-#if defined(SIOCGIFHWADDR) && !defined(__GNU__)
-#if defined(_AIX)
-#include <sys/ndd_var.h>
-#include <sys/kinfo.h>
-#else
-#include <linux/sockios.h>
-#endif
-#endif
-
-#include <errno.h>
-
-#include "clamav.h"
-#include "hostid_internal.h"
-#include "others.h"
-
-struct device *get_device_entry(struct device *devices, size_t *ndevices, const char *name);
-
-struct device *get_device_entry(struct device *devices, size_t *ndevices, const char *name)
-{
- void *p;
- size_t i;
-
- if ((devices)) {
- int found = 0;
-
- for (i = 0; i < *ndevices; i++) {
- if (!strcmp(devices[i].name, name)) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
- p = realloc(devices, sizeof(struct device) * (*ndevices + 1));
- if (!(p)) {
- for (i = 0; i < *ndevices; i++)
- free(devices[i].name);
- free(devices);
- return NULL;
- }
- devices = p;
-
- memset(devices + *ndevices, 0x00, sizeof(struct device));
- *ndevices = *ndevices + 1;
- }
- } else {
- devices = calloc(1, sizeof(struct device));
- if (!(devices))
- return NULL;
-
- *ndevices = 1;
- }
-
- if (*ndevices && !(devices[*ndevices - 1].name) && name)
- devices[*ndevices - 1].name = strdup(name);
-
- return devices;
-}
-
-#if HAVE_GETIFADDRS
-struct device *get_devices(void)
-{
- struct ifaddrs *addrs = NULL, *addr;
- struct device *devices = NULL;
- size_t ndevices = 0, i, j;
- void *p;
- uint8_t *mac;
- int sock;
-
-#if defined(SIOCGIFHWADDR) && !defined(__GNU__)
- struct ifreq ifr;
-#else
- struct sockaddr_dl *sdl;
-#endif
-
- if (getifaddrs(&addrs))
- return NULL;
-
- for (addr = addrs; addr != NULL; addr = addr->ifa_next) {
- if (!(addr->ifa_addr))
- continue;
-
- /*
- * Even though POSIX (BSD) sockets define AF_LINK, Linux decided to be clever
- * and use AF_PACKET instead.
- */
-#if defined(AF_PACKET)
- if (addr->ifa_addr->sa_family != AF_PACKET)
- continue;
-#elif defined(AF_LINK)
- if (addr->ifa_addr->sa_family != AF_LINK)
- continue;
-#else
- break; /* We don't support anything else */
-#endif
-
- devices = get_device_entry(devices, &ndevices, addr->ifa_name);
- if (!(devices)) {
- freeifaddrs(addrs);
- return NULL;
- }
-
- /*
- * Grab the MAC address for all devices that have them.
- * Linux doesn't support (struct sockaddr_dl) as POSIX (BSD) sockets require.
- * Instead, Linux uses its own ioctl. This code only runs if we're not Linux,
- * Windows, or FreeBSD.
- */
-#if !defined(SIOCGIFHWADDR) || defined(__GNU__)
- for (i = 0; i < ndevices; i++) {
- if (!(strcmp(devices[i].name, addr->ifa_name))) {
- sdl = (struct sockaddr_dl *)(addr->ifa_addr);
-
-#if defined(LLADDR)
- mac = LLADDR(sdl);
-#else
- mac = ((uint8_t *)(sdl->sdl_data + sdl->sdl_nlen));
-#endif
- for (j = 0; j < 6; j++)
- snprintf(devices[i].mac + strlen(devices[i].mac), sizeof(devices[i].mac) - strlen(devices[i].mac) - 1, "%02x:", mac[j]);
-
- break;
- }
- }
-#endif
- }
-
- if (addrs) {
- freeifaddrs(addrs);
- addrs = NULL;
- }
-
- /* This is the Linux version of getting the MAC addresses */
-#if defined(SIOCGIFHWADDR) && !defined(__GNU__)
- for (i = 0; i < ndevices; i++) {
- if (!(devices[i].name))
- continue;
-
- memset(&ifr, 0x00, sizeof(struct ifreq));
- memset(devices[i].mac, 0x00, sizeof(devices[i].mac));
-
- strcpy(ifr.ifr_name, devices[i].name);
-
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock < 0)
- goto err;
-
- if (ioctl(sock, SIOCGIFHWADDR, &ifr)) {
- close(sock);
- goto err;
- }
- close(sock);
-
- mac = ((uint8_t *)(ifr.ifr_ifru.ifru_hwaddr.sa_data));
- if (!(mac))
- continue;
-
- for (j = 0; j < 6; j++)
- snprintf(devices[i].mac + strlen(devices[i].mac), sizeof(devices[i].mac) - strlen(devices[i].mac) - 1, "%02x:", mac[j]);
- }
-#endif
-
- p = realloc(devices, sizeof(struct device) * (ndevices + 1));
- if (!(p))
- goto err;
-
- devices = p;
- devices[ndevices].name = NULL;
- memset(devices[ndevices].mac, 0x00, sizeof(devices[ndevices].mac));
-
- return devices;
-
-err:
- if (devices) {
- for (i = 0; i < ndevices; i++)
- if (devices[i].name)
- free(devices[i].name);
-
- free(devices);
- }
-
- return NULL;
-}
-#else
-struct device *get_devices(void)
-{
- return NULL;
-}
-#endif /* HAVE_GETIFADDRS */
-
-#if !HAVE_SYSCTLBYNAME && !defined(_WIN32)
-/*
- * Since we're getting potentially sensitive data (MAC addresses for all devices on the system),
- * hash all the MAC addresses to provide basic anonymity and security.
- */
-char *internal_get_host_id(void)
-{
- size_t i;
- unsigned char raw_md5[16];
- char *printable_md5;
- struct device *devices;
- void *ctx;
-
- devices = get_devices();
- if (!(devices))
- return NULL;
-
- printable_md5 = calloc(1, 37);
- if (!(printable_md5)) {
- free(devices);
- return NULL;
- }
-
- ctx = cl_hash_init("md5");
- if (!(ctx)) {
- for (i = 0; devices[i].name != NULL; i++)
- free(devices[i].name);
-
- free(devices);
- free(printable_md5);
-
- return NULL;
- }
-
- for (i = 0; devices[i].name != NULL; i++)
- cl_update_hash(ctx, devices[i].mac, sizeof(devices[i].mac));
-
- cl_finish_hash(ctx, raw_md5);
-
- for (i = 0; devices[i].name != NULL; i++)
- free(devices[i].name);
- free(devices);
-
- for (i = 0; i < sizeof(raw_md5); i++) {
- size_t len = strlen(printable_md5);
- switch (len) {
- case 8:
- case 13:
- case 18:
- case 23:
- printable_md5[len++] = '-';
- break;
- }
-
- sprintf(printable_md5 + len, "%02x", raw_md5[i]);
- }
-
- return printable_md5;
-}
-#endif
diff --git a/libclamav/hostid_internal.h b/libclamav/hostid_internal.h
deleted file mode 100644
index 1a5bd7cb2..000000000
--- a/libclamav/hostid_internal.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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
-
-struct device {
- char *name;
- char mac[19];
-};
-
-struct device *get_devices(void);
-
-#if !HAVE_SYSCTLBYNAME
-char *internal_get_host_id(void);
-#endif
-
-#endif
diff --git a/libclamav/libclamav.map b/libclamav/libclamav.map
index ffd7ec30a..56e6bf326 100644
--- a/libclamav/libclamav.map
+++ b/libclamav/libclamav.map
@@ -44,20 +44,10 @@ CLAMAV_PUBLIC {
cl_scanmap_callback;
cl_fmap_close;
cl_always_gen_section_hash;
- cl_engine_set_stats_set_cbdata;
- cl_engine_set_clcb_stats_add_sample;
- cl_engine_set_clcb_stats_remove_sample;
- cl_engine_set_clcb_stats_decrement_count;
- cl_engine_set_clcb_stats_submit;
- cl_engine_set_clcb_stats_flush;
- cl_engine_set_clcb_stats_get_num;
- cl_engine_set_clcb_stats_get_size;
- cl_engine_set_clcb_stats_get_hostid;
cl_hash_init;
cl_update_hash;
cl_finish_hash;
cl_hash_destroy;
- cl_engine_stats_enable;
lsig_sub_matched;
cl_engine_set_clcb_engine_compile_progress;
cl_engine_set_clcb_engine_free_progress;
diff --git a/libclamav/matcher.c b/libclamav/matcher.c
index 5ed8cce89..74dd9d876 100644
--- a/libclamav/matcher.c
+++ b/libclamav/matcher.c
@@ -653,24 +653,6 @@ cl_error_t cli_check_fp(cli_ctx *ctx, const char *vname)
ctx->engine->cb_hash(fmap_fd(ctx->fmap), map->len, hash_string, vname ? vname : "noname", ctx->cb_ctx);
}
- if (ctx->engine->cb_stats_add_sample) {
- stats_section_t sections;
- memset(§ions, 0x00, sizeof(stats_section_t));
-
- if (!(ctx->engine->engine_options & ENGINE_OPTIONS_DISABLE_PE_STATS) &&
- !(ctx->engine->dconf->stats & (DCONF_STATS_DISABLED | DCONF_STATS_PE_SECTION_DISABLED))) {
-
- cli_genhash_pe(ctx, CL_GENHASH_PE_CLASS_SECTION, 1, §ions);
- }
-
- // TODO We probably only want to call cb_stats_add_sample when
- // sections.section != NULL... leaving as is for now
- ctx->engine->cb_stats_add_sample(vname ? vname : "noname", hash, map->len, §ions, ctx->engine->stats_data);
-
- if (sections.sections) {
- free(sections.sections);
- }
- }
}
if (cli_hm_scan(hash, map->len, &virname, ctx->engine->hm_fp, hash_type) == CL_VIRUS) {
diff --git a/libclamav/others.c b/libclamav/others.c
index d9fe3aec9..9208eef74 100644
--- a/libclamav/others.c
+++ b/libclamav/others.c
@@ -75,7 +75,6 @@
#include "bytecode_api_impl.h"
#include "cache.h"
#include "readdb.h"
-#include "stats.h"
#include "json_api.h"
#include "mpool.h"
@@ -473,7 +472,6 @@ struct cl_engine *cl_engine_new(void)
cl_error_t status = CL_ERROR;
struct cl_engine *new = NULL;
- cli_intel_t *intel = NULL;
char *cvdcertsdir = NULL;
new = (struct cl_engine *)calloc(1, sizeof(struct cl_engine));
@@ -545,33 +543,6 @@ struct cl_engine *cl_engine_new(void)
goto done;
}
- /* Set up default stats/intel gathering callbacks */
- intel = calloc(1, sizeof(cli_intel_t));
- if ((intel)) {
-#ifdef CL_THREAD_SAFE
- if (pthread_mutex_init(&(intel->mutex), NULL)) {
- cli_errmsg("cli_engine_new: Cannot initialize stats gathering mutex\n");
- goto done;
- }
-#endif
- intel->engine = new;
- intel->maxsamples = STATS_MAX_SAMPLES;
- intel->maxmem = STATS_MAX_MEM;
- intel->timeout = 10;
- new->stats_data = intel;
- } else {
- new->stats_data = NULL;
- }
-
- new->cb_stats_add_sample = NULL;
- new->cb_stats_submit = NULL;
- new->cb_stats_flush = clamav_stats_flush;
- new->cb_stats_remove_sample = clamav_stats_remove_sample;
- new->cb_stats_decrement_count = clamav_stats_decrement_count;
- new->cb_stats_get_num = clamav_stats_get_num;
- new->cb_stats_get_size = clamav_stats_get_size;
- new->cb_stats_get_hostid = clamav_stats_get_hostid;
-
/* Setup raw disk image max settings */
new->maxpartitions = CLI_DEFAULT_MAXPARTITIONS;
@@ -651,9 +622,6 @@ done:
free(new);
new = NULL;
}
- if (NULL != intel) {
- free(intel);
- }
}
return new;
@@ -811,20 +779,6 @@ cl_error_t cl_engine_set_num(struct cl_engine *engine, enum cl_engine_field fiel
engine->cache_size = (uint32_t)num;
}
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;
@@ -938,8 +892,6 @@ long long cl_engine_get_num(const struct cl_engine *engine, enum cl_engine_field
return engine->engine_options & ENGINE_OPTIONS_DISABLE_CACHE;
case CL_ENGINE_CACHE_SIZE:
return engine->cache_size;
- case CL_ENGINE_STATS_TIMEOUT:
- return ((cli_intel_t *)(engine->stats_data))->timeout;
case CL_ENGINE_MAX_PARTITIONS:
return engine->maxpartitions;
case CL_ENGINE_MAX_ICONSPE:
@@ -1081,15 +1033,6 @@ struct cl_settings *cl_engine_settings_copy(const struct cl_engine *engine)
settings->engine_options = engine->engine_options;
settings->cache_size = engine->cache_size;
- settings->cb_stats_add_sample = engine->cb_stats_add_sample;
- settings->cb_stats_remove_sample = engine->cb_stats_remove_sample;
- settings->cb_stats_decrement_count = engine->cb_stats_decrement_count;
- settings->cb_stats_submit = engine->cb_stats_submit;
- settings->cb_stats_flush = engine->cb_stats_flush;
- settings->cb_stats_get_num = engine->cb_stats_get_num;
- settings->cb_stats_get_size = engine->cb_stats_get_size;
- settings->cb_stats_get_hostid = engine->cb_stats_get_hostid;
-
settings->maxpartitions = engine->maxpartitions;
settings->maxiconspe = engine->maxiconspe;
@@ -1162,15 +1105,6 @@ cl_error_t cl_engine_settings_apply(struct cl_engine *engine, const struct cl_se
engine->cb_meta = settings->cb_meta;
engine->cb_file_props = settings->cb_file_props;
- engine->cb_stats_add_sample = settings->cb_stats_add_sample;
- engine->cb_stats_remove_sample = settings->cb_stats_remove_sample;
- engine->cb_stats_decrement_count = settings->cb_stats_decrement_count;
- engine->cb_stats_submit = settings->cb_stats_submit;
- engine->cb_stats_flush = settings->cb_stats_flush;
- engine->cb_stats_get_num = settings->cb_stats_get_num;
- engine->cb_stats_get_size = settings->cb_stats_get_size;
- engine->cb_stats_get_hostid = settings->cb_stats_get_hostid;
-
engine->maxpartitions = settings->maxpartitions;
engine->maxiconspe = settings->maxiconspe;
diff --git a/libclamav/others.h b/libclamav/others.h
index d58959942..c02667945 100644
--- a/libclamav/others.h
+++ b/libclamav/others.h
@@ -201,36 +201,6 @@ typedef struct cli_ctx_tag {
bool abort_scan; /* So we can guarantee a scan is aborted, even if CL_ETIMEOUT/etc. status is lost in the scan recursion stack. */
} cli_ctx;
-#define STATS_ANON_UUID "5b585e8f-3be5-11e3-bf0b-18037319526c"
-#define STATS_MAX_SAMPLES 50
-#define STATS_MAX_MEM 1024 * 1024
-
-typedef struct cli_flagged_sample {
- char **virus_name;
- char md5[MD5_HASH_SIZE];
- uint32_t size; /* A size of zero means size is unavailable (why would this ever happen?) */
- uint32_t hits;
- stats_section_t *sections;
-
- struct cli_flagged_sample *prev;
- struct cli_flagged_sample *next;
-} cli_flagged_sample_t;
-
-typedef struct cli_clamav_intel {
- char *hostid;
- char *host_info;
- cli_flagged_sample_t *samples;
- uint32_t nsamples;
- uint32_t maxsamples;
- uint32_t maxmem;
- uint32_t timeout;
- time_t nextupdate;
- struct cl_engine *engine;
-#ifdef CL_THREAD_SAFE
- pthread_mutex_t mutex;
-#endif
-} cli_intel_t;
-
typedef struct {
uint64_t v[2][4];
} icon_groupset;
@@ -423,17 +393,6 @@ struct cl_engine {
uint64_t maxscriptnormalize; /* max size to normalize scripts */
uint64_t maxziptypercg; /* max size to re-do zip filetype */
- /* Statistics/intelligence gathering */
- void *stats_data;
- clcb_stats_add_sample cb_stats_add_sample;
- clcb_stats_remove_sample cb_stats_remove_sample;
- clcb_stats_decrement_count cb_stats_decrement_count;
- clcb_stats_submit cb_stats_submit;
- clcb_stats_flush cb_stats_flush;
- clcb_stats_get_num cb_stats_get_num;
- clcb_stats_get_size cb_stats_get_size;
- clcb_stats_get_hostid cb_stats_get_hostid;
-
/* Raw disk image max settings */
uint32_t maxpartitions; /* max number of partitions to scan in a disk image */
@@ -501,17 +460,6 @@ struct cl_settings {
uint64_t maxscriptnormalize; /* max size to normalize scripts */
uint64_t maxziptypercg; /* max size to re-do zip filetype */
- /* Statistics/intelligence gathering */
- void *stats_data;
- clcb_stats_add_sample cb_stats_add_sample;
- clcb_stats_remove_sample cb_stats_remove_sample;
- clcb_stats_decrement_count cb_stats_decrement_count;
- clcb_stats_submit cb_stats_submit;
- clcb_stats_flush cb_stats_flush;
- clcb_stats_get_num cb_stats_get_num;
- clcb_stats_get_size cb_stats_get_size;
- clcb_stats_get_hostid cb_stats_get_hostid;
-
/* Raw disk image max settings */
uint32_t maxpartitions; /* max number of partitions to scan in a disk image */
diff --git a/libclamav/pe.c b/libclamav/pe.c
index f1010d61d..918696901 100644
--- a/libclamav/pe.c
+++ b/libclamav/pe.c
@@ -5698,26 +5698,19 @@ finish:
return ret;
}
-/* Print out either the MD5, SHA1, or SHA2-256 associated with the imphash or
- * the individual sections. Also, this function computes the hashes of each
- * section (sorted based on the RVAs of the sections) if hashes is non-NULL.
+/* Generate and, when debug logging is enabled, print the MD5, SHA1, or
+ * SHA2-256 associated with the imphash or the individual sections. Section
+ * hashes are computed after sorting sections by raw file offset.
*
- * If the section hashes are to be computed and returned, this function
- * allocates memory for the section hashes, and it's up to the caller to free
- * it. hashes->sections will be initialized to NULL at the beginning of the
- * function, and if after the call its value is non-NULL, the memory should be
- * freed. Furthermore, if hashes->sections is non-NULL, the hashes can assume
- * to be valid regardless of the return code.
- *
- * Also, a few other notes:
- * - If a section has a virtual size of zero, its corresponding hash value
- * will not be computed and the hash contents will be all zeroes.
- * - If a section extends beyond the end of the file, the section data and
- * length will be truncated, and the hash generated accordingly
- * - If a section exists completely outside of the file, it won't be included
- * in the list of sections, and nsections will be adjusted accordingly.
+ * A few other notes:
+ * - Sections with zero raw size, sections larger than CLI_MAX_ALLOCATION, or
+ * sections whose raw data cannot be mapped do not produce a hash.
+ * - If a section's raw data extends beyond the end of the file, cli_peheader()
+ * truncates the raw size and the hash is generated from that truncated span.
+ * - If a section exists completely outside of the file, cli_peheader() sets
+ * its raw size to zero, so no section hash is printed for it.
*/
-cl_error_t cli_genhash_pe(cli_ctx *ctx, unsigned int class, cli_hash_type_t type, stats_section_t *hashes)
+cl_error_t cli_genhash_pe(cli_ctx *ctx, unsigned int class, cli_hash_type_t type)
{
unsigned int i;
struct cli_exe_info _peinfo;
@@ -5728,15 +5721,6 @@ cl_error_t cli_genhash_pe(cli_ctx *ctx, unsigned int class, cli_hash_type_t type
bool genhash[CLI_HASH_AVAIL_TYPES] = {false};
int hlen = 0;
- if (hashes) {
- hashes->sections = NULL;
-
- if (class != CL_GENHASH_PE_CLASS_SECTION || type != 1) {
- cli_dbgmsg("`hashes` can only be populated with MD5 PE section data\n");
- return CL_EARG;
- }
- }
-
if (class >= CL_GENHASH_PE_CLASS_LAST)
return CL_EARG;
@@ -5768,17 +5752,6 @@ cl_error_t cli_genhash_pe(cli_ctx *ctx, unsigned int class, cli_hash_type_t type
return CL_EMEM;
}
- if (hashes) {
- hashes->nsections = peinfo->nsections;
- hashes->sections = cli_max_calloc(peinfo->nsections, sizeof(struct cli_section_hash));
-
- if (!(hashes->sections)) {
- cli_exe_info_destroy(peinfo);
- free(hash);
- return CL_EMEM;
- }
- }
-
if (class == CL_GENHASH_PE_CLASS_SECTION) {
char *dstr;
@@ -5792,10 +5765,6 @@ cl_error_t cli_genhash_pe(cli_ctx *ctx, unsigned int class, cli_hash_type_t type
free(dstr);
}
}
- if (hashes) {
- memcpy(hashes->sections[i].md5, hash, sizeof(hashes->sections[i].md5));
- hashes->sections[i].len = peinfo->sections[i].rsz;
- }
} else if (peinfo->sections[i].rsz) {
cli_dbgmsg("Section{%u}: failed to generate hash for section\n", i);
} else {
diff --git a/libclamav/pe.h b/libclamav/pe.h
index 74ac83f80..4e15f20d1 100644
--- a/libclamav/pe.h
+++ b/libclamav/pe.h
@@ -91,7 +91,7 @@ cl_error_t cli_pe_targetinfo(cli_ctx *ctx, struct cli_exe_info *peinfo);
cl_error_t cli_peheader(cli_ctx *ctx, struct cli_exe_info *peinfo, uint32_t opts);
cl_error_t cli_check_auth_header(cli_ctx *ctx, struct cli_exe_info *peinfo);
-cl_error_t cli_genhash_pe(cli_ctx *ctx, unsigned int class, cli_hash_type_t type, stats_section_t *hashes);
+cl_error_t cli_genhash_pe(cli_ctx *ctx, unsigned int class, cli_hash_type_t type);
uint32_t cli_rawaddr(uint32_t, const struct cli_exe_section *, uint16_t, unsigned int *, size_t, uint32_t);
void findres(uint32_t, uint32_t, fmap_t *map, struct cli_exe_info *, int (*)(void *, uint32_t, uint32_t, uint32_t, uint32_t), void *);
diff --git a/libclamav/readdb.c b/libclamav/readdb.c
index befc68e13..008e4143e 100644
--- a/libclamav/readdb.c
+++ b/libclamav/readdb.c
@@ -5618,24 +5618,10 @@ cl_error_t cl_engine_free(struct cl_engine *engine)
return CL_SUCCESS;
}
- if (engine->cb_stats_submit)
- engine->cb_stats_submit(engine, engine->stats_data);
-
#ifdef CL_THREAD_SAFE
- if (engine->stats_data) {
- cli_intel_t *intel = (cli_intel_t *)(engine->stats_data);
-
- pthread_mutex_destroy(&(intel->mutex));
- }
-
pthread_mutex_unlock(&cli_ref_mutex);
#endif
- if (engine->stats_data) {
- free(engine->stats_data);
- engine->stats_data = NULL;
- }
-
/*
* Pre-calculate number of "major" tasks to complete for the progress callback
*/
diff --git a/libclamav/stats.c b/libclamav/stats.c
deleted file mode 100644
index 8f749a4f3..000000000
--- a/libclamav/stats.c
+++ /dev/null
@@ -1,703 +0,0 @@
-/*
- * 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
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <sys/types.h>
-#if !defined(_WIN32)
-#if defined(C_SOLARIS)
-#include <sys/utsname.h>
-#else
-#if HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#if HAVE_SYSCTLBYNAME
-#include <sys/sysctl.h>
-#endif
-#endif
-#else
-#include <Windows.h>
-#include <tchar.h>
-#endif
-
-#ifdef CL_THREAD_SAFE
-#include <pthread.h>
-#endif
-
-#include <errno.h>
-
-#include "others.h"
-#include "clamav.h"
-#include "dconf.h"
-#include "stats_json.h"
-#include "stats.h"
-#include "hostid_internal.h"
-#include "www.h"
-
-#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);
-
-#if DEBUG_STATS
-char *get_hash(unsigned char *md5)
-{
- char *hash;
- int i;
-
- hash = calloc(1, 33);
- if (!(hash))
- return NULL;
-
- for (i = 0; i < 16; i++)
- sprintf(hash + (i * 2), "%02x", md5[i]);
-
- return hash;
-}
-
-char *get_sample_names(char **names)
-{
- char *ret;
- size_t n, i, sz;
-
- sz = 0;
- for (n = 0; names[n] != NULL; n++)
- sz += strlen(names[n]);
-
- ret = calloc(1, sz + n + 1);
- if (!(ret))
- return NULL;
-
- for (i = 0; names[i] != NULL; i++)
- sprintf(ret + strlen(ret), "%s%s", (i == 0) ? "" : " ", names[i]);
-
- return ret;
-}
-
-void print_sample(cli_flagged_sample_t *sample)
-{
- char *hash, *names;
- size_t i;
-
- if (!(sample))
- return;
-
- hash = get_hash(sample->md5);
- if (!(hash))
- return;
-
- cli_warnmsg("Sample[%s]:\n", hash);
- cli_warnmsg(" * Size: %zu\n", sample->size);
- cli_warnmsg(" * Hits: %u\n", sample->hits);
-
- free(hash);
-
- names = get_sample_names(sample->virus_name);
- if ((names))
- cli_warnmsg(" * Names: %s\n", names);
-
- if (sample->sections && sample->sections->nsections) {
- for (i = 0; i < sample->sections->nsections; i++) {
- hash = get_hash(sample->sections->sections[i].md5);
- if ((hash)) {
- cli_warnmsg(" * Section[%zu] (%zu): %s\n", i, sample->sections->sections[i].len, hash);
- free(hash);
- }
- }
- }
-
- if ((names))
- free(names);
-}
-#endif
-
-void clamav_stats_add_sample(const char *virname, const unsigned char *md5, size_t size, stats_section_t *sections, void *cbdata)
-{
- cli_intel_t *intel;
- cli_flagged_sample_t *sample;
- size_t i;
- char **p;
- int err, submit = 0;
-
- if (!(cbdata))
- return;
-
- intel = (cli_intel_t *)cbdata;
- 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);
- else
- submit = (clamav_stats_get_size(cbdata) >= intel->maxmem);
-
- if (submit == 0) {
- if ((intel->engine->cb_stats_get_num))
- submit = (intel->engine->cb_stats_get_num(cbdata) >= intel->maxsamples);
- else
- submit = (clamav_stats_get_num(cbdata) >= intel->maxsamples);
- }
-
- if (submit) {
- if ((intel->engine->cb_stats_submit)) {
- intel->engine->cb_stats_submit(intel->engine, cbdata);
- } else {
- if ((intel->engine->cb_stats_flush))
- intel->engine->cb_stats_flush(intel->engine, intel);
-
- return;
- }
- }
-
-#ifdef CL_THREAD_SAFE
- err = pthread_mutex_lock(&(intel->mutex));
- if (err) {
- cli_warnmsg("clamav_stats_add_sample: locking mutex failed (err: %d): %s\n", err, strerror(err));
- return;
- }
-#endif
-
- sample = find_sample(intel, virname, md5, size, sections);
- if (!(sample)) {
- if (!(intel->samples)) {
- sample = intel->samples = calloc(1, sizeof(cli_flagged_sample_t));
- if (!(sample))
- goto end;
- } else {
- sample = calloc(1, sizeof(cli_flagged_sample_t));
- if (!(sample))
- goto end;
-
- sample->next = intel->samples;
- intel->samples->prev = sample;
- intel->samples = sample;
- }
-
- 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 **));
- if (!(sample->virus_name)) {
- free(sample);
- if (sample == intel->samples)
- intel->samples = NULL;
-
- goto end;
- }
- }
-
- sample->virus_name[i] = strdup((virname != NULL) ? virname : "[unknown]");
- if (!(sample->virus_name[i])) {
- free(sample->virus_name);
- free(sample);
- if (sample == intel->samples)
- intel->samples = NULL;
-
- goto end;
- }
-
- p = realloc(sample->virus_name, sizeof(char **) * (i + 2));
- if (!(p)) {
- free(sample->virus_name);
- free(sample);
- if (sample == intel->samples)
- intel->samples = NULL;
-
- goto end;
- }
-
- sample->virus_name = p;
- sample->virus_name[i + 1] = NULL;
-
- memcpy(sample->md5, md5, sizeof(sample->md5));
- sample->size = (uint32_t)size;
- intel->nsamples++;
-
- if (sections && sections->nsections && !(sample->sections)) {
- /* Copy the section data that has already been allocated. We don't care if calloc fails; just skip copying if it does. */
- sample->sections = calloc(1, sizeof(stats_section_t));
- if ((sample->sections)) {
- sample->sections->sections = calloc(sections->nsections, sizeof(struct cli_section_hash));
- if ((sample->sections->sections)) {
- memcpy(sample->sections->sections, sections->sections, sections->nsections * sizeof(struct cli_section_hash));
- sample->sections->nsections = sections->nsections;
- } else {
- free(sample->sections);
- sample->sections = NULL;
- }
- }
- }
- }
-
- sample->hits++;
-
-end:
-#ifdef CL_THREAD_SAFE
- err = pthread_mutex_unlock(&(intel->mutex));
- if (err) {
- cli_warnmsg("clamav_stats_add_sample: unlocking mutex failed (err: %d): %s\n", err, strerror(err));
- }
-#endif
- return;
-}
-
-void clamav_stats_flush(struct cl_engine *engine, void *cbdata)
-{
- cli_intel_t *intel;
- cli_flagged_sample_t *sample, *next;
- int err;
-
- if (!(cbdata) || !(engine))
- return;
-
- intel = (cli_intel_t *)cbdata;
-
-#ifdef CL_THREAD_SAFE
- err = pthread_mutex_lock(&(intel->mutex));
- if (err) {
- cli_warnmsg("clamav_stats_flush: locking mutex failed (err: %d): %s\n", err, strerror(err));
- return;
- }
-#endif
-
- for (sample = intel->samples; sample != NULL; sample = next) {
- next = sample->next;
-
- free_sample(sample);
- }
-
- intel->samples = NULL;
- intel->nsamples = 0;
- if (intel->hostid) {
- free(intel->hostid);
- intel->hostid = NULL;
- }
-
-#ifdef CL_THREAD_SAFE
- err = pthread_mutex_unlock(&(intel->mutex));
- if (err)
- cli_warnmsg("clamav_stats_flush: unlocking mutex failed (err: %d): %s\n", err, strerror(err));
-#endif
-}
-
-void free_sample(cli_flagged_sample_t *sample)
-{
- size_t i;
-
- if ((sample->virus_name)) {
- for (i = 0; sample->virus_name[i] != NULL; i++)
- free(sample->virus_name[i]);
-
- free(sample->virus_name);
- }
-
- if ((sample->sections) && (sample->sections->nsections)) {
- free(sample->sections->sections);
- free(sample->sections);
- }
-
- free(sample);
-}
-
-void clamav_stats_submit(struct cl_engine *engine, void *cbdata)
-{
- char *json;
- cli_intel_t *intel, myintel;
- cli_flagged_sample_t *sample, *next;
- int err;
-
- intel = (cli_intel_t *)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))
- engine->cb_stats_flush(engine, cbdata);
-
- return;
- }
-
- cli_dbgmsg("stats - start\n");
-
-#ifdef CL_THREAD_SAFE
- err = pthread_mutex_lock(&(intel->mutex));
- if (err) {
- cli_warnmsg("clamav_stats_submit: locking mutex failed (err: %d): %s\n", err, strerror(err));
-
- if ((intel->engine) && (intel->engine->cb_stats_flush))
- intel->engine->cb_stats_flush(intel->engine, cbdata);
-
- return;
- }
-#endif
-
- /* Empty out the cached intelligence data so that other threads don't sit waiting to add data to the cache */
- memcpy(&myintel, intel, sizeof(cli_intel_t));
- intel->samples = NULL;
- intel->nsamples = 0;
-
- json = export_stats_to_json(engine, &myintel);
-
-#ifdef CL_THREAD_SAFE
- err = pthread_mutex_unlock(&(intel->mutex));
- if (err) {
- cli_warnmsg("clamav_stats_submit: unlocking mutex failed (err: %d): %s\n", err, strerror(err));
- }
-#endif
-
- for (sample = myintel.samples; sample != NULL; sample = next) {
-#if DEBUG_STATS
- print_sample(sample);
-#endif
- next = sample->next;
-
- free_sample(sample);
- }
-
- if (json) {
- submit_post(STATS_HOST, STATS_PORT, "PUT", "/clamav/1/submit/stats", json, myintel.timeout);
- free(json);
- }
-
- if (myintel.hostid && !(intel->hostid)) {
- free(myintel.hostid);
- myintel.hostid = NULL;
- }
-
- cli_dbgmsg("stats - end\n");
-}
-
-void clamav_stats_remove_sample(const char *virname, const unsigned char *md5, size_t size, void *cbdata)
-{
- cli_intel_t *intel;
- cli_flagged_sample_t *sample;
- int err;
-
- intel = (cli_intel_t *)cbdata;
- if (!(intel))
- return;
-
-#ifdef CL_THREAD_SAFE
- err = pthread_mutex_lock(&(intel->mutex));
- if (err) {
- cli_warnmsg("clamav_stats_remove_sample: locking mutex failed (err: %d): %s\n", err, strerror(err));
- return;
- }
-#endif
-
- while ((sample = find_sample(intel, virname, md5, size, NULL))) {
- if (sample->prev)
- sample->prev->next = sample->next;
- if (sample->next)
- sample->next->prev = sample->prev;
- if (sample == intel->samples)
- intel->samples = sample->next;
-
- free_sample(sample);
- intel->nsamples--;
- }
-
-#ifdef CL_THREAD_SAFE
- err = pthread_mutex_unlock(&(intel->mutex));
- if (err) {
- cli_warnmsg("clamav_stats_remove_sample: unlocking mutex failed (err: %d): %s\n", err, strerror(err));
- }
-#endif
-}
-
-void clamav_stats_decrement_count(const char *virname, const unsigned char *md5, size_t size, void *cbdata)
-{
- cli_intel_t *intel;
- cli_flagged_sample_t *sample;
- int err;
-
- intel = (cli_intel_t *)cbdata;
- if (!(intel))
- return;
-
-#ifdef CL_THREAD_SAFE
- err = pthread_mutex_lock(&(intel->mutex));
- if (err) {
- cli_warnmsg("clamav_stats_decrement_count: locking mutex failed (err: %d): %s\n", err, strerror(err));
- return;
- }
-#endif
-
- sample = find_sample(intel, virname, md5, size, NULL);
- if (!(sample))
- goto clamav_stats_decrement_end;
-
- if (sample->hits == 1) {
- if ((intel->engine->cb_stats_remove_sample))
- intel->engine->cb_stats_remove_sample(virname, md5, size, intel);
- else
- clamav_stats_remove_sample(virname, md5, size, intel);
-
- goto clamav_stats_decrement_end;
- }
-
- sample->hits--;
-
-clamav_stats_decrement_end:
-#ifdef CL_THREAD_SAFE
- err = pthread_mutex_unlock(&(intel->mutex));
- if (err) {
- cli_warnmsg("clamav_stats_decrement_count: unlocking mutex failed (err: %d): %s\n", err, strerror(err));
- }
-#endif
- return;
-}
-
-size_t clamav_stats_get_num(void *cbdata)
-{
- cli_intel_t *intel;
-
- intel = (cli_intel_t *)cbdata;
-
- if (!(intel))
- return 0;
-
- return intel->nsamples;
-}
-
-size_t clamav_stats_get_size(void *cbdata)
-{
- cli_intel_t *intel;
- cli_flagged_sample_t *sample;
- size_t sz, i;
- int err;
-
- intel = (cli_intel_t *)cbdata;
- if (!(intel))
- return 0;
-
- sz = sizeof(cli_intel_t);
-
-#ifdef CL_THREAD_SAFE
- err = pthread_mutex_lock(&(intel->mutex));
- if (err) {
- cli_warnmsg("clamav_stats_get_size: locking mutex failed (err: %d): %s\n", err, strerror(err));
- return sz;
- }
-#endif
-
- for (sample = intel->samples; sample != NULL; sample = sample->next) {
- sz += sizeof(cli_flagged_sample_t);
- if ((sample->virus_name)) {
- for (i = 0; sample->virus_name[i] != NULL; i++)
- sz += strlen(sample->virus_name[i]);
- sz += sizeof(char **) * i;
- }
- }
-
-#ifdef CL_THREAD_SAFE
- err = pthread_mutex_unlock(&(intel->mutex));
- if (err) {
- cli_warnmsg("clamav_stats_get_size: unlocking mutex failed (err: %d): %s\n", err, strerror(err));
- }
-#endif
-
- return sz;
-}
-
-#if defined(_WIN32)
-char *clamav_stats_get_hostid(void *cbdata)
-{
- HW_PROFILE_INFO HwProfInfo;
-
- if (!GetCurrentHwProfile(&HwProfInfo))
- return strdup(STATS_ANON_UUID);
-
- return strdup(HwProfInfo.szHwProfileGuid);
-}
-#elif defined(C_SOLARIS)
-char *clamav_stats_get_hostid(void *cbdata)
-{
- struct utsname utsnm;
- int ret;
-
- ret = uname(&utsnm);
- if (ret != -1)
- return strdup(utsnm.nodename);
-
- return strdup(STATS_ANON_UUID);
-}
-#else
-char *clamav_stats_get_hostid(void *cbdata)
-{
- char *buf;
-
-#if HAVE_SYSCTLBYNAME
- char *sysctls[] = {"kern.hostuuid", NULL};
- size_t bufsz, i;
-#endif
-
- UNUSEDPARAM(cbdata);
-
-#if HAVE_SYSCTLBYNAME
- /*
- * FreeBSD provides a handy-dandy sysctl for grabbing the system's HostID. In a jail that
- * hasn't run the hostid rc.d script, the hostid defaults to all zeros.
- */
- for (i = 0; sysctls[i] != NULL; i++) {
- if (sysctlbyname(sysctls[i], NULL, &bufsz, NULL, 0))
- continue;
-
- break; /* Got one */
- }
-
- if (sysctls[i] != NULL) {
- buf = calloc(1, bufsz + 1);
- if (sysctlbyname(sysctls[i], buf, &bufsz, NULL, 0))
- return strdup(STATS_ANON_UUID); /* Not sure why this would happen, but we'll just default to the anon uuid on error */
-
- return buf;
- }
-
- return strdup(STATS_ANON_UUID);
-#else
- buf = internal_get_host_id();
- if (!(buf))
- return strdup(STATS_ANON_UUID);
- return buf;
-#endif
-}
-#endif
-
-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)
-{
- cli_flagged_sample_t *sample;
- size_t i;
-
- for (sample = intel->samples; sample != NULL; sample = sample->next) {
- int foundSections = 0;
-
- if (sample->size != size)
- continue;
-
- if (memcmp(sample->md5, md5, sizeof(sample->md5)))
- continue;
-
- if (!(virname))
- return sample;
-
- if ((sections) && (sample->sections)) {
- if (sections->nsections == sample->sections->nsections) {
- for (i = 0; i < sections->nsections; i++)
- if (sections->sections[i].len == sample->sections->sections[i].len)
- if (memcmp(sections->sections[i].md5, sample->sections->sections[i].md5, sizeof(stats_section_t)))
- break;
-
- if (i == sections->nsections)
- foundSections = 1;
- }
- } else {
- foundSections = 1;
- }
-
- if (foundSections)
- for (i = 0; sample->virus_name[i] != NULL; i++)
- if (!strcmp(sample->virus_name[i], virname))
- return sample;
- }
-
- return NULL;
-}
-
-void cl_engine_set_clcb_stats_submit(struct cl_engine *engine, clcb_stats_submit callback)
-{
- engine->cb_stats_submit = callback;
-}
-
-void cl_engine_set_stats_set_cbdata(struct cl_engine *engine, void *cbdata)
-{
- engine->stats_data = cbdata;
-}
-
-void cl_engine_set_clcb_stats_add_sample(struct cl_engine *engine, clcb_stats_add_sample callback)
-{
- engine->cb_stats_add_sample = callback;
-}
-
-void cl_engine_set_clcb_stats_remove_sample(struct cl_engine *engine, clcb_stats_remove_sample callback)
-{
- engine->cb_stats_remove_sample = callback;
-}
-
-void cl_engine_set_clcb_stats_decrement_count(struct cl_engine *engine, clcb_stats_decrement_count callback)
-{
- engine->cb_stats_decrement_count = callback;
-}
-
-void cl_engine_set_clcb_stats_flush(struct cl_engine *engine, clcb_stats_flush callback)
-{
- engine->cb_stats_flush = callback;
-}
-
-void cl_engine_set_clcb_stats_get_num(struct cl_engine *engine, clcb_stats_get_num callback)
-{
- engine->cb_stats_get_num = callback;
-}
-
-void cl_engine_set_clcb_stats_get_size(struct cl_engine *engine, clcb_stats_get_size callback)
-{
- engine->cb_stats_get_size = callback;
-}
-
-void cl_engine_set_clcb_stats_get_hostid(struct cl_engine *engine, clcb_stats_get_hostid callback)
-{
- engine->cb_stats_get_hostid = callback;
-}
-
-void cl_engine_stats_enable(struct cl_engine *engine)
-{
- engine->cb_stats_add_sample = clamav_stats_add_sample;
- engine->cb_stats_submit = clamav_stats_submit;
-}
diff --git a/libclamav/stats.h b/libclamav/stats.h
deleted file mode 100644
index e9693e493..000000000
--- a/libclamav/stats.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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
-
-#define STATS_HOST "intel.clamav.net"
-#define STATS_PORT "80"
-
-void clamav_stats_add_sample(const char *virname, const unsigned char *md5, size_t size, stats_section_t *sections, void *cbdata);
-void clamav_stats_submit(struct cl_engine *engine, void *cbdata);
-void clamav_stats_flush(struct cl_engine *engine, void *cbdata);
-void clamav_stats_remove_sample(const char *virname, const unsigned char *md5, size_t size, void *cbdata);
-void clamav_stats_decrement_count(const char *virname, const unsigned char *md5, size_t size, void *cbdata);
-size_t clamav_stats_get_num(void *cbdata);
-size_t clamav_stats_get_size(void *cbdata);
-char *clamav_stats_get_hostid(void *cbdata);
-
-#endif
diff --git a/libclamav/stats_json.c b/libclamav/stats_json.c
deleted file mode 100644
index e0a8e13f6..000000000
--- a/libclamav/stats_json.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <sys/types.h>
-#include <errno.h>
-
-#if defined(_WIN32)
-#include <WinSock2.h>
-#include <Windows.h>
-#endif
-
-#include "others.h"
-#include "clamav.h"
-
-#define JSON_BUFSZ 512
-#define SAMPLE_PREFIX "sample_"
-
-char *hex_encode(char *buf, char *data, size_t len);
-char *ensure_bufsize(char *buf, size_t *oldsize, size_t used, size_t additional);
-char *export_stats_to_json(struct cl_engine *engine, cli_intel_t *intel);
-
-char *hex_encode(char *buf, char *data, size_t len)
-{
- size_t i;
- char *p;
- int t;
-
- p = (buf != NULL) ? buf : calloc(1, (len * 2) + 1);
- if (!(p))
- return NULL;
-
- for (i = 0; i < len; i++) {
- t = data[i] & 0xff;
- sprintf(p + (i * 2), "%02x", t);
- }
-
- return p;
-}
-
-char *ensure_bufsize(char *buf, size_t *oldsize, size_t used, size_t additional)
-{
- char *p = buf;
-
- if (*oldsize - used < additional) {
- p = realloc(buf, *oldsize + JSON_BUFSZ);
- if (!(p)) {
- cli_errmsg("ensure_bufsize: Could not allocate more memory: %s (errno: %d)\n", strerror(errno), errno);
- free(buf);
- return NULL;
- }
-
- *oldsize += JSON_BUFSZ;
- }
-
- return p;
-}
-
-char *export_stats_to_json(struct cl_engine *engine, cli_intel_t *intel)
-{
- char *buf = NULL, *hostid, md5[33];
- cli_flagged_sample_t *sample;
- size_t bufsz, curused, i, j;
-
- if (!(intel->hostid))
- if ((engine->cb_stats_get_hostid))
- intel->hostid = engine->cb_stats_get_hostid(engine->stats_data);
-
- hostid = (intel->hostid != NULL) ? intel->hostid : STATS_ANON_UUID;
-
- buf = calloc(1, JSON_BUFSZ);
- if (!(buf))
- return NULL;
-
- bufsz = JSON_BUFSZ;
- sprintf(buf, "{\n\t\"hostid\": \"%s\",\n", hostid);
- if (intel->host_info)
- sprintf(buf + strlen(buf), "\t\"host_info\": \"%s\",\n", intel->host_info);
-
- sprintf(buf + strlen(buf), "\t\"samples\": [\n");
- curused = strlen(buf);
-
- for (sample = intel->samples; sample != NULL; sample = sample->next) {
- if (sample->hits == 0)
- continue;
-
- memset(md5, 0x00, sizeof(md5));
- hex_encode(md5, sample->md5, sizeof(sample->md5));
-
- buf = ensure_bufsize(buf, &bufsz, curused, strlen(md5) + sizeof(SAMPLE_PREFIX) + 45);
- if (!(buf))
- return NULL;
-
- snprintf(buf + curused, bufsz - curused, "\t\t\t{\n");
- curused += strlen(buf + curused);
-
- buf = ensure_bufsize(buf, &bufsz, curused, sizeof("\t\t\t\"hash\": \"\",\n") + strlen(md5) + 1);
- if (!(buf))
- return NULL;
-
- snprintf(buf + curused, bufsz - curused, "\t\t\t\"hash\": \"%s\",\n", md5);
- curused += strlen(buf + curused);
-
- /* Reuse the md5 variable for serializing the number of hits */
- snprintf(md5, sizeof(md5), "%u", sample->hits);
-
- buf = ensure_bufsize(buf, &bufsz, curused, strlen(md5) + 20);
- if (!(buf))
- return NULL;
-
- snprintf(buf + curused, bufsz - curused, "\t\t\t\"hits\": %s,\n", md5);
- curused += strlen(buf + curused);
-
- snprintf(md5, sizeof(md5), "%u", sample->size);
-
- buf = ensure_bufsize(buf, &bufsz, curused, strlen(md5) + 20);
- if (!(buf))
- return NULL;
-
- snprintf(buf + curused, bufsz - curused, "\t\t\t\"size\": %s,\n", md5);
- curused += strlen(buf + curused);
-
- buf = ensure_bufsize(buf, &bufsz, curused, 30);
- if (!(buf))
- return NULL;
-
- if ((sample->sections) && (sample->sections->nsections)) {
- buf = ensure_bufsize(buf, &bufsz, curused, 30);
- if (!(buf))
- return NULL;
-
- snprintf(buf + curused, bufsz - curused, "\t\t\t\"sections\": [\n");
- curused += strlen(buf + curused);
-
- for (i = 0; i < sample->sections->nsections; i++) {
- buf = ensure_bufsize(buf, &bufsz, curused, 30);
- if (!(buf))
- return NULL;
-
- snprintf(buf + curused, bufsz - curused, "\t\t\t\t%s{\n", (i > 0) ? "," : "");
- curused += strlen(buf + curused);
-
- buf = ensure_bufsize(buf, &bufsz, curused, 65);
- if (!(buf))
- return NULL;
-
- memset(md5, 0x00, sizeof(md5));
- for (j = 0; j < 16; j++)
- sprintf(md5 + (j * 2), "%02x", sample->sections->sections[i].md5[j]);
-
- snprintf(buf + curused, bufsz - curused, "\t\t\t\t\t\"hash\": \"%s\",\n", md5);
- curused += strlen(buf + curused);
-
- buf = ensure_bufsize(buf, &bufsz, curused, 65);
- if (!(buf))
- return NULL;
-
- snprintf(buf + curused, bufsz - curused, "\t\t\t\t\t\"size\": %llu\n", (long long unsigned)sample->sections->sections[i].len);
- curused += strlen(buf + curused);
-
- buf = ensure_bufsize(buf, &bufsz, curused, 30);
- if (!(buf))
- return NULL;
-
- snprintf(buf + curused, bufsz - curused, "\t\t\t\t}\n");
- curused += strlen(buf + curused);
- }
-
- buf = ensure_bufsize(buf, &bufsz, curused, 20);
- if (!(buf))
- return NULL;
-
- snprintf(buf + curused, bufsz - curused, "\t\t\t],\n");
- curused += strlen(buf + curused);
- }
-
- snprintf(buf + curused, bufsz - curused, "\t\t\t\"virus_names\": [ ");
- curused += strlen(buf + curused);
-
- for (i = 0; sample->virus_name[i] != NULL; i++) {
- buf = ensure_bufsize(buf, &bufsz, curused, strlen(sample->virus_name[i]) + 5);
- if (!(buf))
- return NULL;
-
- snprintf(buf + curused, bufsz - curused, "%s\"%s\"", (i > 0) ? ", " : "", sample->virus_name[i]);
- curused += strlen(buf + curused);
- }
-
- buf = ensure_bufsize(buf, &bufsz, curused, 10);
- if (!(buf))
- return NULL;
-
- snprintf(buf + curused, bufsz - curused, " ]\n\t\t}%s\n", (sample->next != NULL) ? "," : "");
- curused += strlen(buf + curused);
- }
-
- buf = ensure_bufsize(buf, &bufsz, curused, 15);
- if (!(buf))
- return NULL;
-
- snprintf(buf + curused, bufsz - curused, "\t]\n}\n");
-
- return buf;
-}
diff --git a/libclamav/stats_json.h b/libclamav/stats_json.h
deleted file mode 100644
index 118f09d6c..000000000
--- a/libclamav/stats_json.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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
-
-char *export_stats_to_json(struct cl_engine *engine, cli_intel_t *intel);
-
-#endif
diff --git a/libclamav/www.c b/libclamav/www.c
deleted file mode 100644
index cb5cf75be..000000000
--- a/libclamav/www.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (C) 2014-2026 Cisco Systems, Inc. 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
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <ctype.h>
-
-#include <sys/types.h>
-#include <fcntl.h>
-
-#include <errno.h>
-
-#if !defined(_WIN32)
-#include <sys/socket.h>
-#if HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#else
-#include <sys/time.h>
-#endif
-#include <netinet/in.h>
-#include <netdb.h>
-#endif
-
-#include "platform.h"
-
-#include "others.h"
-#include "clamav.h"
-#include "www.h"
-
-int connect_host(const char *host, const char *port, uint32_t timeout, int useAsync)
-{
- int sockfd = -1;
- struct addrinfo hints, *servinfo = NULL, *p = NULL;
- int flags = 0, error;
- socklen_t len;
- fd_set read_fds, write_fds;
- struct timeval tv;
-#ifdef _WIN32
- int iResult;
- WSADATA wsaData;
-
- /* Force initialization of Windows sockets, even if it already happened elsewhere */
- iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
- if (iResult != 0)
- return -1;
-#endif
-
- memset(&hints, 0x00, sizeof(struct addrinfo));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
-
- if (getaddrinfo(host, port, &hints, &servinfo))
- return -1;
-
- for (p = servinfo; p != NULL; p = p->ai_next) {
- sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
- if (sockfd < 0)
- continue;
-
- if (useAsync) {
- flags = fcntl(sockfd, F_GETFL, 0);
- if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) {
- closesocket(sockfd);
- continue;
- }
- }
-
- if ((error = connect(sockfd, p->ai_addr, p->ai_addrlen))) {
- if (useAsync) {
- if (errno != EINPROGRESS) {
- closesocket(sockfd);
- continue;
- }
- errno = 0;
-
- FD_ZERO(&write_fds);
- FD_ZERO(&read_fds);
- FD_SET(sockfd, &read_fds);
- FD_SET(sockfd, &write_fds);
-
- /* TODO: Make this timeout configurable */
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
- if (select(sockfd + 1, &read_fds, &write_fds, NULL, &tv) <= 0) {
- closesocket(sockfd);
- continue;
- }
-
- if (FD_ISSET(sockfd, &read_fds) || FD_ISSET(sockfd, &write_fds)) {
- len = sizeof(error);
- if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
- closesocket(sockfd);
- continue;
- }
- } else {
- closesocket(sockfd);
- continue;
- }
- } else {
- closesocket(sockfd);
- continue;
- }
- }
-
- /* Connected to host */
- break;
- }
-
- if (!(p)) {
- freeaddrinfo(servinfo);
- if (sockfd >= 0)
- closesocket(sockfd);
- return -1;
- }
-
- freeaddrinfo(servinfo);
-
- /* Return to using a synchronous socket to make Linux happy */
- if (useAsync && (sockfd >= 0)) {
- if (fcntl(sockfd, F_SETFL, flags) < 0) {
- closesocket(sockfd);
- return -1;
- }
- }
-
- return sockfd;
-}
-
-size_t encoded_size(const char *postdata)
-{
- const char *p;
- size_t len = 0;
-
- for (p = postdata; *p != '\0'; p++)
- len += isalnum(*p) ? 1 : 3;
-
- return len;
-}
-
-char *encode_data(const char *postdata)
-{
- char *buf;
- size_t bufsz, i, j;
-
- bufsz = encoded_size(postdata);
- if (bufsz == 0)
- return NULL;
-
- buf = cli_max_calloc(1, bufsz + 1);
- if (!(buf))
- return NULL;
-
- for (i = 0, j = 0; postdata[i] != '\0'; i++) {
- if (isalnum(postdata[i])) {
- buf[j++] = postdata[i];
- } else {
- sprintf(buf + j, "%%%02x", postdata[i]);
- j += 3;
- }
- }
-
- return buf;
-}
-
-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;
- char *buf, *encoded = NULL;
- size_t bufsz;
- ssize_t recvsz;
- char chunkedlen[21];
- fd_set readfds;
- struct timeval tv;
- char *acceptable_methods[] = {
- "GET",
- "PUT",
- "POST",
- NULL};
-
- for (i = 0; acceptable_methods[i] != NULL; i++)
- if (!strcmp(method, acceptable_methods[i]))
- break;
-
- if (acceptable_methods[i] == NULL)
- return;
-
- bufsz = strlen(method);
- bufsz += sizeof(" HTTP/1.1") + 2; /* Yes. Three blank spaces. +1 for the \n */
- bufsz += strlen(url);
- bufsz += sizeof("Host: \r\n");
- bufsz += strlen(host);
- bufsz += sizeof("Connection: Close\r\n");
- bufsz += 4; /* +4 for \r\n\r\n */
-
- if (!strcmp(method, "POST") || !strcmp(method, "PUT")) {
- encoded = encode_data(postdata);
- if (!(encoded))
- return;
- snprintf(chunkedlen, sizeof(chunkedlen), "%zu", strlen(encoded));
- bufsz += sizeof("Content-Type: application/x-www-form-urlencoded\r\n");
- bufsz += sizeof("Content-Length: \r\n");
- bufsz += strlen(chunkedlen);
- bufsz += strlen(encoded);
- }
-
- buf = cli_max_calloc(1, bufsz);
- if (!(buf)) {
- if ((encoded))
- free(encoded);
-
- return;
- }
-
- snprintf(buf, bufsz, "%s %s HTTP/1.1\r\n", method, url);
- snprintf(buf + strlen(buf), bufsz - strlen(buf), "Host: %s\r\n", host);
- snprintf(buf + strlen(buf), bufsz - strlen(buf), "Connection: Close\r\n");
-
- if (!strcmp(method, "POST") || !strcmp(method, "PUT")) {
- snprintf(buf + strlen(buf), bufsz - strlen(buf), "Content-Type: application/x-www-form-urlencoded\r\n");
- snprintf(buf + strlen(buf), bufsz - strlen(buf), "Content-Length: %s\r\n", chunkedlen);
- snprintf(buf + strlen(buf), bufsz - strlen(buf), "\r\n");
- snprintf(buf + strlen(buf), bufsz - strlen(buf), "%s", encoded);
- free(encoded);
- }
-#if defined(_WIN32)
- sockfd = connect_host(host, port, timeout, 0);
-#else
- sockfd = connect_host(host, port, timeout, 1);
-#endif
- if (sockfd < 0) {
- free(buf);
- return;
- }
-
- cli_dbgmsg("stats - Connected to %s:%s\n", host, port);
-
- if ((size_t)send(sockfd, buf, strlen(buf), 0) != (size_t)strlen(buf)) {
- closesocket(sockfd);
- free(buf);
- return;
- }
-
- cli_dbgmsg("stats - Sending %s\n", buf);
-
- while (1) {
- FD_ZERO(&readfds);
- FD_SET(sockfd, &readfds);
-
- /*
- * Check to make sure the stats submitted okay (so that we don't kill the HTTP request
- * while it's being processed). Give a ten-second timeout so we don't have a major
- * impact on scanning.
- */
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
- if ((n = select(sockfd + 1, &readfds, NULL, NULL, &tv)) <= 0)
- break;
-
- if (FD_ISSET(sockfd, &readfds)) {
- memset(buf, 0x00, bufsz);
- if ((recvsz = recv(sockfd, buf, bufsz - 1, 0) <= 0))
- break;
-
- buf[bufsz - 1] = '\0';
-
- cli_dbgmsg("stats - received: %s\n", buf);
-
- if (strstr(buf, "STATOK")) {
- cli_dbgmsg("stats - Data received okay\n");
- break;
- }
- }
- }
-
- closesocket(sockfd);
- free(buf);
-}
diff --git a/libclamav/www.h b/libclamav/www.h
deleted file mode 100644
index 334f0c047..000000000
--- a/libclamav/www.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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, 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, uint32_t timeout);
-
-#endif
diff --git a/libclamav_rust/src/sys.rs b/libclamav_rust/src/sys.rs
index b635bb85c..2f99cb043 100644
--- a/libclamav_rust/src/sys.rs
+++ b/libclamav_rust/src/sys.rs
@@ -100,19 +100,6 @@ pub const bytecode_mode_CL_BYTECODE_MODE_TEST: bytecode_mode = 3;
#[doc = " both JIT and interpreter, compare results, all failures are fatal"]
pub const bytecode_mode_CL_BYTECODE_MODE_OFF: bytecode_mode = 4;
pub type bytecode_mode = ::std::os::raw::c_uint;
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub struct cli_section_hash {
- pub md5: [::std::os::raw::c_uchar; 16usize],
- pub len: usize,
-}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub struct cli_stats_sections {
- pub nsections: usize,
- pub sections: *mut cli_section_hash,
-}
-pub type stats_section_t = cli_stats_sections;
pub type cl_fmap_t = cl_fmap;
#[doc = " @brief Read callback function type.\n\n A callback function pointer type for reading data from a cl_fmap_t that uses\n reads data from a handle interface.\n\n Read 'count' bytes starting at 'offset' into the buffer 'buf'\n\n Thread safety: It is guaranteed that only one callback is executing for a\n specific handle at any time, but there might be multiple callbacks executing\n for different handle at the same time.\n\n @param handle The handle passed to cl_fmap_open_handle, its meaning is up\n to the callback's implementation\n @param buf A buffer to read data into, must be at least offset + count\n bytes in size.\n @param count The number of bytes to read.\n @param offset The offset into buf to read the data to. If successful,\n the number of bytes actually read is returned. Upon reading\n end-of-file, zero is returned. Otherwise, a -1 is returned\n and the global variable errno is set to indicate the error."]
pub type clcb_pread = ::std::option::Option<
@@ -239,52 +226,6 @@ pub type clcb_generic_data = ::std::option::Option<
cbdata: *mut ::std::os::raw::c_void,
) -> ::std::os::raw::c_int,
>;
-#[doc = " @brief Add sample metadata to the statistics for a sample that matched on a signature.\n\n @param virname Name of the signature that matched.\n @param md5 Sample hash.\n @param size Sample size.\n @param sections PE section data, if applicable.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."]
-pub type clcb_stats_add_sample = ::std::option::Option<
- unsafe extern "C" fn(
- virname: *const ::std::os::raw::c_char,
- md5: *const ::std::os::raw::c_uchar,
- size: usize,
- sections: *mut stats_section_t,
- cbdata: *mut ::std::os::raw::c_void,
- ),
->;
-#[doc = " @brief Remove a specific sample from the statistics report.\n\n @param virname Name of the signature that matched.\n @param md5 Sample hash.\n @param size Sample size.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."]
-pub type clcb_stats_remove_sample = ::std::option::Option<
- unsafe extern "C" fn(
- virname: *const ::std::os::raw::c_char,
- md5: *const ::std::os::raw::c_uchar,
- size: usize,
- cbdata: *mut ::std::os::raw::c_void,
- ),
->;
-#[doc = " @brief Decrement the hit count listed in the statistics report for a specific sample.\n\n @param virname Name of the signature that matched.\n @param md5 Sample hash.\n @param size Sample size.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."]
-pub type clcb_stats_decrement_count = ::std::option::Option<
- unsafe extern "C" fn(
- virname: *const ::std::os::raw::c_char,
- md5: *const ::std::os::raw::c_uchar,
- size: usize,
- cbdata: *mut ::std::os::raw::c_void,
- ),
->;
-#[doc = " @brief Function to submit a statistics report.\n\n @param engine The initialized scanning engine.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."]
-pub type clcb_stats_submit = ::std::option::Option<
- unsafe extern "C" fn(engine: *mut cl_engine, cbdata: *mut ::std::os::raw::c_void),
->;
-#[doc = " @brief Function to flush/free the statistics report data.\n\n @param engine The initialized scanning engine.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."]
-pub type clcb_stats_flush = ::std::option::Option<
- unsafe extern "C" fn(engine: *mut cl_engine, cbdata: *mut ::std::os::raw::c_void),
->;
-#[doc = " @brief Function to get the number of samples listed in the statistics report.\n\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."]
-pub type clcb_stats_get_num =
- ::std::option::Option<unsafe extern "C" fn(cbdata: *mut ::std::os::raw::c_void) -> usize>;
-#[doc = " @brief Function to get the size of memory used to store the statistics report.\n\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."]
-pub type clcb_stats_get_size =
- ::std::option::Option<unsafe extern "C" fn(cbdata: *mut ::std::os::raw::c_void) -> usize>;
-#[doc = " @brief Function to get the machine's unique host ID.\n\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."]
-pub type clcb_stats_get_hostid = ::std::option::Option<
- unsafe extern "C" fn(cbdata: *mut ::std::os::raw::c_void) -> *mut ::std::os::raw::c_char,
->;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cl_cvd {
@@ -431,7 +372,6 @@ pub struct cli_dconf {
pub other: u32,
pub phishing: u32,
pub bytecode: u32,
- pub stats: u32,
pub pcre: u32,
}
pub type fmap_t = cl_fmap_t;
@@ -835,15 +775,6 @@ pub struct cl_engine {
pub maxhtmlnotags: u64,
pub maxscriptnormalize: u64,
pub maxziptypercg: u64,
- pub stats_data: *mut ::std::os::raw::c_void,
- pub cb_stats_add_sample: clcb_stats_add_sample,
- pub cb_stats_remove_sample: clcb_stats_remove_sample,
- pub cb_stats_decrement_count: clcb_stats_decrement_count,
- pub cb_stats_submit: clcb_stats_submit,
- pub cb_stats_flush: clcb_stats_flush,
- pub cb_stats_get_num: clcb_stats_get_num,
- pub cb_stats_get_size: clcb_stats_get_size,
- pub cb_stats_get_hostid: clcb_stats_get_hostid,
pub maxpartitions: u32,
pub maxiconspe: u32,
pub maxrechwp3: u32,
diff --git a/libfreshclam/libfreshclam.c b/libfreshclam/libfreshclam.c
index 51581f299..cba2bf5ae 100644
--- a/libfreshclam/libfreshclam.c
+++ b/libfreshclam/libfreshclam.c
@@ -494,8 +494,6 @@ fc_error_t fc_test_database_ex(const char *dbFilename, int bBytecodeEnabled, cha
goto done;
}
- cl_engine_set_clcb_stats_submit(engine, NULL);
-
dboptions = CL_DB_PHISHING | CL_DB_PHISHING_URLS | CL_DB_BYTECODE | CL_DB_PUA | CL_DB_ENHANCED;
if (g_bFipsLimits) {
dboptions |= CL_DB_FIPS_LIMITS;
diff --git a/sigtool/sigtool.c b/sigtool/sigtool.c
index f39c89674..c280b373e 100644
--- a/sigtool/sigtool.c
+++ b/sigtool/sigtool.c
@@ -243,10 +243,10 @@ static int hashpe(const char *filename, unsigned int class, cli_hash_type_t type
/* Send to PE-specific hasher */
switch (class) {
case 1:
- ret = cli_genhash_pe(&ctx, CL_GENHASH_PE_CLASS_SECTION, type, NULL);
+ ret = cli_genhash_pe(&ctx, CL_GENHASH_PE_CLASS_SECTION, type);
break;
case 2:
- ret = cli_genhash_pe(&ctx, CL_GENHASH_PE_CLASS_IMPTBL, type, NULL);
+ ret = cli_genhash_pe(&ctx, CL_GENHASH_PE_CLASS_IMPTBL, type);
break;
default:
mprintf(LOGG_ERROR, "hashpe: unknown classification(%u) for pe hash!\n", class);