更新libclamav库1.0.0版本

This commit is contained in:
2023-01-14 18:28:39 +08:00
parent b879ee0b2e
commit 45fe15f472
8531 changed files with 1222046 additions and 177272 deletions

102
Makefile
View File

@@ -1,18 +1,14 @@
CROSS_COMPILE ?= CROSS_COMPILE ?=
CC := $(CROSS_COMPILE)gcc CC := $(CROSS_COMPILE)gcc
AR := $(CROSS_COMPILE)ar
RANLIB := $(CROSS_COMPILE)ranlib
CMAKE := cmake
OBG = rhost
CFLAGS += -Os -g -Wall -DCRON_USE_LOCAL_TIME -DCRON_TEST_MALLOC
LIB += -lcurl -lip4tc clamscan/clamscan.o clamscan/manager.o -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 ./clamscan/shared/libshared.a -lssl -lcrypto -lz -lpthread
IPTC_CFLAGS += -DHAVE_CONFIG_H -I./libiptc -D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 -D_REENTRANT IPTC_CFLAGS += -DHAVE_CONFIG_H -I./libiptc -D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 -D_REENTRANT
IPTC_LIB += -lip4tc
OBG = rhost
CFLAGS += -Os -g -Wall -DCRON_USE_LOCAL_TIME -DCRON_TEST_MALLOC
CLAMSCAN_CFLAGS += -Wall -Os -DHAVE_CONFIG_H -I./clamscan -I./clamscan/shared -I./clamscan/libclamav -I./clamscan/libclamunrar_iface -I/usr/include/json-c -Wdate-time -D_FORTIFY_SOURCE=2 -fstack-protector-strong -Wall -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
SHARED_CFLAGS += -Wall -Os -DHAVE_CONFIG_H -I./clamscan -I./clamscan/shared -I./clamscan/libclamav -I./clamscan/libclamunrar_iface -I/usr/include/json-c -Wdate-time -D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wall -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
freshclam_CFLAGS += -g -O2 -Wall -DHAVE_CONFIG_H -I./clamscan -I./clamscan/shared -I./clamscan/libclamav -I./clamscan/libclamunrar_iface -I/usr/include/json-c -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
libfreshclam_CFLAGS += -g -Os -Wall -DHAVE_CONFIG_H -I./clamscan -I./clamscan/freshclam -I./clamscan/shared -I./clamscan/libclamav -I./clamscan/libclamunrar_iface -I/usr/include/json-c -Wdate-time -D_FORTIFY_SOURCE=2
freshclam_LIB += clamscan/freshclam/freshclam.o clamscan/freshclam/notify.o clamscan/freshclam/execute.o clamscan/freshclam/libfreshclam.o clamscan/freshclam/libfreshclam_internal.o clamscan/freshclam/dns.o ./clamscan/shared/libshared.a -lssl -lcrypto -lclamav -lresolv -lcurl -lz -ljson-c -lltdl -lpthread -lm
cJSON_CFLAGS += -std=c89 -c -fPIC -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion -fstack-protector cJSON_CFLAGS += -std=c89 -c -fPIC -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion -fstack-protector
cJSON_LIB += cJSON.o cJSON_LIB += cJSON.o
@@ -20,52 +16,78 @@ cJSON_LIB += cJSON.o
ip2region_CFLAGS += -Os -g -Wall -I/ip2region -c ip2region_CFLAGS += -Os -g -Wall -I/ip2region -c
ip2region_LIB += ip2region.o xdb_searcher.o ip2region_LIB += ip2region.o xdb_searcher.o
CLAMAV_CFLAGS += -DHAVE_CONFIG_H -I./clamav/libclamav -I./clamav/ -I./clamav/libclamunrar_iface -I./clamav/common -isystem ./clamav/ -isystem /usr/include/libxml2 -isystem /usr/include/json-c -fPIE -Wall -Wextra -Wformat-security -std=gnu90
CLAMAV_LIB += ./clamav/clamscan/clamscan.c.o ./clamav/clamscan/manager.c.o ./clamav/libcommon.a -Wl,-rpath,$${PWD}/clamav $${PWD}/clamav/libclamav.so.11.0.0 -lmspack ./clamav/libclamav_rust/x86_64-unknown-linux-gnu/debug/libclamav_rust.a -lgcc_s -lutil -lrt -lpthread -lm -ldl -lc -lbz2 -lpcre2-8 -lxml2 -ljson-c -lc -ldl -lm -lssl -lcrypto -lz -lcurl -lsystemd
FRESHCLAM_CFLAGS += -DHAVE_CONFIG_H -I./clamav/libfreshclam -I./clamav/common -I./clamav/libclamav -I./clamav/libclamunrar_iface -isystem ./clamav/ -isystem ./clamav/libclamav_rust -isystem /usr/include/libxml2 -isystem /usr/include/json-c -fPIE -Wall -Wextra -Wformat-security -std=gnu90
FRESHCLAM_LIB += ./clamav/freshclam/freshclam.c.o ./clamav/freshclam/execute.c.o ./clamav/freshclam/notify.c.o -Wl,-rpath,$${PWD}/clamav ${PWD}/clamav/libfreshclam.so.2.0.2 ./clamav/libcommon.a -Wl,-rpath,$${PWD}/clamav $${PWD}/clamav/libclamav.so.11.0.0 -lmspack ./clamav/libclamav_rust/x86_64-unknown-linux-gnu/debug/libclamav_rust.a -lgcc_s -lutil -lrt -lpthread -lm -ldl -lc -lbz2 -lpcre2-8 -lxml2 -ljson-c -lc -ldl -lm -lz -lsystemd -lcurl -lssl -lcrypto -lresolv
LIBCOMMON__CFLAGS += -DHAVE_CONFIG_H -I./clamav/common -I./clamav/libclamav -I./clamav/ -I./clamav/libclamunrar_iface -isystem ./clamav/ -isystem /usr/include/libxml2 -isystem /usr/include/json-c -fPIC -Wall -Wextra -Wformat-security
LIBCOMMON_LIB += ./clamav/common/cert_util.c.o ./clamav/common/actions.c.o ./clamav/common/clamdcom.c.o ./clamav/common/getopt.c.o ./clamav/common/hostid.c.o ./clamav/common/idmef_logging.c.o ./clamav/common/misc.c.o ./clamav/common/optparser.c.o ./clamav/common/output.c.o ./clamav/common/tar.c.o ./clamav/common/linux/cert_util_linux.c.o
all: conf.o rhost.o libiptc.o ccronexpr.o all: conf.o rhost.o libiptc.o ccronexpr.o
$(CC) $(ip2region_CFLAGS) ip2region/ip2region.c $(CC) $(ip2region_CFLAGS) ip2region/ip2region.c
$(CC) $(ip2region_CFLAGS) ip2region/xdb_searcher.c $(CC) $(ip2region_CFLAGS) ip2region/xdb_searcher.c
$(CC) $(cJSON_CFLAGS) cJSON/cJSON.c $(CC) $(cJSON_CFLAGS) cJSON/cJSON.c
$(CC) $(freshclam_CFLAGS) -c clamscan/freshclam/freshclam.c -fPIC -DPIC -o clamscan/freshclam/freshclam.o
$(CC) $(freshclam_CFLAGS) -c clamscan/freshclam/notify.c -fPIC -DPIC -o clamscan/freshclam/notify.o
$(CC) $(freshclam_CFLAGS) -c clamscan/freshclam/execute.c -fPIC -DPIC -o clamscan/freshclam/execute.o
$(CC) $(libfreshclam_CFLAGS) -c clamscan/freshclam/libfreshclam.c -fPIC -DPIC -o clamscan/freshclam/libfreshclam.o $(CC) $(LIBCOMMON__CFLAGS) -o ./clamav/common/cert_util.c.o -c ./clamav/common/cert_util.c
$(CC) $(libfreshclam_CFLAGS) -c clamscan/freshclam/libfreshclam_internal.c -fPIC -DPIC -o clamscan/freshclam/libfreshclam_internal.o $(CC) $(LIBCOMMON__CFLAGS) -o ./clamav/common/actions.c.o -c ./clamav/common/actions.c
$(CC) $(libfreshclam_CFLAGS) -c clamscan/freshclam/dns.c -fPIC -DPIC -o clamscan/freshclam/dns.o $(CC) $(LIBCOMMON__CFLAGS) -o ./clamav/common/clamdcom.c.o -c ./clamav/common/clamdcom.c
$(CC) $(LIBCOMMON__CFLAGS) -o ./clamav/common/getopt.c.o -c ./clamav/common/getopt.c
$(CC) $(LIBCOMMON__CFLAGS) -o ./clamav/common/hostid.c.o -c ./clamav/common/hostid.c
$(CC) $(LIBCOMMON__CFLAGS) -o ./clamav/common/idmef_logging.c.o -c ./clamav/common/idmef_logging.c
$(CC) $(LIBCOMMON__CFLAGS) -o ./clamav/common/misc.c.o -c ./clamav/common/misc.c
$(CC) $(LIBCOMMON__CFLAGS) -o ./clamav/common/optparser.c.o -c ./clamav/common/optparser.c
$(CC) $(LIBCOMMON__CFLAGS) -o ./clamav/common/output.c.o -c ./clamav/common/output.c
$(CC) $(LIBCOMMON__CFLAGS) -o ./clamav/common/tar.c.o -c ./clamav/common/tar.c
$(CC) $(LIBCOMMON__CFLAGS) -o ./clamav/common/linux/cert_util_linux.c.o -c ./clamav/common/linux/cert_util_linux.c
$(AR) qc ./clamav/libcommon.a $(LIBCOMMON_LIB)
$(RANLIB) ./clamav/libcommon.a
$(CC) $(SHARED_CFLAGS) -c ./clamscan/shared/actions.c -fPIC -DPIC -o ./clamscan/shared/actions.o $(CC) -DHAVE_CONFIG_H -Dfreshclam_EXPORTS -I./clamav/libfreshclam -I./clamav/common -I./clamav/libclamav -I./clamav/ -I./clamav/libclamunrar_iface -isystem clamav/libclamav_rust -isystem /usr/include/libxml2 -isystem /usr/include/json-c -fPIC -Wall -Wextra -Wformat-security -std=gnu90 -o clamav/libfreshclam/libfreshclam.c.o -c clamav/libfreshclam/libfreshclam.c
$(CC) $(SHARED_CFLAGS) -c ./clamscan/shared/cdiff.c -fPIC -DPIC -o ./clamscan/shared/cdiff.o $(CC) -DHAVE_CONFIG_H -Dfreshclam_EXPORTS -I./clamav/libfreshclam -I./clamav/common -I./clamav/libclamav -I./clamav/ -I./clamav/libclamunrar_iface -isystem clamav/libclamav_rust -isystem /usr/include/libxml2 -isystem /usr/include/json-c -fPIC -Wall -Wextra -Wformat-security -std=gnu90 -o clamav/libfreshclam/libfreshclam_internal.c.o -c clamav/libfreshclam/libfreshclam_internal.c
$(CC) $(SHARED_CFLAGS) -c ./clamscan/shared/cert_util.c -fPIC -DPIC -o ./clamscan/shared/cert_util.o $(CC) -DHAVE_CONFIG_H -Dfreshclam_EXPORTS -I./clamav/libfreshclam -I./clamav/common -I./clamav/libclamav -I./clamav/ -I./clamav/libclamunrar_iface -isystem clamav/libclamav_rust -isystem /usr/include/libxml2 -isystem /usr/include/json-c -fPIC -Wall -Wextra -Wformat-security -std=gnu90 -o clamav/libfreshclam/dns.c.o -c clamav/libfreshclam/dns.c
$(CC) $(SHARED_CFLAGS) -c ./clamscan/shared/clamdcom.c -fPIC -DPIC -o ./clamscan/shared/clamdcom.o $(CC) -fPIC -shared -Wl,-soname,libfreshclam.so.2 -o clamav/libfreshclam.so.2.0.2 clamav/libfreshclam/libfreshclam.c.o clamav/libfreshclam/libfreshclam_internal.c.o clamav/libfreshclam/dns.c.o ./clamav/libcommon.a -lcurl -lssl -lcrypto -lresolv ${PWD}/clamav/libclamav.so.11.0.0 -lssl -lcrypto -lmspack ${PWD}/clamav/libclamav_rust/x86_64-unknown-linux-gnu/debug/libclamav_rust.a -lgcc_s -lutil -lrt -lpthread -lm -ldl -lc -lbz2 -lpcre2-8 -lxml2 -ljson-c -lc -ldl -lm -lz -lsystemd
$(CC) $(SHARED_CFLAGS) -c ./clamscan/shared/getopt.c -fPIC -DPIC -o ./clamscan/shared/getopt.o
$(CC) $(SHARED_CFLAGS) -c ./clamscan/shared/hostid.c -fPIC -DPIC -o ./clamscan/shared/hostid.o
$(CC) $(SHARED_CFLAGS) -c ./clamscan/shared/idmef_logging.c -fPIC -DPIC -o ./clamscan/shared/idmef_logging.o
$(CC) $(SHARED_CFLAGS) -c ./clamscan/shared/misc.c -fPIC -DPIC -o ./clamscan/shared/misc.o
$(CC) $(SHARED_CFLAGS) -c ./clamscan/shared/optparser.c -fPIC -DPIC -o ./clamscan/shared/optparser.o
$(CC) $(SHARED_CFLAGS) -c ./clamscan/shared/output.c -fPIC -DPIC -o ./clamscan/shared/output.o
$(CC) $(SHARED_CFLAGS) -c ./clamscan/shared/tar.c -fPIC -DPIC -o ./clamscan/shared/tar.o
$(CC) $(SHARED_CFLAGS) -c ./clamscan/shared/linux/cert_util_linux.c -fPIC -DPIC -o ./clamscan/shared/linux/cert_util_linux.o
ar cr ./clamscan/shared/libshared.a ./clamscan/shared/actions.o ./clamscan/shared/cdiff.o ./clamscan/shared/cert_util.o ./clamscan/shared/clamdcom.o ./clamscan/shared/getopt.o ./clamscan/shared/hostid.o ./clamscan/shared/idmef_logging.o ./clamscan/shared/misc.o ./clamscan/shared/optparser.o ./clamscan/shared/output.o ./clamscan/shared/tar.o ./clamscan/shared/linux/cert_util_linux.o
$(CC) $(CLAMSCAN_CFLAGS) -c clamscan/clamscan.c -o clamscan/clamscan.o $(CC) $(CLAMAV_CFLAGS) -o ./clamav/clamscan/clamscan.c.o -c ./clamav/clamscan/clamscan.c
$(CC) $(CLAMSCAN_CFLAGS) -c clamscan/manager.c -o clamscan/manager.o $(CC) $(CLAMAV_CFLAGS) -o ./clamav/clamscan/manager.c.o -c ./clamav/clamscan/manager.c
$(CC) $(CFLAGS) $^ -o $(OBG) $(cJSON_LIB) $(ip2region_LIB) $(LIB) $(freshclam_LIB) $(CC) $(FRESHCLAM_CFLAGS) -o ./clamav/freshclam/freshclam.c.o -c ./clamav/freshclam/freshclam.c
$(CC) $(FRESHCLAM_CFLAGS) -o ./clamav/freshclam/execute.c.o -c ./clamav/freshclam/execute.c
$(CC) $(FRESHCLAM_CFLAGS) -o ./clamav/freshclam/notify.c.o -c ./clamav/freshclam/notify.c
$(CC) $(CFLAGS) $^ -o $(OBG) $(cJSON_LIB) $(ip2region_LIB) $(CLAMAV_LIB) $(IPTC_LIB) $(FRESHCLAM_LIB)
chmod +x $(OBG) chmod +x $(OBG)
libclamav_rust:
cd clamav/libclamav_rust && $(CMAKE) -E env CARGO_CMD=build CARGO_TARGET_DIR=./ MAINTAINER_MODE=OFF RUSTFLAGS="" \
cargo build --target x86_64-unknown-linux-gnu --target-dir ./
cd ..
libclamav:
cd clamav/ && bash -x build-libclamav.sh
rm -rf ${PWD}/clamav/libclamav.so.11 && ln -s ${PWD}/clamav/libclamav.so.11.0.0 ${PWD}/clamav/libclamav.so.11
rm -rf ${PWD}/clamav/libfreshclam.so.2 && ln -s ${PWD}/clamav/libfreshclam.so.2.0.2 ${PWD}/clamav/libfreshclam.so.2
cd ..
test:
ls `echo $${PWD}`
static: conf.o rhost.o libiptc.o static: conf.o rhost.o libiptc.o
$(CC) $(IPTC_CFLAGS) -c libiptc/libip4tc.c -o libiptc/libip4tc.o $(CC) $(IPTC_CFLAGS) -c libiptc/libip4tc.c -o libiptc/libip4tc.o
ar crs libiptc/libip4tc.a libiptc/libip4tc.o ar crs libiptc/libip4tc.a libiptc/libip4tc.o
#$(CC) $(CFLAGS) $^ libiptc/libip4tc.o -o $(OBG) `/data/curl/bin/curl-config --cflags --static-libs` `pkg-config --libs --static libbrotlidec` #$(CC) $(CFLAGS) $^ libiptc/libip4tc.o -o $(OBG) `/data/curl/bin/curl-config --cflags --static-libs` `pkg-config --libs --static libbrotlidec`
.PHONY: clean
clean: clean:
rm -rf *.o rm -rf *.o
rm -rf libiptc/*.o libiptc/*.a rm -rf $(OBG) $(cJSON_LIB) $(ip2region_LIB)
rm -rf clamscan/shared/*.o clamscan/shared/libshared.a clamscan/*.o rm -rf `find ./clamav/ -name *.o`
rm -rf clamscan/freshclam/*.o rm -rf ./clamav/*.a
rm -rf `find clamscan/libclamav/ -name *.lo` rm -rf ./clamav/libclamav.so.11.0.0
rm -rf `find clamscan/libclamav/ -name *.o` rm -rf ./clamav/libfreshclam.so.2.0.2
rm -rf cJSON/*.o rm -rf ${PWD}/clamav/libclamav.so.11
rm -rf ip2region/*.o rm -rf ${PWD}/clamav/libfreshclam.so.2
rm -rf $(OBG)

View File

@@ -13,7 +13,7 @@
Debian Debian
apt -y install libclamav-dev libip4tc-dev libcurl4-openssl-dev #(或者libcurl4-gnutls-dev) apt -y install libclamav-dev libip4tc-dev libcurl4-openssl-dev #(或者libcurl4-gnutls-dev)
apt -y install libsystemd-dev libjson-c-dev libpcre2-dev clamav-freshclam apt -y install libsystemd-dev libjson-c-dev libpcre2-dev clamav-freshclam
apt -y install libltdl-dev apt -y install libltdl-dev libmspack-dev
freshclam # 更新病毒库(必要) freshclam # 更新病毒库(必要)
@@ -29,7 +29,7 @@ Debian
Centos 7 Centos 7
yum install clamav clamav-update clamav-lib clamav-devel json-c-devel pcre2-devel yum install clamav clamav-update clamav-lib clamav-devel json-c-devel pcre2-devel
yum install iptables-devel libcurl-devel yum install iptables-devel libcurl-devel
yum install systemd-devel libtool-ltdl-devel yum install systemd-devel libtool-ltdl-devel libmspack-devel
yum -y install centos-release-scl yum -y install centos-release-scl
yum -y install devtoolset-11-gcc yum -y install devtoolset-11-gcc
@@ -49,7 +49,10 @@ Centos 7
cd /root cd /root
git clone https://git.aixiao.me/aixiao/denyhosts git clone https://git.aixiao.me/aixiao/denyhosts
cd denyhosts cd denyhosts
make clean; make make clean
make libclamav_rust
make libclamav
make all
bash build.sh bash build.sh

319
clamav/build-libclamav.sh Normal file

File diff suppressed because one or more lines are too long

617
clamav/clamav-config.h Normal file
View File

@@ -0,0 +1,617 @@
/* clamav-config.h.cmake.in. Autoconf compatibility layer for CMake. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* mmap flag for anonymous maps */
#define ANONYMOUS_MAP MAP_ANONYMOUS
/* bind 8 compatibility mode, required on some systems to get T_TXT, etc from nameser_compat.h */
/* #undef BIND_8_COMPAT */
/* name of the clamav group */
#define CLAMAVGROUP "clamav"
/* name of the clamav user */
#define CLAMAVUSER "clamav"
/* enable debugging */
/* #undef CL_DEBUG */
/* enable experimental code */
/* #undef CL_EXPERIMENTAL */
/* thread safe */
#define CL_THREAD_SAFE 1
/* curses header location */
#define CURSES_INCLUDE <ncurses.h>
/* os is aix */
/* #undef C_AIX */
/* os is beos */
/* #undef C_BEOS */
/* Increase thread stack size. */
/* #undef C_BIGSTACK */
/* os is bsd flavor */
/* #undef C_BSD */
/* os is darwin */
/* #undef C_DARWIN */
/* target is gnu-hurd */
/* #undef C_GNU_HURD */
/* os is hpux */
/* #undef C_HPUX */
/* os is interix */
/* #undef C_INTERIX */
/* os is irix */
/* #undef C_IRIX */
/* target is kfreebsd-gnu */
/* #undef C_KFREEBSD_GNU */
/* target is linux */
#define C_LINUX 1
/* os is OS/2 */
/* #undef C_OS2 */
/* os is osf/tru64 */
/* #undef C_OSF */
/* os is QNX 6.x.x */
/* #undef C_QNX6 */
/* os is solaris */
/* #undef C_SOLARIS */
#ifndef _WIN32
/* Path to virus database directory. */
#define DATADIR "/var/lib/clamav"
/* where to look for the config file */
#define CONFDIR "/etc/clamav"
#endif
/* Have sys/fanotify.h */
#define HAVE_SYS_FANOTIFY_H 1
/* whether _XOPEN_SOURCE needs to be defined for fd passing to work */
/* #undef FDPASS_NEED_XOPEN */
/* file i/o buffer size */
#define FILEBUFF 8192
/* scan buffer size */
#define SCANBUFF 131072
/* enable workaround for broken DNS servers */
/* #undef FRESHCLAM_DNS_FIX */
/* use "Cache-Control: no-cache" in freshclam */
/* #undef FRESHCLAM_NO_CACHE */
/* attrib aligned */
#define HAVE_ATTRIB_ALIGNED 1
/* attrib packed */
#define HAVE_ATTRIB_PACKED 1
/* have bzip2 */
#define HAVE_BZLIB_H 1
/* Define to 1 if you have the `ctime_r' function. */
/* #undef HAVE_CTIME_R */
/* ctime_r takes 2 arguments */
/* #undef HAVE_CTIME_R_2 */
/* ctime_r takes 3 arguments */
/* #undef HAVE_CTIME_R_3 */
/* Define to 1 if you have the declaration of `cygwin_conv_path', and to 0 if
you don't. */
/* #undef HAVE_DECL_CYGWIN_CONV_PATH */
/* Define to 1 if you have a deprecated version of the 'libjson' library
(-ljson). */
/* #undef HAVE_DEPRECATED_JSON */
/* Define to 1 if you have the <dirent.h> header file. */
#define HAVE_DIRENT_H 1
/* Define if you have the GNU dld library. */
/* #undef HAVE_DLD */
/* Define to 1 if you have the <dld.h> header file. */
/* #undef HAVE_DLD_H */
/* Define to 1 if you have the `dlerror' function. */
/* #undef HAVE_DLERROR */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <dl.h> header file. */
/* #undef HAVE_DL_H */
/* Define if you have the _dyld_func_lookup function. */
/* #undef HAVE_DYLD */
/* Define to 1 if you have the `enable_extended_FILE_stdio' function. */
/* #undef HAVE_ENABLE_EXTENDED_FILE_STDIO */
/* Define to 1 if the system has the type `error_t'. */
/* #undef HAVE_ERROR_T */
/* have working file descriptor passing support */
#define HAVE_FD_PASSING 1
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
#define HAVE_FSEEKO 1
/* have getaddrinfo() */
#define HAVE_GETADDRINFO 1
/* Define to 1 if you have the `getnameinfo' function. */
/* #undef HAVE_GETNAMEINFO */
/* Define to 1 if getpagesize() is available */
#define HAVE_GETPAGESIZE 1
/* Define to 1 if you have the <grp.h> header file. */
#define HAVE_GRP_H 1
/* Define if you have the iconv() function and it works. */
#define HAVE_ICONV 1
/* Define to 1 if you have the `initgroups' function. */
#define HAVE_INITGROUPS 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <inttypes.h> header file (for libjson-c). */
#define JSON_C_HAVE_INTTYPES_H 1
/* Define to 1 if you have the 'libjson' library (-ljson). */
#define HAVE_JSON 1
/* Define to '1' if you have the check.h library */
/* #undef HAVE_LIBCHECK */
/* Define to '1' if you have the ncurses.h library */
#define HAVE_LIBNCURSES 1
/* Define to '1' if you have the curses.h library */
/* #undef HAVE_LIBPDCURSES */
/* Define to 1 if you have the `ssl' library (-lssl). */
#define HAVE_LIBSSL 1
/* Define to 1 if you have the 'libxml2' library (-lxml2). */
#define HAVE_LIBXML2 1
/* Define to 1 if you have the `z' library (-lz). */
#define HAVE_LIBZ 1
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if you have the `madvise' function. */
/* #undef HAVE_MADVISE */
/* Define to 1 if you have the `mallinfo' function. */
/* #undef HAVE_MALLINFO */
/* Define to 1 if you have the <malloc.h> header file. */
#define HAVE_MALLOC_H 1
/* Define to 1 if you have the `mkstemp' function. */
/* #undef HAVE_MKSTEMP */
/* Define to 1 if you have a working `mmap' system call that supports
MAP_PRIVATE. */
#define HAVE_MMAP 1
/* Define to 1 if you have a pcre library (-lpcre). */
#define HAVE_PCRE 1
/* Define to 1 if you using the pcre2 library. */
#define USING_PCRE2 1
/* Define to 1 if you have the `poll' function. */
#define HAVE_POLL 1
/* Define to 1 if you have the <poll.h> header file. */
#define HAVE_POLL_H 1
/* "pragma pack" */
/* #undef HAVE_PRAGMA_PACK */
/* "pragma pack hppa/hp-ux style" */
/* #undef HAVE_PRAGMA_PACK_HPPA */
/* Define if libtool can extract symbol lists from object files. */
/* #undef HAVE_PRELOADED_SYMBOLS */
/* Define to 1 if you have the <pthread.h> header file */
#define HAVE_PTHREAD_H 1
/* Define to 1 if you have the <pwd.h> header file. */
#define HAVE_PWD_H 1
/* Define to 1 if you have the `readdir' function. */
/* #undef HAVE_READDIR */
/* Define to 1 if you have the `recvmsg' function. */
#define HAVE_RECVMSG 1
/* have resolv.h */
#define HAVE_RESOLV_H 1
/* Define signed right shift implementation */
#define HAVE_SAR 1
/* Define to 1 if you have the `sched_yield' function. */
/* #undef HAVE_SCHED_YIELD */
/* Define to 1 if you have the `sendmsg' function. */
#define HAVE_SENDMSG 1
/* Define to 1 if you have the `setgroups' function. */
/* #undef HAVE_SETGROUPS */
/* Define to 1 if you have the `setsid' function. */
#define HAVE_SETSID 1
/* Define to 1 if you have the `snprintf' function. */
#define HAVE_SNPRINTF 1
/* enable stat64 */
/* #undef HAVE_STAT64 */
/* Define to 1 if you have the <stdbool.h> header file. */
#define HAVE_STDBOOL_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strcasestr' function. */
/* #undef HAVE_STRCASESTR */
/* Define to 1 if you have the `strerror_r' function. */
#define HAVE_STRERROR_R 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strlcat' function. */
/* #undef HAVE_STRLCAT */
/* Define to 1 if you have the `strlcpy' function. */
/* #undef HAVE_STRLCPY */
/* Define to 1 if you have the `strndup' function. */
#define HAVE_STRNDUP 1
/* using internal strn functions */
/* #undef HAVE_STRNI */
/* Define to 1 if you have the `strnlen' function. */
#define HAVE_STRNLEN 1
/* Define to 1 if you have the `strnstr' function. */
/* #undef HAVE_STRNSTR */
/* Define to 1 if sysconf(_SC_PAGESIZE) is available */
#define HAVE_SYSCONF_SC_PAGESIZE 1
/* Define to 1 if you have the `sysctlbyname' function. */
/* #undef HAVE_SYSCTLBYNAME */
/* systemd is supported */
#define HAVE_SYSTEMD 1
/* Use private fts() implementation which is LFS safe */
#define HAVE_SYSTEM_LFS_FTS 1
/* Define to 1 if you have the <sys/cdefs.h> header file. */
#define HAVE_SYS_CDEFS_H 1
/* Define to 1 if you have the <sys/dl.h> header file. */
/* #undef HAVE_SYS_DL_H */
/* Define to 1 if you have the <sys/filio.h> header file. */
/* #undef HAVE_SYS_FILIO_H */
/* Define to 1 if you have the <sys/inttypes.h> header file. */
/* #undef HAVE_SYS_INTTYPES_H */
/* Define to 1 if you have the <sys/int_types.h> header file. */
/* #undef HAVE_SYS_INT_TYPES_H */
/* Define to 1 if you have the <sys/mman.h> header file. */
#define HAVE_SYS_MMAN_H 1
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/queue.h> header file. */
#define HAVE_SYS_QUEUE_H 1
/* "have <sys/select.h>" */
#define HAVE_SYS_SELECT_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/times.h> header file. */
#define HAVE_SYS_TIMES_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/uio.h> header file. */
#define HAVE_SYS_UIO_H 1
/* Define to 1 if you have the <termios.h> header file. */
#define HAVE_TERMIOS_H 1
/* Define to 1 if you have the `timegm' function. */
#define HAVE_TIMEGM 1
/* Define this if uname(2) is POSIX */
#define HAVE_UNAME_SYSCALL 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the `vsnprintf' function. */
#define HAVE_VSNPRINTF 1
/* This value is set to 1 to indicate that the system argz facility works */
/* #undef HAVE_WORKING_ARGZ */
/* yara sources are compiled in */
#define HAVE_YARA 1
/* Define to 1 if you have the <zlib.h> header file. */
#define HAVE_ZLIB_H 1
/* For internal use only - DO NOT DEFINE */
/* #undef HAVE__INTERNAL__SHA_COLLECT */
/* Define as const if the declaration of iconv() needs const. */
/* #undef ICONV_CONST */
/* Define if UNRAR is linked instead of loaded. */
/* #undef UNRAR_LINKED */
/* Define if UNRAR is linked instead of loaded. */
/* #undef HAVE_SYSTEM_TOMSFASTMATH */
/* "Full clamav library version number" */
#define LIBCLAMAV_FULLVER "11.0.0"
/* "Major clamav library version number" */
#define LIBCLAMAV_MAJORVER 11
/* "Full freshclam library version number" */
#define LIBFRESHCLAM_FULLVER "2.0.2"
/* "Major freshclam library version number" */
#define LIBFRESHCLAM_MAJORVER 2
/* The archive extension */
#define LT_LIBEXT ".a"
/* The archive prefix */
#define LT_LIBPREFIX "lib"
/* Define to the extension used for runtime loadable modules, say, ".so" or ".dylib". */
#define LT_MODULE_EXT ".so"
/* Define to the name of the environment variable that determines the run-time
module search path. */
#ifdef _WIN32
#define SEARCH_LIBDIR "/usr"
#else
#define SEARCH_LIBDIR "/usr/lib/x86_64-linux-gnu"
#endif
/* Define to the shared library suffix, say, ".dylib". */
#define LT_SHARED_EXT ".so"
/* disable assertions */
/* #undef NDEBUG */
/* Define if dlsym() requires a leading underscore in symbol names. */
/* #undef NEED_USCORE */
/* bzip funtions do not have bz2 prefix */
/* #undef NOBZ2PREFIX */
/* "no fd_set" */
/* #undef NO_FD_SET */
/* Name of package */
#define PACKAGE "ClamAV"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "https://github.com/Cisco-Talos/clamav/issues"
/* Define to the full name of this package. */
#define PACKAGE_NAME "ClamAV"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "ClamAV 1.0.0"
/* Define to the one symbol short name of this package. */
/* #undef PACKAGE_TARNAME */
/* Define to the home page for this package. */
#define PACKAGE_URL "https://www.clamav.net/"
/* Define to the version of this package. */
#define PACKAGE_VERSION "1.0.0"
/* Libprelude support enabled */
/* #undef PRELUDE */
/* Define whether application use libtool >= 2.0 */
/* #undef PRELUDE_APPLICATION_USE_LIBTOOL2 */
/* Define to if the `setpgrp' function takes no argument. */
/* #undef SETPGRP_VOID */
/* The number of bytes in type int */
#define SIZEOF_INT 4
/* The number of bytes in type long */
#define SIZEOF_LONG 8
/* The number of bytes in type long long */
#define SIZEOF_LONG_LONG 8
/* The number of bytes in type short */
#define SIZEOF_SHORT 2
/* The number of bytes in type void * */
#define SIZEOF_VOID_P 8
/* Define to if you have the ANSI C header files. */
/* #undef STDC_HEADERS */
/* Support for IPv6 */
/* #undef SUPPORT_IPv6 */
/* enable memory pools */
#define USE_MPOOL 1
/* use syslog */
#define USE_SYSLOG 1
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
/* #undef _ALL_SOURCE */
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
/* #undef _POSIX_PTHREAD_SEMANTICS */
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
/* #undef _TANDEM_SOURCE */
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
/* #undef __EXTENSIONS__ */
#endif
/* LLVM version (if found) */
/* #undef LLVM_VERSION */
/* Version number of package */
#define VERSION "1.0.0"
/* Version suffix for package */
#define VERSION_SUFFIX ""
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* #undef WORDS_BIGENDIAN */
# endif
#endif
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
`char[]'. */
/* #undef YYTEXT_POINTER */
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
/* #undef _LARGEFILE_SOURCE */
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */
/* Define to 1 if on MINIX. */
/* #undef _MINIX */
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
/* #undef _POSIX_1_SOURCE */
/* POSIX compatibility */
/* #undef _POSIX_PII_SOCKET */
/* Define to 1 if you need to in order for `stat' and other things to work. */
/* #undef _POSIX_SOURCE */
/* thread safe */
#define _REENTRANT 1
/* Define so that glibc/gnulib argp.h does not typedef error_t. */
/* #undef __error_t_defined */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#define inline inline
#endif
/* Define to `long int' if <sys/types.h> does not define. */
/* #undef off_t */
/* Define to `int' if <sys/types.h> does not define. */
/* #undef ssize_t */
/* Define to the equivalent of the C99 'restrict' keyword, or to
nothing if this is not supported. Do not define if restrict is
supported directly. */
#define restrict __restrict
/* Work around a bug in Sun C++: it does not support _Restrict or
__restrict__, even though the corresponding Sun C compiler ends up with
"#define restrict _Restrict" or "#define restrict __restrict__" in the
previous line. Perhaps some future version of Sun C++ will work with
restrict; if so, hopefully it defines __RESTRICT like Sun C does. */
#if defined __SUNPRO_CC && !defined __RESTRICT
# define _Restrict
# define __restrict__
#endif
/* Define to "int" if <sys/socket.h> does not define. */
/* #undef socklen_t */
#include "platform.h"

84
clamav/clamav-types.h Normal file
View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2013-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2007-2013 Sourcefire, Inc.
*
* Authors: Tomasz Kojm, Micah Snyder
*
* WARNING: This file was generated by CMake. Do not edit!
*
* 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 __CLAMAV_TYPES_H
#define __CLAMAV_TYPES_H
#include <inttypes.h>
/* Ensure we have print format types */
/* PRIu64 should be in <inttypes.h> */
#ifndef _SF64_PREFIX
#define _SF64_PREFIX "l"
#endif
#ifndef PRIu64
#define PRIu64 _SF64_PREFIX "u"
#endif
#ifndef PRIx64
#define PRIx64 _SF64_PREFIX "i"
#endif
#ifndef PRIi64
#define PRIi64 _SF64_PREFIX "x"
#endif
#ifndef STDu64
#define STDu64 "%" PRIu64
#define STDi64 "%" PRIi64
#define STDx64 "%" PRIx64
#endif
/* PRIu32 should also be in <inttypes.h> */
#ifndef PRIu32
#ifndef _SF32_PREFIX
#define _SF32_PREFIX ""
#endif
#define PRIu32 _SF32_PREFIX "u"
#define PRIi32 _SF32_PREFIX "i"
#define PRIx32 _SF32_PREFIX "x"
#endif
#ifndef STDu32
#define STDu32 "%" PRIu32
#define STDi32 "%" PRIi32
#define STDx32 "%" PRIx32
#endif
#ifndef INT32_MAX
#define INT32_MAX 2147483647
#endif
#endif

68
clamav/clamav-version.h Normal file
View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2019-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*
* Authors: Micah Snyder
*
* WARNING: This file was generated by CMake. Do not edit!
*
* 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 CLAMAV_VER_H
#define CLAMAV_VER_H
/**
* @macro
* Version number of the clamav package release
*/
#define CLAMAV_VERSION "1.0.0"
/**
* @macro
* Numerical representation of the version number of the clamav package
* release. This is a 24 bit number with 8 bits for major number, 8 bits
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
*/
#define CLAMAV_VERSION_NUM 0x010000
/**
* @macro
* Version number of the clamav library release
*/
#define LIBCLAMAV_VERSION "11.0.0"
/**
* @macro
* Numerical representation of the version number of the libclamav library
* release. This is a 24 bit number with 8 bits for major number, 8 bits
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
*/
#define LIBCLAMAV_VERSION_NUM 0x0b0000
/**
* @macro
* Version number of the clamav library release
*/
#define LIBFRESHCLAM_VERSION "2.0.2"
/**
* @macro
* Numerical representation of the version number of the libfreshclam library
* release. This is a 24 bit number with 8 bits for major number, 8 bits
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
*/
#define LIBFRESHCLAM_VERSION_NUM 0x020200
#endif /* CLAMAV_VER_H */

208
clamav/clamav_rust.h Normal file
View File

@@ -0,0 +1,208 @@
/* Copyright (C) 2021-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved. */
#ifndef __CLAMAV_RUST_H
#define __CLAMAV_RUST_H
/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "clamav.h"
#include "matcher-ac.h"
typedef struct cli_matcher cli_matcher; typedef struct cli_ctx_tag cli_ctx;
typedef enum IndicatorType {
/**
* For hash-based indicators.
*/
IndicatorType_Strong,
/**
* For potentially unwanted applications/programs that are not malicious but may be used maliciously.
*/
IndicatorType_PotentiallyUnwanted,
/**
* Weak indicators that together with other indicators can be used to form a stronger indicator.
* This type of indicator should NEVER alert the user on its own.
*/
IndicatorType_Weak,
} IndicatorType;
/**
* A generic container for any error that implements `Into<std::error::Error>`
*/
typedef struct FFIError FFIError;
bool script2cdiff(const char *script, const char *builder, const char *server);
/**
* This function is only meant to be called from sigtool.c
*/
int32_t cdiff_apply(int32_t fd, uint16_t mode);
/**
* Initialize a match vector
*/
evidence_t evidence_new(void);
/**
* Free the evidence
*/
void evidence_free(evidence_t evidence);
/**
* C interface for Evidence::render_verdict().
* Handles all the unsafe ffi stuff.
*
* Render a verdict based on the evidence, depending on the severity of the
* indicators found and the scan configuration.
*
* The individual alerting-indicators would have already been printed at this point.
*
* # Safety
*
* No parameters may be NULL
*/
bool evidence_render_verdict(evidence_t evidence);
/**
* C interface to get a string name for one of the alerts.
* Will first check for one from the strong indicators, then pua.
*
* # Safety
*
* Returns a string that is either static, or allocated when reading the database.
* So the lifetime of the string is good at least until you reload or unload the databases.
*
* No parameters may be NULL
*/
const char *evidence_get_last_alert(evidence_t evidence);
/**
* C interface to get a string name for one of the alerts.
* Will first check for one from the strong indicators, then pua.
*
* # Safety
*
* Returns a string that is either static, or allocated when reading the database.
* So the lifetime of the string is good at least until you reload or unload the databases.
*
* No parameters may be NULL
*/
const char *evidence_get_indicator(evidence_t evidence,
enum IndicatorType indicator_type,
uintptr_t index);
/**
* C interface to check number of alerting indicators in evidence.
*
* # Safety
*
* No parameters may be NULL
*/
uintptr_t evidence_num_alerts(evidence_t evidence);
/**
* C interface to check number of indicators in evidence.
* Handles all the unsafe ffi stuff.
*
* # Safety
*
* No parameters may be NULL
*/
uintptr_t evidence_num_indicators_type(evidence_t evidence, enum IndicatorType indicator_type);
/**
* C interface for Evidence::add_indicator().
* Handles all the unsafe ffi stuff.
*
* Add an indicator to the evidence.
*
* # Safety
*
* `hexsig` and `err` must not be NULL
*/
bool evidence_add_indicator(evidence_t evidence,
const char *name,
enum IndicatorType indicator_type,
struct FFIError **err);
/**
* Compute (and cache) a formatted error string from the provided [`FFIError`] pointer.
*
* # Safety
*
* `err` must not be NULL
*/
const char *ffierror_fmt(struct FFIError *err);
/**
* Free a [`FFIError`] structure
*
* # Safety
*
* `err` must not be NULL
*/
void ffierror_free(struct FFIError *err);
/**
* Initialize the hashmap
*/
fuzzyhashmap_t fuzzy_hashmap_new(void);
/**
* Free the hashmap
*/
void fuzzy_hash_free_hashmap(fuzzyhashmap_t fuzzy_hashmap);
/**
* C interface for FuzzyHashMap::check().
* Handles all the unsafe ffi stuff.
*
* # Safety
*
* No parameters may be NULL
*/
bool fuzzy_hash_check(fuzzyhashmap_t fuzzy_hashmap,
cli_ac_data *mdata,
image_fuzzy_hash_t image_fuzzy_hash);
/**
* C interface for FuzzyHashMap::load_subsignature().
* Handles all the unsafe ffi stuff.
*
* # Safety
*
* `hexsig` and `err` must not be NULL
*/
bool fuzzy_hash_load_subsignature(fuzzyhashmap_t fuzzy_hashmap,
const char *hexsig,
uint32_t lsig_id,
uint32_t subsig_id,
struct FFIError **err);
/**
* C interface for fuzzy_hash_calculate_image().
* Handles all the unsafe ffi stuff.
*
* # Safety
*
* `file_bytes` and `hash_out` must not be NULL
*/
bool fuzzy_hash_calculate_image(const uint8_t *file_bytes,
uintptr_t file_size,
uint8_t *hash_out,
uintptr_t hash_out_len,
struct FFIError **err);
bool clrs_log_init(void);
/**
* API exported for C code to log to standard error using Rust.
* This would be be an alternative to fputs, and reliably prints
* non-ASCII UTF8 characters on Windows, where fputs does not.
*/
void clrs_eprint(const char *c_buf);
#endif /* __CLAMAV_RUST_H */

View File

@@ -0,0 +1,48 @@
# Copyright (C) 2020-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
if(WIN32)
add_definitions(-DWIN32_LEAN_AND_MEAN)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
# Windows compatibility headers
include_directories(${CMAKE_SOURCE_DIR}/win32/compat)
endif()
# The clamscan executable.
add_executable( clamscan )
target_sources( clamscan
PRIVATE
clamscan.c
manager.c
manager.h
global.h )
if(WIN32)
target_sources( clamscan
PRIVATE
${CMAKE_SOURCE_DIR}/win32/res/clamscan.rc
${CMAKE_SOURCE_DIR}/win32/res/clam.manifest )
endif()
target_include_directories( clamscan
PRIVATE ${CMAKE_BINARY_DIR} # For clamav-config.h
)
set_target_properties( clamscan PROPERTIES COMPILE_FLAGS "${WARNCFLAGS}" )
if (APPLE AND CLAMAV_SIGN_FILE)
set_target_properties( clamscan PROPERTIES
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ${CODE_SIGN_IDENTITY}
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM ${DEVELOPMENT_TEAM_ID}
)
endif()
target_link_libraries( clamscan
PRIVATE
ClamAV::libclamav
ClamAV::common )
if(WIN32)
install(TARGETS clamscan DESTINATION . COMPONENT programs)
install(FILES $<TARGET_PDB_FILE:clamscan> DESTINATION . OPTIONAL COMPONENT programs)
else()
install(TARGETS clamscan DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT programs)
endif()

21
clamav/clamscan/Doxyfile Normal file
View File

@@ -0,0 +1,21 @@
PROJECT_NAME = ClamAV - Clamscan
OUTPUT_DIRECTORY = ../docs/clamscan
WARNINGS = YES
FILE_PATTERNS = *.c *.h
PERL_PATH = /usr/bin/perl
SEARCHENGINE = YES
GENERATE_LATEX=NO
OPTIMIZE_OUTPUT_FOR_C=YES
HAVE_DOT=YES
CALL_GRAPH=YES
CALLER_GRAPH=YES
JAVADOC_AUTOBRIEF=YES
GENERATE_MAN=NO
EXAMPLE_PATH=examples
DOT_CLEANUP=NO
MAX_DOT_GRAPH_DEPTH=3
EXTRACT_ALL=YES
INPUT = .

346
clamav/clamscan/clamscan.c Normal file
View File

@@ -0,0 +1,346 @@
/*
* Copyright (C) 2013-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2007-2013 Sourcefire, Inc.
*
* Authors: Tomasz Kojm
*
* 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>
#include <signal.h>
#include <locale.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifndef _WIN32
#include <sys/time.h>
#endif
#include <time.h>
#ifdef C_LINUX
#include <sys/resource.h>
#endif
// libclamav
#include "clamav.h"
#include "others.h"
#include "str.h"
// common
#include "misc.h"
#include "output.h"
#include "actions.h"
#include "optparser.h"
#include "global.h"
#include "manager.h"
void help(void);
struct s_info info;
short recursion = 0, bell = 0;
short printinfected = 0, printclean = 1;
int _clamscan(int argc, char **argv)
{
int ds, dms, ret;
double mb, rmb;
struct timeval t1, t2;
time_t date_start, date_end;
char buffer[26];
#ifndef _WIN32
sigset_t sigset;
#endif
struct optstruct *opts;
const struct optstruct *opt;
if (check_flevel())
exit(2);
#if !defined(_WIN32)
if (!setlocale(LC_CTYPE, "")) {
mprintf(LOGG_WARNING, "Failed to set locale\n");
}
#if !defined(C_BEOS)
sigemptyset(&sigset);
sigaddset(&sigset, SIGXFSZ);
sigprocmask(SIG_SETMASK, &sigset, NULL);
#endif /* !C_BEOS */
#endif /* !_WIN32 */
cl_initialize_crypto();
if ((opts = optparse(NULL, argc, argv, 1, OPT_CLAMSCAN, 0, NULL)) == NULL) {
mprintf(LOGG_ERROR, "Can't parse command line options\n");
return 2;
}
if (optget(opts, "verbose")->enabled) {
mprintf_verbose = 1;
logg_verbose = 1;
}
if (optget(opts, "quiet")->enabled)
mprintf_quiet = 1;
if (optget(opts, "stdout")->enabled)
mprintf_stdout = 1;
if (optget(opts, "debug")->enabled) {
#if defined(C_LINUX)
/* njh@bandsman.co.uk: create a dump if needed */
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_CORE, &rlim) < 0)
perror("setrlimit");
#endif
cl_debug(); /* enable debug messages */
}
if (optget(opts, "gen-mdb")->enabled) {
cl_always_gen_section_hash();
}
if (optget(opts, "version")->enabled) {
print_version(optget(opts, "database")->strarg);
optfree(opts);
return 0;
}
if (optget(opts, "help")->enabled) {
optfree(opts);
help();
return 0;
}
if (optget(opts, "recursive")->enabled)
recursion = 1;
if (optget(opts, "infected")->enabled)
printinfected = 1;
if (optget(opts, "suppress-ok-results")->enabled)
printclean = 0;
if (optget(opts, "bell")->enabled)
bell = 1;
/* initialize logger */
if ((opt = optget(opts, "log"))->enabled) {
logg_file = opt->strarg;
if (logg(LOGG_INFO_NF, "\n-------------------------------------------------------------------------------\n\n")) {
mprintf(LOGG_ERROR, "Problem with internal logger.\n");
optfree(opts);
return 2;
}
} else
logg_file = NULL;
if (actsetup(opts)) {
optfree(opts);
logg_close();
exit(2);
}
memset(&info, 0, sizeof(struct s_info));
date_start = time(NULL);
gettimeofday(&t1, NULL);
ret = scanmanager(opts);
if (!optget(opts, "no-summary")->enabled) {
struct tm tmp;
date_end = time(NULL);
gettimeofday(&t2, NULL);
ds = t2.tv_sec - t1.tv_sec;
dms = t2.tv_usec - t1.tv_usec;
ds -= (dms < 0) ? (1) : (0);
dms += (dms < 0) ? (1000000) : (0);
logg(LOGG_INFO, "\n----------- SCAN SUMMARY -----------\n");
logg(LOGG_INFO, "Known viruses: %u\n", info.sigs);
logg(LOGG_INFO, "Engine version: %s\n", get_version());
logg(LOGG_INFO, "Scanned directories: %u\n", info.dirs);
logg(LOGG_INFO, "Scanned files: %u\n", info.files);
logg(LOGG_INFO, "Infected files: %u\n", info.ifiles);
if (info.errors)
logg(LOGG_INFO, "Total errors: %u\n", info.errors);
if (notremoved) {
logg(LOGG_INFO, "Not removed: %u\n", notremoved);
}
if (notmoved) {
logg(LOGG_INFO, "Not %s: %u\n", optget(opts, "copy")->enabled ? "moved" : "copied", notmoved);
}
mb = info.blocks * (CL_COUNT_PRECISION / 1024) / 1024.0;
logg(LOGG_INFO, "Data scanned: %2.2lf MB\n", mb);
rmb = info.rblocks * (CL_COUNT_PRECISION / 1024) / 1024.0;
logg(LOGG_INFO, "Data read: %2.2lf MB (ratio %.2f:1)\n", rmb, info.rblocks ? (double)info.blocks / (double)info.rblocks : 0);
logg(LOGG_INFO, "Time: %u.%3.3u sec (%u m %u s)\n", ds, dms / 1000, ds / 60, ds % 60);
#ifdef _WIN32
if (0 != localtime_s(&tmp, &date_start)) {
#else
if (!localtime_r(&date_start, &tmp)) {
#endif
logg(LOGG_ERROR, "Failed to get local time for Start Date.\n");
}
strftime(buffer, sizeof(buffer), "%Y:%m:%d %H:%M:%S", &tmp);
logg(LOGG_INFO, "Start Date: %s\n", buffer);
#ifdef _WIN32
if (0 != localtime_s(&tmp, &date_end)) {
#else
if (!localtime_r(&date_end, &tmp)) {
#endif
logg(LOGG_ERROR, "Failed to get local time for End Date.\n");
}
strftime(buffer, sizeof(buffer), "%Y:%m:%d %H:%M:%S", &tmp);
logg(LOGG_INFO, "End Date: %s\n", buffer);
}
optfree(opts);
return ret;
}
void help(void)
{
mprintf_stdout = 1;
mprintf(LOGG_INFO, "\n");
mprintf(LOGG_INFO, " Clam AntiVirus: Scanner %s\n", get_version());
mprintf(LOGG_INFO, " By The ClamAV Team: https://www.clamav.net/about.html#credits\n");
mprintf(LOGG_INFO, " (C) 2022 Cisco Systems, Inc.\n");
mprintf(LOGG_INFO, "\n");
mprintf(LOGG_INFO, " clamscan [options] [file/directory/-]\n");
mprintf(LOGG_INFO, "\n");
mprintf(LOGG_INFO, " --help -h Show this help\n");
mprintf(LOGG_INFO, " --version -V Print version number\n");
mprintf(LOGG_INFO, " --verbose -v Be verbose\n");
mprintf(LOGG_INFO, " --archive-verbose -a Show filenames inside scanned archives\n");
mprintf(LOGG_INFO, " --debug Enable libclamav's debug messages\n");
mprintf(LOGG_INFO, " --quiet Only output error messages\n");
mprintf(LOGG_INFO, " --stdout Write to stdout instead of stderr. Does not affect 'debug' messages.\n");
mprintf(LOGG_INFO, " --no-summary Disable summary at end of scanning\n");
mprintf(LOGG_INFO, " --infected -i Only print infected files\n");
mprintf(LOGG_INFO, " --suppress-ok-results -o Skip printing OK files\n");
mprintf(LOGG_INFO, " --bell Sound bell on virus detection\n");
mprintf(LOGG_INFO, "\n");
mprintf(LOGG_INFO, " --tempdir=DIRECTORY Create temporary files in DIRECTORY\n");
mprintf(LOGG_INFO, " --leave-temps[=yes/no(*)] Do not remove temporary files\n");
mprintf(LOGG_INFO, " --gen-json[=yes/no(*)] Generate JSON metadata for the scanned file(s). For testing & development use ONLY.\n");
mprintf(LOGG_INFO, " JSON will be printed if --debug is enabled.\n");
mprintf(LOGG_INFO, " A JSON file will dropped to the temp directory if --leave-temps is enabled.\n");
mprintf(LOGG_INFO, " --database=FILE/DIR -d FILE/DIR Load virus database from FILE or load all supported db files from DIR\n");
mprintf(LOGG_INFO, " --official-db-only[=yes/no(*)] Only load official signatures\n");
mprintf(LOGG_INFO, " --log=FILE -l FILE Save scan report to FILE\n");
mprintf(LOGG_INFO, " --recursive[=yes/no(*)] -r Scan subdirectories recursively\n");
mprintf(LOGG_INFO, " --allmatch[=yes/no(*)] -z Continue scanning within file after finding a match\n");
mprintf(LOGG_INFO, " --cross-fs[=yes(*)/no] Scan files and directories on other filesystems\n");
mprintf(LOGG_INFO, " --follow-dir-symlinks[=0/1(*)/2] Follow directory symlinks (0 = never, 1 = direct, 2 = always)\n");
mprintf(LOGG_INFO, " --follow-file-symlinks[=0/1(*)/2] Follow file symlinks (0 = never, 1 = direct, 2 = always)\n");
mprintf(LOGG_INFO, " --file-list=FILE -f FILE Scan files from FILE\n");
mprintf(LOGG_INFO, " --remove[=yes/no(*)] Remove infected files. Be careful!\n");
mprintf(LOGG_INFO, " --move=DIRECTORY Move infected files into DIRECTORY\n");
mprintf(LOGG_INFO, " --copy=DIRECTORY Copy infected files into DIRECTORY\n");
mprintf(LOGG_INFO, " --exclude=REGEX Don't scan file names matching REGEX\n");
mprintf(LOGG_INFO, " --exclude-dir=REGEX Don't scan directories matching REGEX\n");
mprintf(LOGG_INFO, " --include=REGEX Only scan file names matching REGEX\n");
mprintf(LOGG_INFO, " --include-dir=REGEX Only scan directories matching REGEX\n");
#ifdef _WIN32
mprintf(LOGG_INFO, " --memory Scan loaded executable modules\n");
mprintf(LOGG_INFO, " --kill Kill/Unload infected loaded modules\n");
mprintf(LOGG_INFO, " --unload Unload infected modules from processes\n");
#endif
mprintf(LOGG_INFO, "\n");
mprintf(LOGG_INFO, " --bytecode[=yes(*)/no] Load bytecode from the database\n");
mprintf(LOGG_INFO, " --bytecode-unsigned[=yes/no(*)] Load unsigned bytecode\n");
mprintf(LOGG_INFO, " **Caution**: You should NEVER run bytecode signatures from untrusted sources.\n");
mprintf(LOGG_INFO, " Doing so may result in arbitrary code execution.\n");
mprintf(LOGG_INFO, " --bytecode-timeout=N Set bytecode timeout (in milliseconds)\n");
mprintf(LOGG_INFO, " --statistics[=none(*)/bytecode/pcre] Collect and print execution statistics\n");
mprintf(LOGG_INFO, " --detect-pua[=yes/no(*)] Detect Possibly Unwanted Applications\n");
mprintf(LOGG_INFO, " --exclude-pua=CAT Skip PUA sigs of category CAT\n");
mprintf(LOGG_INFO, " --include-pua=CAT Load PUA sigs of category CAT\n");
mprintf(LOGG_INFO, " --detect-structured[=yes/no(*)] Detect structured data (SSN, Credit Card)\n");
mprintf(LOGG_INFO, " --structured-ssn-format=X SSN format (0=normal,1=stripped,2=both)\n");
mprintf(LOGG_INFO, " --structured-ssn-count=N Min SSN count to generate a detect\n");
mprintf(LOGG_INFO, " --structured-cc-count=N Min CC count to generate a detect\n");
mprintf(LOGG_INFO, " --structured-cc-mode=X CC mode (0=credit debit and private label, 1=credit cards only\n");
mprintf(LOGG_INFO, " --scan-mail[=yes(*)/no] Scan mail files\n");
mprintf(LOGG_INFO, " --phishing-sigs[=yes(*)/no] Enable email signature-based phishing detection\n");
mprintf(LOGG_INFO, " --phishing-scan-urls[=yes(*)/no] Enable URL signature-based phishing detection\n");
mprintf(LOGG_INFO, " --heuristic-alerts[=yes(*)/no] Heuristic alerts\n");
mprintf(LOGG_INFO, " --heuristic-scan-precedence[=yes/no(*)] Stop scanning as soon as a heuristic match is found\n");
mprintf(LOGG_INFO, " --normalize[=yes(*)/no] Normalize html, script, and text files. Use normalize=no for yara compatibility\n");
mprintf(LOGG_INFO, " --scan-pe[=yes(*)/no] Scan PE files\n");
mprintf(LOGG_INFO, " --scan-elf[=yes(*)/no] Scan ELF files\n");
mprintf(LOGG_INFO, " --scan-ole2[=yes(*)/no] Scan OLE2 containers\n");
mprintf(LOGG_INFO, " --scan-pdf[=yes(*)/no] Scan PDF files\n");
mprintf(LOGG_INFO, " --scan-swf[=yes(*)/no] Scan SWF files\n");
mprintf(LOGG_INFO, " --scan-html[=yes(*)/no] Scan HTML files\n");
mprintf(LOGG_INFO, " --scan-xmldocs[=yes(*)/no] Scan xml-based document files\n");
mprintf(LOGG_INFO, " --scan-hwp3[=yes(*)/no] Scan HWP3 files\n");
mprintf(LOGG_INFO, " --scan-archive[=yes(*)/no] Scan archive files (supported by libclamav)\n");
mprintf(LOGG_INFO, " --alert-broken[=yes/no(*)] Alert on broken executable files (PE & ELF)\n");
mprintf(LOGG_INFO, " --alert-broken-media[=yes/no(*)] Alert on broken graphics files (JPEG, TIFF, PNG, GIF)\n");
mprintf(LOGG_INFO, " --alert-encrypted[=yes/no(*)] Alert on encrypted archives and documents\n");
mprintf(LOGG_INFO, " --alert-encrypted-archive[=yes/no(*)] Alert on encrypted archives\n");
mprintf(LOGG_INFO, " --alert-encrypted-doc[=yes/no(*)] Alert on encrypted documents\n");
mprintf(LOGG_INFO, " --alert-macros[=yes/no(*)] Alert on OLE2 files containing VBA macros\n");
mprintf(LOGG_INFO, " --alert-exceeds-max[=yes/no(*)] Alert on files that exceed max file size, max scan size, or max recursion limit\n");
mprintf(LOGG_INFO, " --alert-phishing-ssl[=yes/no(*)] Alert on emails containing SSL mismatches in URLs\n");
mprintf(LOGG_INFO, " --alert-phishing-cloak[=yes/no(*)] Alert on emails containing cloaked URLs\n");
mprintf(LOGG_INFO, " --alert-partition-intersection[=yes/no(*)] Alert on raw DMG image files containing partition intersections\n");
mprintf(LOGG_INFO, " --nocerts Disable authenticode certificate chain verification in PE files\n");
mprintf(LOGG_INFO, " --dumpcerts Dump authenticode certificate chain in PE files\n");
mprintf(LOGG_INFO, "\n");
mprintf(LOGG_INFO, " --max-scantime=#n Scan time longer than this will be skipped and assumed clean (milliseconds)\n");
mprintf(LOGG_INFO, " --max-filesize=#n Files larger than this will be skipped and assumed clean\n");
mprintf(LOGG_INFO, " --max-scansize=#n The maximum amount of data to scan for each container file (**)\n");
mprintf(LOGG_INFO, " --max-files=#n The maximum number of files to scan for each container file (**)\n");
mprintf(LOGG_INFO, " --max-recursion=#n Maximum archive recursion level for container file (**)\n");
mprintf(LOGG_INFO, " --max-dir-recursion=#n Maximum directory recursion level\n");
mprintf(LOGG_INFO, " --max-embeddedpe=#n Maximum size file to check for embedded PE\n");
mprintf(LOGG_INFO, " --max-htmlnormalize=#n Maximum size of HTML file to normalize\n");
mprintf(LOGG_INFO, " --max-htmlnotags=#n Maximum size of normalized HTML file to scan\n");
mprintf(LOGG_INFO, " --max-scriptnormalize=#n Maximum size of script file to normalize\n");
mprintf(LOGG_INFO, " --max-ziptypercg=#n Maximum size zip to type reanalyze\n");
mprintf(LOGG_INFO, " --max-partitions=#n Maximum number of partitions in disk image to be scanned\n");
mprintf(LOGG_INFO, " --max-iconspe=#n Maximum number of icons in PE file to be scanned\n");
mprintf(LOGG_INFO, " --max-rechwp3=#n Maximum recursive calls to HWP3 parsing function\n");
#if HAVE_PCRE
mprintf(LOGG_INFO, " --pcre-match-limit=#n Maximum calls to the PCRE match function.\n");
mprintf(LOGG_INFO, " --pcre-recmatch-limit=#n Maximum recursive calls to the PCRE match function.\n");
mprintf(LOGG_INFO, " --pcre-max-filesize=#n Maximum size file to perform PCRE subsig matching.\n");
#endif /* HAVE_PCRE */
mprintf(LOGG_INFO, " --disable-cache Disable caching and cache checks for hash sums of scanned files.\n");
mprintf(LOGG_INFO, "\n");
mprintf(LOGG_INFO, "Pass in - as the filename for stdin.\n");
mprintf(LOGG_INFO, "\n");
mprintf(LOGG_INFO, "(*) Default scan settings\n");
mprintf(LOGG_INFO, "(**) Certain files (e.g. documents, archives, etc.) may in turn contain other\n");
mprintf(LOGG_INFO, " files inside. The above options ensure safe processing of this kind of data.\n\n");
}

1676
clamav/clamscan/manager.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,84 @@
# Copyright (C) 2020-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
if(WIN32)
add_definitions(-DWIN32_LEAN_AND_MEAN)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
# Windows compatibility headers
include_directories(${CMAKE_SOURCE_DIR}/win32/compat)
endif()
# The "common" static library.
add_library( common STATIC )
target_sources( common
PRIVATE
cert_util.c
actions.c
clamdcom.c
getopt.c
hostid.c
idmef_logging.c
misc.c
optparser.c
output.c
tar.c
PUBLIC
cert_util.h
actions.h
clamdcom.h
fdpassing.h
getopt.h
hostid.h
idmef_logging.h
misc.h
optparser.h
output.h
tar.h )
target_include_directories( common
PRIVATE ${CMAKE_BINARY_DIR}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} )
if(FOUND_SYSTEMD)
target_include_directories( common
PRIVATE ${SYSTEMD_INCLUDE_DIRS} )
endif()
if(APPLE)
target_sources( common PRIVATE mac/cert_util_mac.m )
elseif(WIN32)
target_sources( common
PRIVATE service.c scanmem.c exescanner.c
PUBLIC service.h scanmem.h exescanner.h )
target_sources( common PRIVATE win/cert_util_win.c )
else()
target_sources( common PRIVATE linux/cert_util_linux.c )
endif()
target_link_libraries( common
PUBLIC
ClamAV::libclamav
ZLIB::ZLIB
CURL::libcurl
OpenSSL::SSL
OpenSSL::Crypto )
if(WIN32)
target_link_libraries( common
PUBLIC
crypt32
psapi)
endif()
if(HAVE_SYSTEMD)
target_link_libraries( common
PRIVATE
SYSTEMD::systemd )
endif()
set_target_properties( common PROPERTIES COMPILE_FLAGS "${WARNCFLAGS}" )
if(WIN32)
set_target_properties(common PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif()
add_library( ClamAV::common ALIAS common )

View File

@@ -154,11 +154,11 @@ static HANDLE win32_openat(
cchNextDirectoryName = MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0); cchNextDirectoryName = MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
filenameW = malloc(cchNextDirectoryName * sizeof(WCHAR)); filenameW = malloc(cchNextDirectoryName * sizeof(WCHAR));
if (NULL == filenameW) { if (NULL == filenameW) {
logg("win32_openat: failed to allocate memory for next directory name UTF16LE string\n"); logg(LOGG_INFO, "win32_openat: failed to allocate memory for next directory name UTF16LE string\n");
goto done; goto done;
} }
if (0 == MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, cchNextDirectoryName)) { if (0 == MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, cchNextDirectoryName)) {
logg("win32_openat: failed to allocate buffer for unicode version of intermediate directory name.\n"); logg(LOGG_INFO, "win32_openat: failed to allocate buffer for unicode version of intermediate directory name.\n");
goto done; goto done;
} }
pRtlInitUnicodeString(&filenameU, filenameW); pRtlInitUnicodeString(&filenameU, filenameW);
@@ -183,32 +183,32 @@ static HANDLE win32_openat(
NULL, // EaBuffer NULL, // EaBuffer
0); // EaLength 0); // EaLength
if (!NT_SUCCESS(ntStatus) || (NULL == next_handle)) { if (!NT_SUCCESS(ntStatus) || (NULL == next_handle)) {
logg("win32_openat: Failed to open file '%s'. \nError: 0x%x \nioStatusBlock: 0x%x\n", filename, ntStatus, ioStatusBlock.Information); logg(LOGG_INFO, "win32_openat: Failed to open file '%s'. \nError: 0x%x \nioStatusBlock: 0x%x\n", filename, ntStatus, ioStatusBlock.Information);
goto done; goto done;
} }
logg("*win32_openat: Opened file \"%s\"\n", filename); logg(LOGG_DEBUG, "win32_openat: Opened file \"%s\"\n", filename);
if (0 == GetFileInformationByHandleEx( if (0 == GetFileInformationByHandleEx(
next_handle, // hFile, next_handle, // hFile,
FileAttributeTagInfo, // FileInformationClass FileAttributeTagInfo, // FileInformationClass
&tagInfo, // lpFileInformation &tagInfo, // lpFileInformation
sizeof(FILE_ATTRIBUTE_TAG_INFO))) { // dwBufferSize sizeof(FILE_ATTRIBUTE_TAG_INFO))) { // dwBufferSize
logg("win32_openat: Failed to get file information by handle '%s'. Error: %d.\n", filename, GetLastError()); logg(LOGG_INFO, "win32_openat: Failed to get file information by handle '%s'. Error: %d.\n", filename, GetLastError());
CloseHandle(next_handle); CloseHandle(next_handle);
next_handle = NULL; next_handle = NULL;
goto done; goto done;
} }
logg("*win32_openat: tagInfo.FileAttributes: 0x%0x\n", tagInfo.FileAttributes); logg(LOGG_DEBUG, "win32_openat: tagInfo.FileAttributes: 0x%0x\n", tagInfo.FileAttributes);
logg("*win32_openat: tagInfo.ReparseTag: 0x%0x\n", tagInfo.ReparseTag); logg(LOGG_DEBUG, "win32_openat: tagInfo.ReparseTag: 0x%0x\n", tagInfo.ReparseTag);
if (0 != (tagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { if (0 != (tagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
logg("win32_openat: File is a soft link: '%s' Aborting path traversal.\n\n", filename); logg(LOGG_INFO, "win32_openat: File is a soft link: '%s' Aborting path traversal.\n\n", filename);
CloseHandle(next_handle); CloseHandle(next_handle);
next_handle = NULL; next_handle = NULL;
goto done; goto done;
} }
logg("*win32_openat: File or directory is not a soft link.\n\n"); logg(LOGG_DEBUG, "win32_openat: File or directory is not a soft link.\n\n");
done: done:
if (NULL != filenameW) { if (NULL != filenameW) {
@@ -265,37 +265,37 @@ static int traverse_to(const char *directory, bool want_directory_handle, HANDLE
#endif #endif
if (NULL == directory || NULL == out_handle) { if (NULL == directory || NULL == out_handle) {
logg("traverse_to: Invalid arguments!\n"); logg(LOGG_INFO, "traverse_to: Invalid arguments!\n");
goto done; goto done;
} }
#ifdef _WIN32 #ifdef _WIN32
ntdll = LoadLibraryA("ntdll.dll"); ntdll = LoadLibraryA("ntdll.dll");
if (NULL == ntdll) { if (NULL == ntdll) {
logg("traverse_to: failed to load ntdll!\n"); logg(LOGG_INFO, "traverse_to: failed to load ntdll!\n");
goto done; goto done;
} }
pNtCreateFile = (PNTCF)GetProcAddress(ntdll, "NtCreateFile"); pNtCreateFile = (PNTCF)GetProcAddress(ntdll, "NtCreateFile");
if (NULL == pNtCreateFile) { if (NULL == pNtCreateFile) {
logg("traverse_to: failed to get NtCreateFile proc address!\n"); logg(LOGG_INFO, "traverse_to: failed to get NtCreateFile proc address!\n");
goto done; goto done;
} }
pRtlInitUnicodeString = (PRIUS)GetProcAddress(ntdll, "RtlInitUnicodeString"); pRtlInitUnicodeString = (PRIUS)GetProcAddress(ntdll, "RtlInitUnicodeString");
if (NULL == pRtlInitUnicodeString) { if (NULL == pRtlInitUnicodeString) {
logg("traverse_to: failed to get pRtlInitUnicodeString proc address!\n"); logg(LOGG_INFO, "traverse_to: failed to get pRtlInitUnicodeString proc address!\n");
goto done; goto done;
} }
#endif #endif
tokenized_directory = strdup(directory); tokenized_directory = strdup(directory);
if (NULL == tokenized_directory) { if (NULL == tokenized_directory) {
logg("traverse_to: Failed to get copy of directory path to be tokenized!\n"); logg(LOGG_INFO, "traverse_to: Failed to get copy of directory path to be tokenized!\n");
goto done; goto done;
} }
tokens_count = cli_strtokenize(tokenized_directory, *PATHSEP, PATH_MAX / 2, tokens); tokens_count = cli_strtokenize(tokenized_directory, *PATHSEP, PATH_MAX / 2, tokens);
if (0 == tokens_count) { if (0 == tokens_count) {
logg("traverse_to: tokenize of target directory returned 0 tokens!\n"); logg(LOGG_INFO, "traverse_to: tokenize of target directory returned 0 tokens!\n");
goto done; goto done;
} }
@@ -306,7 +306,7 @@ static int traverse_to(const char *directory, bool want_directory_handle, HANDLE
*/ */
current_handle = open("/", O_RDONLY | O_NOFOLLOW); current_handle = open("/", O_RDONLY | O_NOFOLLOW);
if (-1 == current_handle) { if (-1 == current_handle) {
logg("traverse_to: Failed to open file descriptor for '/' directory.\n"); logg(LOGG_INFO, "traverse_to: Failed to open file descriptor for '/' directory.\n");
goto done; goto done;
} }
#endif #endif
@@ -316,7 +316,7 @@ static int traverse_to(const char *directory, bool want_directory_handle, HANDLE
} }
if (0 == tokens_count) { if (0 == tokens_count) {
logg("traverse_to: Failed to get copy of directory path to be tokenized!\n"); logg(LOGG_INFO, "traverse_to: Failed to get copy of directory path to be tokenized!\n");
goto done; goto done;
} }
@@ -328,7 +328,7 @@ static int traverse_to(const char *directory, bool want_directory_handle, HANDLE
#ifndef _WIN32 #ifndef _WIN32
next_handle = openat(current_handle, tokens[i], O_RDONLY | O_NOFOLLOW); next_handle = openat(current_handle, tokens[i], O_RDONLY | O_NOFOLLOW);
if (-1 == next_handle) { if (-1 == next_handle) {
logg("traverse_to: Failed open %s\n", tokens[i]); logg(LOGG_INFO, "traverse_to: Failed open %s\n", tokens[i]);
goto done; goto done;
} }
close(current_handle); close(current_handle);
@@ -369,14 +369,14 @@ static int traverse_to(const char *directory, bool want_directory_handle, HANDLE
shareAccess); shareAccess);
} }
if (NULL == next_handle) { if (NULL == next_handle) {
logg("traverse_to: Failed open %s\n", tokens[i]); logg(LOGG_INFO, "traverse_to: Failed open %s\n", tokens[i]);
goto done; goto done;
} }
CloseHandle(current_handle); CloseHandle(current_handle);
current_handle = next_handle; current_handle = next_handle;
next_handle = NULL; next_handle = NULL;
#endif #endif
logg("*traverse_to: Handle opened for '%s' directory.\n", tokens[i]); logg(LOGG_DEBUG, "traverse_to: Handle opened for '%s' directory.\n", tokens[i]);
} }
status = 0; status = 0;
@@ -426,22 +426,22 @@ static int traverse_rename(const char *source, const char *destination)
#endif #endif
if (NULL == source || NULL == destination) { if (NULL == source || NULL == destination) {
logg("traverse_rename: Invalid arguments!\n"); logg(LOGG_INFO, "traverse_rename: Invalid arguments!\n");
goto done; goto done;
} }
#ifndef _WIN32 #ifndef _WIN32
if (0 != traverse_to(source, true, &source_directory_fd)) { if (0 != traverse_to(source, true, &source_directory_fd)) {
logg("traverse_rename: Failed to open file descriptor for source directory!\n"); logg(LOGG_INFO, "traverse_rename: Failed to open file descriptor for source directory!\n");
goto done; goto done;
} }
#else #else
if (0 != traverse_to(source, false, &source_file_handle)) { if (0 != traverse_to(source, false, &source_file_handle)) {
logg("traverse_rename: Failed to open file descriptor for source file!\n"); logg(LOGG_INFO, "traverse_rename: Failed to open file descriptor for source file!\n");
goto done; goto done;
} }
if (0 != traverse_to(destination, true, &destination_dir_handle)) { if (0 != traverse_to(destination, true, &destination_dir_handle)) {
logg("traverse_rename: Failed to open file descriptor for destination directory!\n"); logg(LOGG_INFO, "traverse_rename: Failed to open file descriptor for destination directory!\n");
goto done; goto done;
} }
#endif #endif
@@ -449,12 +449,12 @@ static int traverse_rename(const char *source, const char *destination)
#ifndef _WIN32 #ifndef _WIN32
ret = cli_basename(source, strlen(source), &source_basename); ret = cli_basename(source, strlen(source), &source_basename);
if (CL_SUCCESS != ret) { if (CL_SUCCESS != ret) {
logg("traverse_rename: Failed to get basename of source path:%s\n\tError: %d\n", source, (int)ret); logg(LOGG_INFO, "traverse_rename: Failed to get basename of source path:%s\n\tError: %d\n", source, (int)ret);
goto done; goto done;
} }
if (0 != renameat(source_directory_fd, source_basename, -1, destination)) { if (0 != renameat(source_directory_fd, source_basename, -1, destination)) {
logg("traverse_rename: Failed to rename: %s\n\tto: %s\nError:%s\n", source, destination, strerror(errno)); logg(LOGG_INFO, "traverse_rename: Failed to rename: %s\n\tto: %s\nError:%s\n", source, destination, strerror(errno));
goto done; goto done;
} }
#else #else
@@ -462,17 +462,17 @@ static int traverse_rename(const char *source, const char *destination)
cchDestFilepath = MultiByteToWideChar(CP_UTF8, 0, destination, strlen(destination), NULL, 0); cchDestFilepath = MultiByteToWideChar(CP_UTF8, 0, destination, strlen(destination), NULL, 0);
destFilepathW = calloc(cchDestFilepath * sizeof(WCHAR), 1); destFilepathW = calloc(cchDestFilepath * sizeof(WCHAR), 1);
if (NULL == destFilepathW) { if (NULL == destFilepathW) {
logg("traverse_rename: failed to allocate memory for destination basename UTF16LE string\n"); logg(LOGG_INFO, "traverse_rename: failed to allocate memory for destination basename UTF16LE string\n");
goto done; goto done;
} }
if (0 == MultiByteToWideChar(CP_UTF8, 0, destination, strlen(destination), destFilepathW, cchDestFilepath)) { if (0 == MultiByteToWideChar(CP_UTF8, 0, destination, strlen(destination), destFilepathW, cchDestFilepath)) {
logg("traverse_rename: failed to allocate buffer for UTF16LE version of destination file basename.\n"); logg(LOGG_INFO, "traverse_rename: failed to allocate buffer for UTF16LE version of destination file basename.\n");
goto done; goto done;
} }
fileInfo = calloc(1, sizeof(FILE_RENAME_INFO) + cchDestFilepath * sizeof(WCHAR)); fileInfo = calloc(1, sizeof(FILE_RENAME_INFO) + cchDestFilepath * sizeof(WCHAR));
if (NULL == fileInfo) { if (NULL == fileInfo) {
logg("traverse_rename: failed to allocate memory for fileInfo struct\n"); logg(LOGG_INFO, "traverse_rename: failed to allocate memory for fileInfo struct\n");
goto done; goto done;
} }
@@ -486,7 +486,7 @@ static int traverse_rename(const char *source, const char *destination)
fileInfo, // FileInformation fileInfo, // FileInformation
sizeof(FILE_RENAME_INFO) + cchDestFilepath * sizeof(WCHAR))) { // Length sizeof(FILE_RENAME_INFO) + cchDestFilepath * sizeof(WCHAR))) { // Length
logg("traverse_rename: Failed to set file rename info for '%s' to '%s'.\nError: %d\n", source, destination, GetLastError()); logg(LOGG_INFO, "traverse_rename: Failed to set file rename info for '%s' to '%s'.\nError: %d\n", source, destination, GetLastError());
goto done; goto done;
} }
#endif #endif
@@ -544,7 +544,7 @@ static int traverse_unlink(const char *target)
char *target_basename = NULL; char *target_basename = NULL;
if (NULL == target) { if (NULL == target) {
logg("traverse_unlink: Invalid arguments!\n"); logg(LOGG_INFO, "traverse_unlink: Invalid arguments!\n");
goto done; goto done;
} }
@@ -555,19 +555,19 @@ static int traverse_unlink(const char *target)
/* On Windows, we want a handle to the file, not the directory */ /* On Windows, we want a handle to the file, not the directory */
if (0 != traverse_to(target, false, &target_file_handle)) { if (0 != traverse_to(target, false, &target_file_handle)) {
#endif #endif
logg("traverse_unlink: Failed to open file descriptor for target directory!\n"); logg(LOGG_INFO, "traverse_unlink: Failed to open file descriptor for target directory!\n");
goto done; goto done;
} }
ret = cli_basename(target, strlen(target), &target_basename); ret = cli_basename(target, strlen(target), &target_basename);
if (CL_SUCCESS != ret) { if (CL_SUCCESS != ret) {
logg("traverse_unlink: Failed to get basename of target path: %s\n\tError: %d\n", target, (int)ret); logg(LOGG_INFO, "traverse_unlink: Failed to get basename of target path: %s\n\tError: %d\n", target, (int)ret);
goto done; goto done;
} }
#ifndef _WIN32 #ifndef _WIN32
if (0 != unlinkat(target_directory_fd, target_basename, 0)) { if (0 != unlinkat(target_directory_fd, target_basename, 0)) {
logg("traverse_unlink: Failed to unlink: %s\nError:%s\n", target, strerror(errno)); logg(LOGG_INFO, "traverse_unlink: Failed to unlink: %s\nError:%s\n", target, strerror(errno));
goto done; goto done;
} }
#else #else
@@ -578,11 +578,11 @@ static int traverse_unlink(const char *target)
&fileInfo, // FileInformation &fileInfo, // FileInformation
sizeof(FILE_DISPOSITION_INFO))) { // Length sizeof(FILE_DISPOSITION_INFO))) { // Length
logg("traverse_unlink: Failed to set file disposition to 'DELETE' for '%s'.\n", target); logg(LOGG_INFO, "traverse_unlink: Failed to set file disposition to 'DELETE' for '%s'.\n", target);
goto done; goto done;
} }
if (FALSE == CloseHandle(target_file_handle)) { if (FALSE == CloseHandle(target_file_handle)) {
logg("traverse_unlink: Failed to set close & delete file '%s'.\n", target); logg(LOGG_INFO, "traverse_unlink: Failed to set close & delete file '%s'.\n", target);
goto done; goto done;
} }
target_file_handle = NULL; target_file_handle = NULL;
@@ -626,14 +626,14 @@ static void action_move(const char *filename)
#else #else
if (fd < 0 || (((copied = 1)) && filecopy(filename, nuname))) { if (fd < 0 || (((copied = 1)) && filecopy(filename, nuname))) {
#endif #endif
logg("!Can't move file %s to %s\n", filename, nuname); logg(LOGG_ERROR, "Can't move file %s to %s\n", filename, nuname);
notmoved++; notmoved++;
if (nuname) traverse_unlink(nuname); if (nuname) traverse_unlink(nuname);
} else { } else {
if (copied && (0 != traverse_unlink(filename))) if (copied && (0 != traverse_unlink(filename)))
logg("!Can't unlink '%s' after copy: %s\n", filename, strerror(errno)); logg(LOGG_ERROR, "Can't unlink '%s' after copy: %s\n", filename, strerror(errno));
else else
logg("~%s: moved to '%s'\n", filename, nuname); logg(LOGG_INFO, "%s: moved to '%s'\n", filename, nuname);
} }
done: done:
@@ -649,11 +649,11 @@ static void action_copy(const char *filename)
int fd = getdest(filename, &nuname); int fd = getdest(filename, &nuname);
if (fd < 0 || filecopy(filename, nuname)) { if (fd < 0 || filecopy(filename, nuname)) {
logg("!Can't copy file '%s'\n", filename); logg(LOGG_ERROR, "Can't copy file '%s'\n", filename);
notmoved++; notmoved++;
if (nuname) traverse_unlink(nuname); if (nuname) traverse_unlink(nuname);
} else } else
logg("~%s: copied to '%s'\n", filename, nuname); logg(LOGG_INFO, "%s: copied to '%s'\n", filename, nuname);
if (fd >= 0) close(fd); if (fd >= 0) close(fd);
if (nuname) free(nuname); if (nuname) free(nuname);
@@ -668,10 +668,10 @@ static void action_remove(const char *filename)
} }
if (0 != traverse_unlink(filename)) { if (0 != traverse_unlink(filename)) {
logg("!Can't remove file '%s'\n", filename); logg(LOGG_ERROR, "Can't remove file '%s'\n", filename);
notremoved++; notremoved++;
} else { } else {
logg("~%s: Removed.\n", filename); logg(LOGG_INFO, "%s: Removed.\n", filename);
} }
done: done:
@@ -683,7 +683,7 @@ static int isdir(void)
{ {
STATBUF sb; STATBUF sb;
if (CLAMSTAT(actarget, &sb) || !S_ISDIR(sb.st_mode)) { if (CLAMSTAT(actarget, &sb) || !S_ISDIR(sb.st_mode)) {
logg("!'%s' doesn't exist or is not a directory\n", actarget); logg(LOGG_ERROR, "'%s' doesn't exist or is not a directory\n", actarget);
return 0; return 0;
} }
return 1; return 1;
@@ -704,7 +704,7 @@ int actsetup(const struct optstruct *opts)
#ifndef _WIN32 #ifndef _WIN32
ret = cli_realpath((const char *)actarget, &actarget); ret = cli_realpath((const char *)actarget, &actarget);
if (CL_SUCCESS != ret || NULL == actarget) { if (CL_SUCCESS != ret || NULL == actarget) {
logg("action_setup: Failed to get realpath of %s\n", actarget); logg(LOGG_INFO, "action_setup: Failed to get realpath of %s\n", actarget);
return 0; return 0;
} }
#endif #endif

View File

@@ -46,14 +46,14 @@ static cl_error_t _x509_to_pem(X509 *cert,
char *pem_data = NULL; char *pem_data = NULL;
if (cert == NULL || data == NULL || len == NULL) { if (cert == NULL || data == NULL || len == NULL) {
mprintf("!_x509_to_pem: Invalid argument\n"); mprintf(LOGG_ERROR, "_x509_to_pem: Invalid argument\n");
goto done; goto done;
} }
/* Output the certs to a new BIO using the PEM format */ /* Output the certs to a new BIO using the PEM format */
out = BIO_new(BIO_s_mem()); out = BIO_new(BIO_s_mem());
if (!out) { if (!out) {
mprintf("!BIO_new failed\n"); mprintf(LOGG_ERROR, "BIO_new failed\n");
goto done; goto done;
} }
@@ -64,14 +64,14 @@ static cl_error_t _x509_to_pem(X509 *cert,
/* Convert the BIO to char* */ /* Convert the BIO to char* */
pem_len = BIO_get_mem_data(out, &pem_data); pem_len = BIO_get_mem_data(out, &pem_data);
if (pem_len <= 0 || !pem_data) { if (pem_len <= 0 || !pem_data) {
mprintf("!BIO_new: BIO_get_mem_data failed\n"); mprintf(LOGG_ERROR, "BIO_new: BIO_get_mem_data failed\n");
BIO_free_all(out); BIO_free_all(out);
goto done; goto done;
} }
*data = calloc(1, pem_len + 1); *data = calloc(1, pem_len + 1);
if (!*data) { if (!*data) {
mprintf("!BIO_new: malloc failed\n"); mprintf(LOGG_ERROR, "BIO_new: malloc failed\n");
BIO_free_all(out); BIO_free_all(out);
goto done; goto done;
} }
@@ -85,7 +85,7 @@ static cl_error_t _x509_to_pem(X509 *cert,
ret = CL_SUCCESS; ret = CL_SUCCESS;
done: done:
return (0); return ret;
} }
/** /**
@@ -119,21 +119,21 @@ static cl_error_t _x509_to_pem_append(X509 *ca_cert,
if (ca_cert == NULL || total_buf_len == NULL || if (ca_cert == NULL || total_buf_len == NULL ||
remaining_buf_len == NULL || *cert_data == NULL) { remaining_buf_len == NULL || *cert_data == NULL) {
mprintf("!NULL parameter given\n"); mprintf(LOGG_ERROR, "NULL parameter given\n");
goto done; goto done;
} }
current_len = *total_buf_len; current_len = *total_buf_len;
if (_x509_to_pem(ca_cert, &pem_data, &pem_data_len) != 0) { if (CL_SUCCESS != _x509_to_pem(ca_cert, &pem_data, &pem_data_len)) {
mprintf("!Failed to convert x509 certificate to PEM\n"); mprintf(LOGG_ERROR, "Failed to convert x509 certificate to PEM\n");
goto done; goto done;
} }
if (pem_data_len > (int)*remaining_buf_len) { if (pem_data_len > (int)*remaining_buf_len) {
tmp = realloc(*cert_data, current_len + pem_data_len + 1); tmp = realloc(*cert_data, current_len + pem_data_len + 1);
if (tmp == NULL) { if (tmp == NULL) {
mprintf("!Could not realloc enough memory for PEM " mprintf(LOGG_ERROR, "Could not realloc enough memory for PEM "
"certificate\n"); "certificate\n");
free(*cert_data); free(*cert_data);
@@ -199,7 +199,7 @@ void cert_store_unload(void)
pt_err = pthread_mutex_lock(&_cert_store.mutex); pt_err = pthread_mutex_lock(&_cert_store.mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex lock failed\n"); mprintf(LOGG_ERROR, "Mutex lock failed\n");
} }
cert_store_unload_int(); cert_store_unload_int();
@@ -207,7 +207,7 @@ void cert_store_unload(void)
pt_err = pthread_mutex_unlock(&_cert_store.mutex); pt_err = pthread_mutex_unlock(&_cert_store.mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex unlock failed\n"); mprintf(LOGG_ERROR, "Mutex unlock failed\n");
} }
} }
@@ -236,7 +236,7 @@ static cl_error_t x509_cert_name_cmp(X509 *cert_a, X509 *cert_b, int *cmp_out)
a = X509_get_subject_name(cert_a); a = X509_get_subject_name(cert_a);
if (-1 == X509_NAME_print_ex(bio_out_a, a, 0, XN_FLAG_SEP_SPLUS_SPC)) { if (-1 == X509_NAME_print_ex(bio_out_a, a, 0, XN_FLAG_SEP_SPLUS_SPC)) {
mprintf("!Failed to print x509 certificate name!\n"); mprintf(LOGG_ERROR, "Failed to print x509 certificate name!\n");
goto done; goto done;
} }
BIO_get_mem_ptr(bio_out_a, &biomem_a); BIO_get_mem_ptr(bio_out_a, &biomem_a);
@@ -244,7 +244,7 @@ static cl_error_t x509_cert_name_cmp(X509 *cert_a, X509 *cert_b, int *cmp_out)
b = X509_get_subject_name(cert_b); b = X509_get_subject_name(cert_b);
if (-1 == X509_NAME_print_ex(bio_out_b, b, 0, XN_FLAG_SEP_SPLUS_SPC)) { if (-1 == X509_NAME_print_ex(bio_out_b, b, 0, XN_FLAG_SEP_SPLUS_SPC)) {
mprintf("!Failed to print x509 certificate name!\n"); mprintf(LOGG_ERROR, "Failed to print x509 certificate name!\n");
goto done; goto done;
} }
BIO_get_mem_ptr(bio_out_b, &biomem_b); BIO_get_mem_ptr(bio_out_b, &biomem_b);
@@ -284,14 +284,14 @@ cl_error_t x509_get_cert_name(X509 *cert, char **name)
a = X509_get_subject_name(cert); a = X509_get_subject_name(cert);
if (-1 == X509_NAME_print_ex(bio_out, a, 0, XN_FLAG_SEP_SPLUS_SPC)) { if (-1 == X509_NAME_print_ex(bio_out, a, 0, XN_FLAG_SEP_SPLUS_SPC)) {
mprintf("!Failed to print x509 certificate name!\n"); mprintf(LOGG_ERROR, "Failed to print x509 certificate name!\n");
goto done; goto done;
} }
BIO_get_mem_ptr(bio_out, &biomem); BIO_get_mem_ptr(bio_out, &biomem);
cert_name = malloc(biomem->length + 1); cert_name = malloc(biomem->length + 1);
if (!cert_name) { if (!cert_name) {
mprintf("!Failed to allocate memory for certificate name biomem structure!\n"); mprintf(LOGG_ERROR, "Failed to allocate memory for certificate name biomem structure!\n");
goto done; goto done;
} }
@@ -323,13 +323,13 @@ cl_error_t cert_store_export_pem(char **cert_data,
bool add_additional_ca_cert = true; bool add_additional_ca_cert = true;
if ((cert_data == NULL) || (cert_data_len == NULL)) { if ((cert_data == NULL) || (cert_data_len == NULL)) {
mprintf("!One or more arguments are NULL\n"); mprintf(LOGG_ERROR, "One or more arguments are NULL\n");
goto done; goto done;
} }
*cert_data = calloc(1, STARTING_RAW_PEM_LENGTH + 1); *cert_data = calloc(1, STARTING_RAW_PEM_LENGTH + 1);
if (*cert_data == NULL) { if (*cert_data == NULL) {
mprintf("!Could not allocate memory for PEM certs\n"); mprintf(LOGG_ERROR, "Could not allocate memory for PEM certs\n");
goto done; goto done;
} }
*cert_data_len = 0; *cert_data_len = 0;
@@ -337,7 +337,7 @@ cl_error_t cert_store_export_pem(char **cert_data,
pt_err = pthread_mutex_lock(&_cert_store.mutex); pt_err = pthread_mutex_lock(&_cert_store.mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex lock failed\n"); mprintf(LOGG_ERROR, "Mutex lock failed\n");
} }
locked = true; locked = true;
@@ -430,7 +430,7 @@ done:
pt_err = pthread_mutex_unlock(&_cert_store.mutex); pt_err = pthread_mutex_unlock(&_cert_store.mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex unlock failed\n"); mprintf(LOGG_ERROR, "Mutex unlock failed\n");
} }
locked = false; locked = false;
} }
@@ -451,14 +451,14 @@ cl_error_t cert_store_set_trusted_int(X509 **trusted_certs, size_t trusted_cert_
do { do {
if ((trusted_certs == NULL) || (trusted_cert_count == 0)) { if ((trusted_certs == NULL) || (trusted_cert_count == 0)) {
mprintf("!Empty trusted certificate list\n"); mprintf(LOGG_ERROR, "Empty trusted certificate list\n");
break; break;
} }
tmp_trusted.certificates = calloc(trusted_cert_count, tmp_trusted.certificates = calloc(trusted_cert_count,
sizeof(*tmp_trusted.certificates)); sizeof(*tmp_trusted.certificates));
if (!tmp_trusted.certificates) { if (!tmp_trusted.certificates) {
mprintf("!Failed to reserve memory for trusted certs\n"); mprintf(LOGG_ERROR, "Failed to reserve memory for trusted certs\n");
break; break;
} }
@@ -480,7 +480,7 @@ cl_error_t cert_store_set_trusted_int(X509 **trusted_certs, size_t trusted_cert_
tmp_trusted.certificates[tmp_trusted.count] = tmp_trusted.certificates[tmp_trusted.count] =
X509_dup(trusted_certs[i]); X509_dup(trusted_certs[i]);
if (!tmp_trusted.certificates[tmp_trusted.count]) { if (!tmp_trusted.certificates[tmp_trusted.count]) {
mprintf("!X509_dup failed at index: %zu\n", i); mprintf(LOGG_ERROR, "X509_dup failed at index: %zu\n", i);
continue; /* continue on error */ continue; /* continue on error */
} }
@@ -509,7 +509,7 @@ cl_error_t cert_store_set_trusted(X509 **trusted_certs, size_t trusted_cert_coun
pt_err = pthread_mutex_lock(&_cert_store.mutex); pt_err = pthread_mutex_lock(&_cert_store.mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex lock failed\n"); mprintf(LOGG_ERROR, "Mutex lock failed\n");
} }
if (_cert_store.loaded) { if (_cert_store.loaded) {
@@ -519,7 +519,7 @@ cl_error_t cert_store_set_trusted(X509 **trusted_certs, size_t trusted_cert_coun
pt_err = pthread_mutex_unlock(&_cert_store.mutex); pt_err = pthread_mutex_unlock(&_cert_store.mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex unlock failed\n"); mprintf(LOGG_ERROR, "Mutex unlock failed\n");
} }
return ret; return ret;
@@ -533,7 +533,7 @@ size_t cert_store_remove_trusted(void)
pt_err = pthread_mutex_lock(&_cert_store.mutex); pt_err = pthread_mutex_lock(&_cert_store.mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex lock failed\n"); mprintf(LOGG_ERROR, "Mutex lock failed\n");
} }
if (_cert_store.loaded) { if (_cert_store.loaded) {
@@ -544,7 +544,7 @@ size_t cert_store_remove_trusted(void)
pt_err = pthread_mutex_unlock(&_cert_store.mutex); pt_err = pthread_mutex_unlock(&_cert_store.mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex unlock failed\n"); mprintf(LOGG_ERROR, "Mutex unlock failed\n");
} }
return count; return count;
@@ -558,7 +558,7 @@ void cert_fill_X509_store(X509_STORE *store, X509 **certs, size_t cert_count)
if (store && certs && cert_count > 0) { if (store && certs && cert_count > 0) {
for (i = 0; i < cert_count; ++i) { for (i = 0; i < cert_count; ++i) {
if (!certs[i]) { if (!certs[i]) {
mprintf("!NULL cert at index %zu in X509 cert list; skipping\n", i); mprintf(LOGG_ERROR, "NULL cert at index %zu in X509 cert list; skipping\n", i);
continue; continue;
} }
if (X509_STORE_add_cert(store, certs[i]) != 1) { if (X509_STORE_add_cert(store, certs[i]) != 1) {
@@ -571,15 +571,18 @@ void cert_fill_X509_store(X509_STORE *store, X509 **certs, size_t cert_count)
#endif #endif
err = ERR_get_error(); err = ERR_get_error();
if (X509_R_CERT_ALREADY_IN_HASH_TABLE == ERR_GET_REASON(err)) { if (X509_R_CERT_ALREADY_IN_HASH_TABLE == ERR_GET_REASON(err)) {
mprintf("*Certificate skipped; already exists in store: %s\n", mprintf(LOGG_DEBUG, "Certificate skipped; already exists in store: %s\n",
(name ? name : "")); (name ? name : ""));
} else { } else {
mprintf("!Failed to add certificate to store: %s (%lu) [%s]\n", mprintf(LOGG_ERROR, "Failed to add certificate to store: %s (%lu) [%s]\n",
ERR_error_string(err, NULL), err, ERR_error_string(err, NULL), err,
(name ? name : "")); (name ? name : ""));
} }
#if OPENSSL_VERSION_NUMBER >= 0x10100000L #if OPENSSL_VERSION_NUMBER >= 0x10100000L
if (NULL != name) {
free(name); free(name);
name = NULL;
}
#endif #endif
} }
} }
@@ -593,24 +596,24 @@ void cert_store_export_certs(X509_STORE *store, X509 *additional_ca_cert)
do { do {
if (!store) { if (!store) {
mprintf("!NULL X509 store\n"); mprintf(LOGG_ERROR, "NULL X509 store\n");
break; break;
} }
cert_store = cert_store_get_int(); cert_store = cert_store_get_int();
if (!cert_store) { if (!cert_store) {
mprintf("!Failed to retrieve cert store\n"); mprintf(LOGG_ERROR, "Failed to retrieve cert store\n");
break; break;
} }
pt_err = pthread_mutex_lock(&cert_store->mutex); pt_err = pthread_mutex_lock(&cert_store->mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex lock failed\n"); mprintf(LOGG_ERROR, "Mutex lock failed\n");
} }
if (!cert_store->loaded) { if (!cert_store->loaded) {
mprintf("!Cert store not loaded\n"); mprintf(LOGG_ERROR, "Cert store not loaded\n");
break; break;
} }
@@ -637,16 +640,19 @@ void cert_store_export_certs(X509_STORE *store, X509 *additional_ca_cert)
name = additional_ca_cert->name; name = additional_ca_cert->name;
#endif #endif
if (X509_R_CERT_ALREADY_IN_HASH_TABLE == ERR_GET_REASON(err)) { if (X509_R_CERT_ALREADY_IN_HASH_TABLE == ERR_GET_REASON(err)) {
mprintf("Certificate is already in trust [%s]\n", mprintf(LOGG_INFO, "Certificate is already in trust [%s]\n",
(name ? name : "")); (name ? name : ""));
} else { } else {
mprintf("!Failed to add CA certificate for the SSL context. " mprintf(LOGG_ERROR, "Failed to add CA certificate for the SSL context. "
"Error: %d [%s]\n", "Error: %d [%s]\n",
ERR_GET_REASON(err), ERR_GET_REASON(err),
(name ? name : "")); (name ? name : ""));
} }
#if OPENSSL_VERSION_NUMBER >= 0x10100000L #if OPENSSL_VERSION_NUMBER >= 0x10100000L
if (NULL != name) {
free(name); free(name);
name = NULL;
}
#endif #endif
} }
} while (0); } while (0);
@@ -655,7 +661,7 @@ void cert_store_export_certs(X509_STORE *store, X509 *additional_ca_cert)
pt_err = pthread_mutex_unlock(&cert_store->mutex); pt_err = pthread_mutex_unlock(&cert_store->mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex unlock failed\n"); mprintf(LOGG_ERROR, "Mutex unlock failed\n");
} }
} }
} }
@@ -670,13 +676,13 @@ CURLcode sslctx_function(CURL *curl, void *ssl_ctx, void *userptr)
cert_store = cert_store_get_int(); cert_store = cert_store_get_int();
if (!cert_store) { if (!cert_store) {
mprintf("!Failed to retrieve cert store\n"); mprintf(LOGG_ERROR, "Failed to retrieve cert store\n");
goto done; goto done;
} }
if (!cert_store->loaded) { if (!cert_store->loaded) {
if (CL_SUCCESS != cert_store_load(NULL, 0)) { if (CL_SUCCESS != cert_store_load(NULL, 0)) {
mprintf("!Failed to load cert store\n"); mprintf(LOGG_ERROR, "Failed to load cert store\n");
goto done; goto done;
} }
} }

483
clamav/common/clamdcom.c Normal file
View File

@@ -0,0 +1,483 @@
/*
* Copyright (C) 2013-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2009-2013 Sourcefire, Inc.
*
* Author: aCaB
*
* 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 <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <errno.h>
#ifndef _WIN32
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#endif
#include "clamav.h"
#include "actions.h"
#include "output.h"
#include "clamdcom.h"
#ifndef _WIN32
struct sockaddr_un nixsock;
#endif
static const char *scancmd[] = {"CONTSCAN", "MULTISCAN", "INSTREAM", "FILDES", "ALLMATCHSCAN"};
/* Sends bytes over a socket
* Returns 0 on success */
int sendln(int sockd, const char *line, unsigned int len)
{
while (len) {
int sent = send(sockd, line, len, 0);
if (sent <= 0) {
if (sent && errno == EINTR) continue;
logg(LOGG_ERROR, "Can't send to clamd: %s\n", strerror(errno));
return 1;
}
line += sent;
len -= sent;
}
return 0;
}
/* Inits a RECVLN struct before it can be used in recvln() - see below */
void recvlninit(struct RCVLN *s, int sockd)
{
s->sockd = sockd;
s->bol = s->cur = s->buf;
s->r = 0;
}
/* Receives a full (terminated with \0) line from a socket
* Sets rbol to the begin of the received line, and optionally
* reol to the end of line.
* Should be called repeatedly until all input is consumed
* Returns:
* - the length of the line (a positive number) on success
* - 0 if the connection is closed
* - -1 on error
*/
int recvln(struct RCVLN *s, char **rbol, char **reol)
{
char *eol;
while (1) {
if (!s->r) {
s->r = recv(s->sockd, s->cur, sizeof(s->buf) - (s->cur - s->buf), 0);
if (s->r <= 0) {
if (s->r && errno == EINTR) {
s->r = 0;
continue;
}
if (s->r || s->cur != s->buf) {
*s->cur = '\0';
if (strcmp(s->buf, "UNKNOWN COMMAND\n"))
logg(LOGG_ERROR, "Communication error\n");
else
logg(LOGG_ERROR, "Command rejected by clamd (wrong clamd version?)\n");
return -1;
}
return 0;
}
}
if ((eol = memchr(s->cur, 0, s->r))) {
int ret = 0;
eol++;
s->r -= eol - s->cur;
*rbol = s->bol;
if (reol) *reol = eol;
ret = eol - s->bol;
if (s->r)
s->bol = s->cur = eol;
else
s->bol = s->cur = s->buf;
return ret;
}
s->r += s->cur - s->bol;
if (!eol && s->r == sizeof(s->buf)) {
logg(LOGG_ERROR, "Overlong reply from clamd\n");
return -1;
}
if (!eol) {
if (s->buf != s->bol) { /* old memmove sux */
memmove(s->buf, s->bol, s->r);
s->bol = s->buf;
}
s->cur = &s->bol[s->r];
s->r = 0;
}
}
}
/* Determines if a path should be excluded
* 0: scan, 1: skip */
int chkpath(const char *path, struct optstruct *clamdopts)
{
int status = 0;
const struct optstruct *opt;
char *real_path = NULL;
if (!path) {
status = 1;
goto done;
}
if ((opt = optget(clamdopts, "ExcludePath"))->enabled) {
while (opt) {
if (match_regex(path, opt->strarg) == 1) {
logg(LOGG_DEBUG, "%s: Excluded\n", path);
status = 1;
goto done;
}
opt = opt->nextarg;
}
}
done:
if (NULL != real_path) {
free(real_path);
}
return status;
}
#ifdef HAVE_FD_PASSING
/* Issues a FILDES command and pass a FD to clamd
* Returns >0 on success, 0 soft fail, -1 hard fail */
int send_fdpass(int sockd, const char *filename)
{
struct iovec iov[1];
struct msghdr msg;
struct cmsghdr *cmsg;
unsigned char fdbuf[CMSG_SPACE(sizeof(int))];
char dummy[] = "";
int fd;
const char zFILDES[] = "zFILDES";
if (filename) {
if ((fd = open(filename, O_RDONLY)) < 0) {
logg(LOGG_INFO, "%s: Failed to open file\n", filename);
return 0;
}
} else
fd = 0;
if (sendln(sockd, zFILDES, sizeof(zFILDES))) {
close(fd);
return -1;
}
iov[0].iov_base = dummy;
iov[0].iov_len = 1;
memset(&msg, 0, sizeof(msg));
msg.msg_control = fdbuf;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_controllen = CMSG_LEN(sizeof(int));
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = fd;
if (sendmsg(sockd, &msg, 0) == -1) {
logg(LOGG_ERROR, "FD send failed: %s\n", strerror(errno));
close(fd);
return -1;
}
close(fd);
return 1;
}
#endif
/* Issues an INSTREAM command to clamd and streams the given file
* Returns >0 on success, 0 soft fail, -1 hard fail */
int send_stream(int sockd, const char *filename, struct optstruct *clamdopts)
{
uint32_t buf[BUFSIZ / sizeof(uint32_t)];
int fd, len;
unsigned long int todo = optget(clamdopts, "StreamMaxLength")->numarg;
const char zINSTREAM[] = "zINSTREAM";
if (filename) {
if ((fd = safe_open(filename, O_RDONLY | O_BINARY)) < 0) {
logg(LOGG_INFO, "%s: Failed to open file. ERROR\n", filename);
return 0;
}
} else {
/* Read stream from STDIN */
fd = 0;
}
if (sendln(sockd, zINSTREAM, sizeof(zINSTREAM))) {
close(fd);
return -1;
}
while ((len = read(fd, &buf[1], sizeof(buf) - sizeof(uint32_t))) > 0) {
if ((unsigned int)len > todo) len = todo;
buf[0] = htonl(len);
if (sendln(sockd, (const char *)buf, len + sizeof(uint32_t))) {
close(fd);
return -1;
}
todo -= len;
if (!todo) {
len = 0;
break;
}
}
close(fd);
if (len) {
logg(LOGG_ERROR, "Failed to read from %s.\n", filename ? filename : "STDIN");
return 0;
}
*buf = 0;
sendln(sockd, (const char *)buf, 4);
return 1;
}
/* Connects to clamd
* Returns a FD or -1 on error */
int dconnect(struct optstruct *clamdopts)
{
int sockd, res;
const struct optstruct *opt;
struct addrinfo hints, *info, *p;
char port[10];
char *ipaddr;
#ifndef _WIN32
opt = optget(clamdopts, "LocalSocket");
if (opt->enabled) {
if ((sockd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0) {
if (connect(sockd, (struct sockaddr *)&nixsock, sizeof(nixsock)) == 0)
return sockd;
else {
logg(LOGG_ERROR, "Could not connect to clamd on LocalSocket %s: %s\n", opt->strarg, strerror(errno));
close(sockd);
}
}
}
#endif
snprintf(port, sizeof(port), "%lld", optget(clamdopts, "TCPSocket")->numarg);
opt = optget(clamdopts, "TCPAddr");
while (opt) {
if (opt->enabled) {
ipaddr = NULL;
if (opt->strarg)
ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg);
memset(&hints, 0x00, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((res = getaddrinfo(ipaddr, port, &hints, &info))) {
logg(LOGG_ERROR, "Could not lookup %s: %s\n", ipaddr ? ipaddr : "", gai_strerror(res));
opt = opt->nextarg;
continue;
}
for (p = info; p != NULL; p = p->ai_next) {
if ((sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
logg(LOGG_ERROR, "Can't create the socket: %s\n", strerror(errno));
continue;
}
if (connect(sockd, p->ai_addr, p->ai_addrlen) < 0) {
logg(LOGG_ERROR, "Could not connect to clamd on %s: %s\n", opt->strarg, strerror(errno));
closesocket(sockd);
continue;
}
freeaddrinfo(info);
return sockd;
}
freeaddrinfo(info);
}
opt = opt->nextarg;
}
return -1;
}
/* Sends a proper scan request to clamd and parses its replies
* This is used only in non IDSESSION mode
* Returns the number of infected files or -1 on error
* NOTE: filename may be NULL for STREAM scantype. */
int dsresult(int sockd, int scantype, const char *filename, int *printok, int *errors, struct optstruct *clamdopts)
{
int infected = 0, len = 0, beenthere = 0;
char *bol, *eol;
struct RCVLN rcv;
STATBUF sb;
if (filename) {
if (1 == chkpath(filename, clamdopts)) {
goto done;
}
}
recvlninit(&rcv, sockd);
switch (scantype) {
case MULTI:
case CONT:
case ALLMATCH:
if (!filename) {
logg(LOGG_INFO, "Filename cannot be NULL for MULTISCAN or CONTSCAN.\n");
infected = -1;
goto done;
}
len = strlen(filename) + strlen(scancmd[scantype]) + 3;
if (!(bol = malloc(len))) {
logg(LOGG_ERROR, "Cannot allocate a command buffer: %s\n", strerror(errno));
infected = -1;
goto done;
}
sprintf(bol, "z%s %s", scancmd[scantype], filename);
if (sendln(sockd, bol, len)) {
free(bol);
infected = -1;
goto done;
}
free(bol);
break;
case STREAM:
/* NULL filename safe in send_stream() */
len = send_stream(sockd, filename, clamdopts);
break;
#ifdef HAVE_FD_PASSING
case FILDES:
/* NULL filename safe in send_fdpass() */
len = send_fdpass(sockd, filename);
break;
#endif
}
if (len <= 0) {
if (printok)
*printok = 0;
if (errors)
(*errors)++;
infected = len;
goto done;
}
while ((len = recvln(&rcv, &bol, &eol))) {
if (len == -1) {
infected = -1;
goto done;
}
beenthere = 1;
if (!filename) logg(LOGG_INFO, "%s\n", bol);
if (len > 7) {
char *colon = strrchr(bol, ':');
if (colon && colon[1] != ' ') {
char *br;
*colon = 0;
br = strrchr(bol, '(');
if (br)
*br = 0;
colon = strrchr(bol, ':');
}
if (!colon) {
char *unkco = "UNKNOWN COMMAND";
if (!strncmp(bol, unkco, sizeof(unkco) - 1))
logg(LOGG_INFO, "clamd replied \"UNKNOWN COMMAND\". Command was %s\n",
(scantype < 0 || scantype > MAX_SCANTYPE) ? "unidentified" : scancmd[scantype]);
else
logg(LOGG_INFO, "Failed to parse reply: \"%s\"\n", bol);
infected = -1;
goto done;
} else if (!memcmp(eol - 7, " FOUND", 6)) {
static char last_filename[PATH_MAX + 1] = {'\0'};
*(eol - 7) = 0;
if (printok)
*printok = 0;
if (scantype != ALLMATCH) {
infected++;
} else {
if (filename != NULL && strcmp(filename, last_filename)) {
infected++;
strncpy(last_filename, filename, PATH_MAX);
last_filename[PATH_MAX] = '\0';
}
}
if (filename) {
if (scantype >= STREAM) {
logg(LOGG_INFO, "%s%s FOUND\n", filename, colon);
if (action) action(filename);
} else {
logg(LOGG_INFO, "%s FOUND\n", bol);
*colon = '\0';
if (action)
action(bol);
}
}
} else if (!memcmp(eol - 7, " ERROR", 6)) {
if (errors)
(*errors)++;
if (printok)
*printok = 0;
if (filename) {
if (scantype >= STREAM)
logg(LOGG_INFO, "%s%s\n", filename, colon);
else
logg(LOGG_INFO, "%s\n", bol);
}
}
}
}
if (!beenthere) {
if (!filename) {
logg(LOGG_INFO, "STDIN: noreply from clamd\n.");
infected = -1;
goto done;
}
if (CLAMSTAT(filename, &sb) == -1) {
logg(LOGG_INFO, "%s: stat() failed with %s, clamd may not be responding\n",
filename, strerror(errno));
infected = -1;
goto done;
}
if (!S_ISDIR(sb.st_mode)) {
logg(LOGG_INFO, "%s: no reply from clamd\n", filename);
infected = -1;
goto done;
}
}
done:
return infected;
}

67
clamav/common/clamdcom.h Normal file
View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2013-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2009-2013 Sourcefire, Inc.
*
* Author: aCaB
*
* 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 __CLAMDCOM_H
#define __CLAMDCOM_H
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include "misc.h"
enum {
CONT,
MULTI,
STREAM,
FILDES,
ALLMATCH,
MAX_SCANTYPE = ALLMATCH
};
struct RCVLN {
char buf[PATH_MAX + 1024]; /* FIXME must match that in clamd - bb1349 */
int sockd;
int r;
char *cur;
char *bol;
};
#ifndef _WIN32
extern struct sockaddr_un nixsock;
#endif
int sendln(int sockd, const char *line, unsigned int len);
void recvlninit(struct RCVLN *s, int sockd);
int recvln(struct RCVLN *s, char **rbol, char **reol);
int chkpath(const char *path, struct optstruct *clamdopts);
#ifdef HAVE_FD_PASSING
int send_fdpass(int sockd, const char *filename);
#endif
int send_stream(int sockd, const char *filename, struct optstruct *clamdopts);
int dconnect(struct optstruct *clamdopts);
int dsresult(int sockd, int scantype, const char *filename, int *printok, int *errors, struct optstruct *clamdopts);
#endif

330
clamav/common/exeScanner.c Normal file
View File

@@ -0,0 +1,330 @@
/*
* Copyright (C) 2021-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2005-2010 Gianluigi Tiesi <sherpya@netfarm.it>
*
* Authors: Gianluigi Tiesi
*
* 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 "exescanner.h"
/* -1 = wildchar - -2 = stop here */
sigs_t signatures[] = {
{{0x60, 0xbe, -1, -1, -1, -1, 0x8d, 0xbe, -1, -1, -1, 0xff, 0x57, -2},
"UPX",
.0f},
{{0x94, 0xbc, 0x5d, 0x07, 0x42, 0x00, 0xb9, 0x1d, 0x00, 0x00, 0x00, 0x80,
0x34, 0x0c, 0x44, 0xe2},
"UPXSHiT",
.0f},
{{0xbe, 0xa4, 0x01, 0x40, 0x00, 0xad, 0x93, 0xad, 0x97, 0xad, 0x56, 0x96,
0xb2, 0x80, 0xa4, 0xb6},
"FSG 1.33",
.0f},
{{0x4d, 0x5a, -1, -1, -1, -1, -1, -1, -1, -1, 0x00, 0x00, 0x50, 0x45, 0x00,
0x00},
"FSG 2.00",
.0f},
{{0x4d, 0x5a, 0x4b, 0x45, 0x52, 0x4e, 0x45, 0x4c, 0x33, 0x32, 0x2e, 0x44,
0x4c, 0x4c, 0x00, 0x00},
"WinUpack 0.39",
.0f},
{{0xbe, 0x88, 0x01, 0x40, 0x00, 0xad, 0x8b, 0xf8, 0x95, 0xad, 0x91, 0xf3,
0xa5, 0xad, 0xb5, 0x1c},
"Upack 2.4/2.9",
.0f},
{{0xbe, 0x48, 0x01, 0x40, 0x00, 0xad, 0x8b, 0xf8, 0x95, 0xa5, 0x33, 0xc0,
0x33, 0xc9, 0xab, 0x48},
"Upack 1.1/1.2",
.0f},
{{0x83, 0xec, 0x20, 0x53, 0x55, 0x56, 0x33, 0xdb, 0x57, 0x89, 0x5c, 0x24,
0x18, 0xc7, 0x44, 0x24},
"NullSoft PiMP",
.0f},
{{0xe9, -1, -1, -1, 0xff, 0x0c, -1, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00},
"Mew 11 1.2",
.0f},
{{0x60, 0xe9, 0x3d, 0x04, 0x00, 0x00, -2}, "ASPack 2.11", .0f},
{{0x60, 0xe8, 0x03, 0x00, 0x00, 0x00, 0xe9, 0xeb, 0x04, 0x5d, 0x45, 0x55,
0xc3, 0xe8, 0x01, 0x00},
"ASPack 2.12",
.0f},
{{0x55, 0x83, 0xc4, 0x04, 0x76, 0x08, 0x7a, 0x06, 0x74, 0x04, 0x66, 0x83,
0xea, 0x00, 0xf5, 0x50},
"Morphine 1.4/2.7",
.0f},
{{0x56, 0x72, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x0b, 0xd2, 0xf9,
0x84, 0xdb, 0x68, 0x34},
"Morphine 1.4/2.7 [2]",
.0f},
{{0x53, 0x51, 0x52, 0x56, 0x57, 0x55, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x5d,
0x8b, 0xd5, 0x81, 0xed},
"PEDiminisher 0.1",
.0f},
{{0xe8, 0xf6, 0x03, 0x00, 0x00, 0xe9, 0x9e, 0xfd, 0xff, 0xff, 0xcc, 0xcc,
0xcc, 0xcc, 0xcc, 0xcc},
"MSVC8 Release",
-1.0f},
{{0xe9, -1, -1, -1, 0x00, 0xe9, -1, -1, -1, 0x00, 0xe9, -1, -1, -1, 0x00,
0xe9},
"MSVC8 Debug",
-1.0f},
{{0xe8, -1, -1, 0x00, 0x00, 0xe9, 0x16, 0xfe, 0xff, 0xff, -2},
"MSVC6 Release",
-2.0f},
{{0xe9, 0x96, 0xee, 0x0e, 0x00, 0xb8, 0x6c, 0x02, 0x58, 0x00, 0xe8, 0xae,
0xe4, 0x0e, 0x00, 0x83},
"MSVC6 Release (2)",
-1.0f},
{{0x55, 0x8b, 0xec, 0x6a, 0xff, 0x68, 0xb0, 0x41, 0x40, 0x00, 0x68, 0x10,
0x36, 0x40, 0x00, 0x64},
"MSVC6 Release (3)",
-1.0f},
{{0x55, 0x8b, 0xec, 0x53, 0x8b, 0x5d, 0x08, 0x56, 0x8b, 0x75, 0x0c, 0x57,
0x8b, 0x7d, 0x10, 0x85},
"MSVC6 Release (4)",
-1.0f},
{{0x83, 0x7c, 0x24, 0x08, 0x01, 0x75, 0x05, 0xe8, -1, -1, 0x00, 0x00, 0xff,
0x74, 0x24, 0x04},
"MSVC6 Release DLL",
-1.0f},
{{0xff, 0x25, -1, -1, -1, -1, 0xcc, 0xcc, 0x03, 0x30, 0x01, 0x00, 0x07,
0x00, 0x00, 0x00},
"DotNet",
-1.0f},
{{0x55, 0x89, 0xe5, -2}, "MinGW", -1.0f},
{{0}, 0, 0}};
int sigcmp(const uint8_t *data, const int16_t *sig, size_t n)
{
uint8_t *d = (uint8_t *)data;
int16_t *s = (int16_t *)sig;
while (n-- != 0) {
if (*s == -2)
return 0;
if ((*s != -1) && (*d != *s))
return (*d < *s) ? -1 : +1;
d++;
s++;
}
return 0;
}
sigs_t *checksig(uint8_t *data)
{
int i = 0;
while (signatures[i].name) {
if (!sigcmp(data, signatures[i].sig, 16))
return &signatures[i];
i++;
}
return NULL;
}
double calc_entropy(const unsigned char *data, size_t size)
{
double entropy = .0f;
size_t p[256];
size_t c, i;
memset(p, 0, sizeof(p));
for (c = 0; c < size; c++)
p[data[c]]++;
for (i = 0; i < 256; i++)
if (p[i])
entropy -= ((double)p[i] / size) * log((double)p[i] / size);
return entropy;
}
#define FILLBYTES(dst) \
if (IsBadReadPtr(seek, sizeof(dst))) { \
logg(LOGG_ERROR, "exeScanner: Bad pointer!!!\n"); \
goto cleanup; \
} \
memcpy(&dst, seek, sizeof(dst));
/* Packed exe heuristic detection, errors are handled as like of non packed data
*/
int is_packed(const char *filename)
{
int packed = 0;
int i = 0, c = 0;
int badsection = 0;
double entropy = 0.0;
sigs_t *sig = NULL;
uint16_t e_mz;
uint32_t e_lfanew, e_magic;
uint32_t epoff = 0;
unsigned char *seek = NULL, *s_start = NULL, *ep = NULL, *lpMapAddress = NULL;
PIMAGE_FILE_HEADER pehdr;
PIMAGE_OPTIONAL_HEADER32 opthdr;
PIMAGE_SECTION_HEADER sechdr;
char secname[IMAGE_SIZEOF_SHORT_NAME];
HANDLE hFile = INVALID_HANDLE_VALUE, hMapFile = NULL;
hFile = CreateFileA(filename, GENERIC_READ, 0, NULL, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
elogg(LOGG_INFO, "exeScanner: CreateFileA failed %lu\n", GetLastError());
return packed; /* Returning packed, the module is loaded so it must exists
on disk */
}
hMapFile = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, "exeScanner");
if (!hMapFile) {
elogg(LOGG_INFO, "exeScanner: CreateFileMappingA() failed %lu\n", GetLastError());
goto cleanup;
}
lpMapAddress = (LPBYTE)MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
if (!lpMapAddress) {
elogg(LOGG_INFO, "exeScanner: MapViewOfFile() failed %lu\n", GetLastError());
goto cleanup;
}
seek = lpMapAddress;
/* DOS Signature 'MZ' */
FILLBYTES(e_mz);
if (e_mz != IMAGE_DOS_SIGNATURE) {
elogg(LOGG_INFO, "exeScanner: DOS Signature not found\n");
goto cleanup;
}
seek += 0x3c;
FILLBYTES(e_lfanew);
if (!e_lfanew) {
elogg(LOGG_INFO, "exeScanner: Invalid PE offset\n");
goto cleanup;
}
seek = lpMapAddress + e_lfanew;
/* PE Signature 'PE' */
FILLBYTES(e_magic);
if (e_magic != IMAGE_NT_SIGNATURE) {
elogg(LOGG_INFO, "exeScanner: PE Signature not found\n");
goto cleanup;
}
seek += sizeof(e_magic);
if (IsBadReadPtr(seek, sizeof(IMAGE_FILE_HEADER)))
goto cleanup;
pehdr = (PIMAGE_FILE_HEADER)seek;
seek += sizeof(IMAGE_FILE_HEADER);
if (IsBadReadPtr(seek, sizeof(IMAGE_OPTIONAL_HEADER32)))
goto cleanup;
opthdr = (PIMAGE_OPTIONAL_HEADER32)seek;
seek += sizeof(IMAGE_OPTIONAL_HEADER32);
if (pehdr->Machine != IMAGE_FILE_MACHINE_I386) {
elogg(LOGG_INFO, "exeScanner: Not an x86 executable\n");
goto cleanup;
}
/* Invalid sections number */
if ((pehdr->NumberOfSections < 1) || (pehdr->NumberOfSections > 32)) {
elogg(LOGG_INFO, "exeScanner: Invalid sections number\n");
packed = 1;
goto cleanup;
}
for (i = 0; i < pehdr->NumberOfSections; i++) {
double section_entropy = .0f;
if (IsBadReadPtr(seek, sizeof(IMAGE_SECTION_HEADER)))
goto cleanup;
sechdr = (PIMAGE_SECTION_HEADER)seek;
seek += sizeof(IMAGE_SECTION_HEADER);
if (opthdr->AddressOfEntryPoint >= sechdr->VirtualAddress)
epoff = opthdr->AddressOfEntryPoint - sechdr->VirtualAddress +
sechdr->PointerToRawData;
s_start = lpMapAddress + sechdr->PointerToRawData;
if (!IsBadReadPtr(s_start, sechdr->SizeOfRawData))
section_entropy = calc_entropy(s_start, sechdr->SizeOfRawData);
entropy = MAX(entropy, section_entropy);
/* Sanitize the section name */
memcpy(secname, sechdr->Name, IMAGE_SIZEOF_SHORT_NAME);
for (c = 0; (c < IMAGE_SIZEOF_SHORT_NAME) && secname[c]; c++)
if (!isprint(secname[c]))
secname[c] = '?';
secname[IMAGE_SIZEOF_SHORT_NAME - 1] = 0;
elogg(LOGG_INFO, "exeScanner: Section name: [%s] - Entropy %f\n", secname,
section_entropy);
if (!sechdr->SizeOfRawData)
badsection = 1;
}
elogg(LOGG_INFO, "exeScanner: Max entropy = %f\n", entropy);
/* EP Check */
elogg(LOGG_INFO, "exeScanner: Entry Point rva: 0x%lx - raw: 0x%lx\n",
opthdr->AddressOfEntryPoint, epoff);
ep = lpMapAddress + epoff;
if (!IsBadReadPtr(ep, EP_SIGNATURE_SIZE)) {
#ifdef DUMP_SIGNATURE
int i;
for (i = 0; i < EP_SIGNATURE_SIZE; i++)
elogg(LOGG_INFO, "%02x ", ep[i]);
elogg(LOGG_INFO, "\n[C Code]: ");
for (i = 0; i < EP_SIGNATURE_SIZE - 1; i++)
elogg(LOGG_INFO, "0x%02x, ", ep[i]);
elogg(LOGG_INFO, "0x%02x\n", ep[i]);
#endif
if ((sig = checksig(ep))) {
elogg(LOGG_INFO, "exeScanner: Signature check: %s\n", sig->name);
entropy += sig->score;
packed = (sig->score >= .0f);
if (sig->score < .0f)
elogg(
"exeScanner: Whitelisted signature found, lowering entropy to %f\n",
entropy);
} else
elogg(LOGG_INFO, "exeScanner: Signature check: Nothing found\n");
} else
elogg(LOGG_INFO, "exeScanner: Invalid address of Entry Point\n");
if (badsection) {
if ((entropy == .0f) || (entropy > ENTROPY_THRESHOLD)) {
elogg(LOGG_INFO, "exeScanner: found zero SizeOfRawData and entropy %f\n", entropy);
packed = 1;
goto cleanup;
}
}
cleanup:
if (lpMapAddress)
UnmapViewOfFile(lpMapAddress);
if (hMapFile)
CloseHandle(hMapFile);
CloseHandle(hFile);
return packed;
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2021-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2006-2008 Gianluigi Tiesi <sherpya@netfarm.it>
*
* Authors: Gianluigi Tiesi
*
* 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 _EXESCANNER_H_
#define _EXESCANNER_H_
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#ifdef EXESCANNER_STANDALONE
#define DUMP_SIGNATURE
#include <windows.h>
#define logg printf
#define elogg printf
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef __int16 int16_t;
#else
#include "output.h"
#include <others.h>
static inline void elogg(const char *fmt, ...){};
#endif /* EXESCANNER_STANDALONE */
#define ENTROPY_THRESHOLD 4.0
#define EP_SIGNATURE_SIZE 16
#ifndef IMAGE_DOS_SIGNATURE
#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */
#endif
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
typedef struct _sigs_t {
int16_t sig[16];
const char *name;
double score;
} sigs_t;
extern int is_packed(const char *filename);
static const char screv[] =
{
0x65, 0x78, 0x65, 0x53, 0x63, 0x61, 0x6e, 0x6e,
0x65, 0x72, 0x7c, 0x47, 0x50, 0x4c, 0x7c, 0x47,
0x69, 0x61, 0x6e, 0x6c, 0x75, 0x69, 0x67, 0x69,
0x20, 0x54, 0x69, 0x65, 0x73, 0x69, 0x7c, 0x3c,
0x73, 0x68, 0x65, 0x72, 0x70, 0x79, 0x61, 0x40,
0x6e, 0x65, 0x74, 0x66, 0x61, 0x72, 0x6d, 0x2e,
0x69, 0x74, 0x3e};
#endif /* _EXESCANNER_H_ */

View File

@@ -193,6 +193,7 @@ static int _getopt_internal(int argc, char *argv[], const char *shortopts,
if ((argv[i][0] == '-') && if ((argv[i][0] == '-') &&
(argv[i][1] != '\0')) { (argv[i][1] != '\0')) {
optind = i; optind = i;
opt = _getopt_internal(argc, argv, shortopts, opt = _getopt_internal(argc, argv, shortopts,
longopts, longind, longopts, longind,
long_only); long_only);

View File

@@ -58,7 +58,7 @@ char *get_hostid(void *cbdata)
if (!is_valid_hostid()) if (!is_valid_hostid())
return strdup(STATS_ANON_UUID); return strdup(STATS_ANON_UUID);
logg("HostID is valid: %s\n", hostid); logg(LOGG_INFO, "HostID is valid: %s\n", hostid);
return strdup(hostid); return strdup(hostid);
} }

View File

@@ -35,7 +35,7 @@ void prelude_logging(const char *filename, const char *virname, const char *virh
UNUSEDPARAM(virhash); UNUSEDPARAM(virhash);
UNUSEDPARAM(virsize); UNUSEDPARAM(virsize);
logg("You have to compile with libprelude using ./configure --enable-prelude\n"); logg(LOGG_INFO, "You have to compile with libprelude using ./configure --enable-prelude\n");
} }
#else #else
@@ -98,32 +98,32 @@ int prelude_initialize_client(const char *analyzer_name)
ret = prelude_init(0, NULL); ret = prelude_init(0, NULL);
if (ret < 0) { if (ret < 0) {
logg("Unable to initialize the prelude library : %s", prelude_strerror(ret)); logg(LOGG_INFO, "Unable to initialize the prelude library : %s", prelude_strerror(ret));
return -1; return -1;
} }
ret = prelude_client_new(&prelude_client, analyzer_name); ret = prelude_client_new(&prelude_client, analyzer_name);
if (ret < 0) { if (ret < 0) {
logg("Unable to create a prelude client object : %s", prelude_strerror(ret)); logg(LOGG_INFO, "Unable to create a prelude client object : %s", prelude_strerror(ret));
return -1; return -1;
} }
ret = idmef_analyzer_setup(prelude_client_get_analyzer(prelude_client), analyzer_name); ret = idmef_analyzer_setup(prelude_client_get_analyzer(prelude_client), analyzer_name);
if (ret < 0) { if (ret < 0) {
logg("%s", prelude_strerror(ret)); logg(LOGG_INFO, "%s", prelude_strerror(ret));
return -1; return -1;
} }
ret = prelude_client_start(prelude_client); ret = prelude_client_start(prelude_client);
if (ret < 0 || !prelude_client) { if (ret < 0 || !prelude_client) {
logg("Unable to start prelude client : %s", prelude_strerror(ret)); logg(LOGG_INFO, "Unable to start prelude client : %s", prelude_strerror(ret));
prelude_client_destroy(prelude_client, PRELUDE_CLIENT_EXIT_STATUS_SUCCESS); prelude_client_destroy(prelude_client, PRELUDE_CLIENT_EXIT_STATUS_SUCCESS);
return -1; return -1;
} }
ret = prelude_client_set_flags(prelude_client, PRELUDE_CLIENT_FLAGS_ASYNC_SEND | PRELUDE_CLIENT_FLAGS_ASYNC_TIMER); ret = prelude_client_set_flags(prelude_client, PRELUDE_CLIENT_FLAGS_ASYNC_SEND | PRELUDE_CLIENT_FLAGS_ASYNC_TIMER);
if (ret < 0) { if (ret < 0) {
logg("Unable to send asynchronous send and timer : %s", prelude_strerror(ret)); logg(LOGG_INFO, "Unable to send asynchronous send and timer : %s", prelude_strerror(ret));
prelude_client_destroy(prelude_client, PRELUDE_CLIENT_EXIT_STATUS_SUCCESS); prelude_client_destroy(prelude_client, PRELUDE_CLIENT_EXIT_STATUS_SUCCESS);
return -1; return -1;
} }
@@ -242,7 +242,7 @@ void prelude_logging(const char *filename, const char *virname, const char *virh
if (ret < 0) if (ret < 0)
goto err; goto err;
logg("le client : %s", prelude_client_get_config_filename(prelude_client)); logg(LOGG_INFO, "le client : %s", prelude_client_get_config_filename(prelude_client));
prelude_client_send_idmef(prelude_client, idmef); prelude_client_send_idmef(prelude_client, idmef);
idmef_message_destroy(idmef); idmef_message_destroy(idmef);
@@ -252,7 +252,7 @@ err:
if (idmef != NULL) if (idmef != NULL)
idmef_message_destroy(idmef); idmef_message_destroy(idmef);
logg("%s error: %s", prelude_strsource(ret), prelude_strerror(ret)); logg(LOGG_INFO, "%s error: %s", prelude_strsource(ret), prelude_strerror(ret));
return; return;
} }
#endif #endif

View File

@@ -55,14 +55,14 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
do { do {
store = cert_store_get_int(); store = cert_store_get_int();
if (!store) { if (!store) {
mprintf("!Failed to retrieve cert store\n"); mprintf(LOGG_ERROR, "Failed to retrieve cert store\n");
break; break;
} }
pt_err = pthread_mutex_lock(&store->mutex); pt_err = pthread_mutex_lock(&store->mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex lock failed\n"); mprintf(LOGG_ERROR, "Mutex lock failed\n");
} }
if (store->loaded) { if (store->loaded) {
@@ -77,10 +77,10 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
if (trusted_certs && trusted_cert_count > 0) { if (trusted_certs && trusted_cert_count > 0) {
if (cert_store_set_trusted_int(trusted_certs, trusted_cert_count) == 0) { if (cert_store_set_trusted_int(trusted_certs, trusted_cert_count) == 0) {
mprintf("*Trusted certificates loaded: %zu\n", mprintf(LOGG_DEBUG, "Trusted certificates loaded: %zu\n",
store->trusted_certs.count); store->trusted_certs.count);
} else { } else {
mprintf("^Continuing without trusted certificates\n"); mprintf(LOGG_WARNING, "Continuing without trusted certificates\n");
/* proceed as if we succeeded using only certificates from the /* proceed as if we succeeded using only certificates from the
* system */ * system */
} }
@@ -94,7 +94,7 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
pt_err = pthread_mutex_unlock(&store->mutex); pt_err = pthread_mutex_unlock(&store->mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex unlock failed\n"); mprintf(LOGG_ERROR, "Mutex unlock failed\n");
} }
} }

View File

@@ -130,7 +130,7 @@ static CFTypeRef _get_cert_ref(keychain_type_t keychain_type)
status = SecKeychainOpen(kc_info.file_path, &keychain); status = SecKeychainOpen(kc_info.file_path, &keychain);
if (status != errSecSuccess) { if (status != errSecSuccess) {
mprintf("!Failed to open %s keychain: %s (%d)\n", mprintf(LOGG_ERROR, "Failed to open %s keychain: %s (%d)\n",
kc_info.name, kc_info.name,
kc_info.file_path, kc_info.file_path,
status); status);
@@ -139,13 +139,13 @@ static CFTypeRef _get_cert_ref(keychain_type_t keychain_type)
status = SecKeychainGetStatus(keychain, &keychainStatus); status = SecKeychainGetStatus(keychain, &keychainStatus);
if (status != errSecSuccess) { if (status != errSecSuccess) {
mprintf("!Failed to get the status of the %s keychain: %d\n", mprintf(LOGG_ERROR, "Failed to get the status of the %s keychain: %d\n",
kc_info.name, kc_info.name,
status); status);
goto done; goto done;
} }
if (!(keychainStatus & kSecReadPermStatus)) { if (!(keychainStatus & kSecReadPermStatus)) {
mprintf("!The %s keychain is not readable: %" PRIu32 "\n", mprintf(LOGG_ERROR, "The %s keychain is not readable: %" PRIu32 "\n",
kc_info.name, kc_info.name,
keychainStatus); keychainStatus);
goto done; goto done;
@@ -158,7 +158,7 @@ static CFTypeRef _get_cert_ref(keychain_type_t keychain_type)
* has been tampered with. * has been tampered with.
*/ */
if (keychainStatus & (kSecUnlockStateStatus | kSecWritePermStatus)) { if (keychainStatus & (kSecUnlockStateStatus | kSecWritePermStatus)) {
mprintf("!System Root Certificates Keychain has invalid permissions: %" PRIu32 "\n", mprintf(LOGG_ERROR, "System Root Certificates Keychain has invalid permissions: %" PRIu32 "\n",
keychainStatus); keychainStatus);
/* continue on error */ /* continue on error */
} }
@@ -167,7 +167,7 @@ static CFTypeRef _get_cert_ref(keychain_type_t keychain_type)
search_list = CFArrayCreate(kCFAllocatorDefault, search_list = CFArrayCreate(kCFAllocatorDefault,
(const void **)&keychain, 1, &kCFTypeArrayCallBacks); (const void **)&keychain, 1, &kCFTypeArrayCallBacks);
if (search_list == NULL) { if (search_list == NULL) {
mprintf("!Failed to create %s keychain search list\n", mprintf(LOGG_ERROR, "Failed to create %s keychain search list\n",
kc_info.name); kc_info.name);
goto done; goto done;
} }
@@ -179,7 +179,7 @@ static CFTypeRef _get_cert_ref(keychain_type_t keychain_type)
&kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (query == NULL) { if (query == NULL) {
mprintf("!Failed to create %s keychain query dictionary\n", mprintf(LOGG_ERROR, "Failed to create %s keychain query dictionary\n",
kc_info.name); kc_info.name);
goto done; goto done;
} }
@@ -187,10 +187,10 @@ static CFTypeRef _get_cert_ref(keychain_type_t keychain_type)
status = SecItemCopyMatching(query, &items); status = SecItemCopyMatching(query, &items);
if (status != errSecSuccess) { if (status != errSecSuccess) {
if (status == errSecItemNotFound) { if (status == errSecItemNotFound) {
mprintf("*No items found in %s keychain\n", mprintf(LOGG_DEBUG, "No items found in %s keychain\n",
kc_info.name); kc_info.name);
} else { } else {
mprintf("!Unable to copy certificates from %s keychain (%d)\n", mprintf(LOGG_ERROR, "Unable to copy certificates from %s keychain (%d)\n",
kc_info.name, kc_info.name,
status); status);
} }
@@ -239,7 +239,7 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
store = cert_store_get_int(); store = cert_store_get_int();
if (!store) { if (!store) {
mprintf("!Failed to retrieve cert store\n"); mprintf(LOGG_ERROR, "Failed to retrieve cert store\n");
goto done; goto done;
} }
@@ -259,7 +259,7 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
} }
if (CFGetTypeID(items) != CFArrayGetTypeID()) { if (CFGetTypeID(items) != CFArrayGetTypeID()) {
mprintf("!Expected array of certificates from %s keychain, " mprintf(LOGG_ERROR, "Expected array of certificates from %s keychain, "
"got type %lu\n", "got type %lu\n",
kc_info.name, kc_info.name,
CFGetTypeID(items)); CFGetTypeID(items));
@@ -275,7 +275,7 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
kc_data->certs = (CFArrayRef)items; kc_data->certs = (CFArrayRef)items;
kc_data->certs_count = CFArrayGetCount(items); kc_data->certs_count = CFArrayGetCount(items);
mprintf("*Found %ld certificates from %s keychain\n", mprintf(LOGG_DEBUG, "Found %ld certificates from %s keychain\n",
kc_data->certs_count, kc_data->certs_count,
kc_info.name); kc_info.name);
@@ -283,7 +283,7 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
} }
if (total_certificates < 1) { if (total_certificates < 1) {
mprintf("!No certificate found in keychains. Expect at least one " mprintf(LOGG_ERROR, "No certificate found in keychains. Expect at least one "
"certificate to be found in system root and system " "certificate to be found in system root and system "
"keychains\n"); "keychains\n");
goto done; goto done;
@@ -291,19 +291,19 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
store = cert_store_get_int(); store = cert_store_get_int();
if (!store) { if (!store) {
mprintf("!Failed to retrieve cert store\n"); mprintf(LOGG_ERROR, "Failed to retrieve cert store\n");
goto done; goto done;
} }
pt_err = pthread_mutex_lock(&store->mutex); pt_err = pthread_mutex_lock(&store->mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex lock failed\n"); mprintf(LOGG_ERROR, "Mutex lock failed\n");
} }
locked = true; locked = true;
if (store->loaded) { if (store->loaded) {
mprintf("*Cert store already loaded\n"); mprintf(LOGG_DEBUG, "Cert store already loaded\n");
ret = CL_SUCCESS; ret = CL_SUCCESS;
goto done; goto done;
} }
@@ -312,7 +312,7 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
store->system_certs.certificates = calloc(total_certificates, store->system_certs.certificates = calloc(total_certificates,
sizeof(*store->system_certs.certificates)); sizeof(*store->system_certs.certificates));
if (store->system_certs.certificates == NULL) { if (store->system_certs.certificates == NULL) {
mprintf("!Failed to reserve memory for system cert list\n"); mprintf(LOGG_ERROR, "Failed to reserve memory for system cert list\n");
goto done; goto done;
} }
@@ -342,16 +342,19 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
#endif #endif
if (x509) { if (x509) {
mprintf("*Found %s trusted certificate %s\n", mprintf(LOGG_DEBUG, "Found %s trusted certificate %s\n",
kc_info.name, kc_info.name,
(name ? name : "<no name>")); (name ? name : "<no name>"));
store->system_certs.certificates[store->system_certs.count++] = x509; store->system_certs.certificates[store->system_certs.count++] = x509;
} else { } else {
mprintf("!Failed conversion of DER format to X.509\n"); mprintf(LOGG_ERROR, "Failed conversion of DER format to X.509\n");
} }
#if OPENSSL_VERSION_NUMBER >= 0x10100000L #if OPENSSL_VERSION_NUMBER >= 0x10100000L
if (NULL != name) {
free(name); free(name);
name = NULL;
}
#endif #endif
CFRelease(cert_data); CFRelease(cert_data);
@@ -363,10 +366,10 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
if (trusted_certs && trusted_cert_count > 0) { if (trusted_certs && trusted_cert_count > 0) {
if (cert_store_set_trusted_int(trusted_certs, trusted_cert_count) == 0) { if (cert_store_set_trusted_int(trusted_certs, trusted_cert_count) == 0) {
mprintf("*Trusted certificates loaded: %zu\n", mprintf(LOGG_DEBUG, "Trusted certificates loaded: %zu\n",
store->trusted_certs.count); store->trusted_certs.count);
} else { } else {
mprintf("^Continuing without trusted certificates\n"); mprintf(LOGG_WARNING, "Continuing without trusted certificates\n");
/* proceed as if we succeeded using only certificates from the /* proceed as if we succeeded using only certificates from the
* system */ * system */
} }
@@ -380,7 +383,7 @@ done:
pt_err = pthread_mutex_unlock(&store->mutex); pt_err = pthread_mutex_unlock(&store->mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex unlock failed\n"); mprintf(LOGG_ERROR, "Mutex unlock failed\n");
} }
locked = false; locked = false;
} }

View File

@@ -385,7 +385,7 @@ int drop_privileges(const char *const user_name, const char *const log_file)
struct passwd *user = NULL; struct passwd *user = NULL;
if ((user = getpwnam(user_name)) == NULL) { if ((user = getpwnam(user_name)) == NULL) {
logg("^Can't get information about user %s.\n", user_name); logg(LOGG_WARNING, "Can't get information about user %s.\n", user_name);
fprintf(stderr, "ERROR: Can't get information about user %s.\n", user_name); fprintf(stderr, "ERROR: Can't get information about user %s.\n", user_name);
goto done; goto done;
} }
@@ -393,13 +393,13 @@ int drop_privileges(const char *const user_name, const char *const log_file)
#ifdef HAVE_INITGROUPS #ifdef HAVE_INITGROUPS
if (initgroups(user_name, user->pw_gid)) { if (initgroups(user_name, user->pw_gid)) {
fprintf(stderr, "ERROR: initgroups() failed.\n"); fprintf(stderr, "ERROR: initgroups() failed.\n");
logg("^initgroups() failed.\n"); logg(LOGG_WARNING, "initgroups() failed.\n");
goto done; goto done;
} }
#elif HAVE_SETGROUPS #elif HAVE_SETGROUPS
if (setgroups(1, &user->pw_gid)) { if (setgroups(1, &user->pw_gid)) {
fprintf(stderr, "ERROR: setgroups() failed.\n"); fprintf(stderr, "ERROR: setgroups() failed.\n");
logg("^setgroups() failed.\n"); logg(LOGG_WARNING, "setgroups() failed.\n");
goto done; goto done;
} }
#endif #endif
@@ -411,7 +411,7 @@ int drop_privileges(const char *const user_name, const char *const log_file)
fprintf(stderr, "ERROR: lchown to user '%s' failed on\n", user->pw_name); fprintf(stderr, "ERROR: lchown to user '%s' failed on\n", user->pw_name);
fprintf(stderr, "log file '%s'.\n", log_file); fprintf(stderr, "log file '%s'.\n", log_file);
fprintf(stderr, "Error was '%s'\n", strerror(errno)); fprintf(stderr, "Error was '%s'\n", strerror(errno));
logg("^lchown to user '%s' failed on log file '%s'. Error was '%s'\n", logg(LOGG_WARNING, "lchown to user '%s' failed on log file '%s'. Error was '%s'\n",
user->pw_name, log_file, strerror(errno)); user->pw_name, log_file, strerror(errno));
goto done; goto done;
} }
@@ -419,13 +419,13 @@ int drop_privileges(const char *const user_name, const char *const log_file)
if (setgid(user->pw_gid)) { if (setgid(user->pw_gid)) {
fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int)user->pw_gid); fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int)user->pw_gid);
logg("^setgid(%d) failed.\n", (int)user->pw_gid); logg(LOGG_WARNING, "setgid(%d) failed.\n", (int)user->pw_gid);
goto done; goto done;
} }
if (setuid(user->pw_uid)) { if (setuid(user->pw_uid)) {
fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int)user->pw_uid); fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int)user->pw_uid);
logg("^setuid(%d) failed.\n", (int)user->pw_uid); logg(LOGG_WARNING, "setuid(%d) failed.\n", (int)user->pw_uid);
goto done; goto done;
} }
} }

View File

@@ -72,7 +72,7 @@ int daemonize(void);
/*closes stdin, stdout, stderr. This is called by daemonize, but not /*closes stdin, stdout, stderr. This is called by daemonize, but not
* daemonize_all_return. Users of daemonize_all_return should call this * daemonize_all_return. Users of daemonize_all_return should call this
* when initialization is complete.*/ * when initialization is complete.*/
int close_std_descriptors(); int close_std_descriptors(void);
/*Returns the return value of fork. All processes return */ /*Returns the return value of fork. All processes return */
int daemonize_all_return(void); int daemonize_all_return(void);

View File

@@ -158,6 +158,7 @@ const struct clam_option __clam_options[] = {
{NULL, "sha256", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", ""}, {NULL, "sha256", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", ""},
{NULL, "mdb", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", ""}, {NULL, "mdb", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", ""},
{NULL, "imp", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", ""}, {NULL, "imp", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", ""},
{NULL, "fuzzy-img", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", ""},
{NULL, "print-certs", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", ""}, {NULL, "print-certs", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", ""},
{NULL, "html-normalise", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", ""}, {NULL, "html-normalise", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", ""},
{NULL, "ascii-normalise", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", ""}, {NULL, "ascii-normalise", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", ""},
@@ -200,6 +201,13 @@ const struct clam_option __clam_options[] = {
{NULL, "archive-verbose", 'a', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", ""}, {NULL, "archive-verbose", 'a', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", ""},
#ifdef _WIN32
{NULL, "install-service", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM, "", ""},
{NULL, "uninstall-service", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM, "", ""},
{NULL, "daemon", 'd', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "", ""},
{NULL, "service-mode", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM, "", ""},
#endif
/* cmdline only - deprecated */ /* cmdline only - deprecated */
{NULL, "bytecode-trust-all", 't', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", ""}, {NULL, "bytecode-trust-all", 't', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", ""},
{NULL, "http-proxy", 0, CLOPT_TYPE_STRING, NULL, 0, NULL, 0, OPT_FRESHCLAM | OPT_DEPRECATED, "", ""}, {NULL, "http-proxy", 0, CLOPT_TYPE_STRING, NULL, 0, NULL, 0, OPT_FRESHCLAM | OPT_DEPRECATED, "", ""},
@@ -231,6 +239,12 @@ const struct clam_option __clam_options[] = {
{NULL, "tgz", 0, CLOPT_TYPE_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", ""}, {NULL, "tgz", 0, CLOPT_TYPE_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", ""},
{NULL, "deb", 0, CLOPT_TYPE_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", ""}, {NULL, "deb", 0, CLOPT_TYPE_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", ""},
#ifdef _WIN32
{NULL, "memory", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", ""},
{NULL, "kill", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", ""},
{NULL, "unload", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", ""},
#endif
/* config file/cmdline options */ /* config file/cmdline options */
{"AlertExceedsMax", "alert-exceeds-max", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "", ""}, {"AlertExceedsMax", "alert-exceeds-max", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "", ""},
@@ -283,7 +297,7 @@ const struct clam_option __clam_options[] = {
{"MaxConnectionQueueLength", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 200, NULL, 0, OPT_CLAMD, "Maximum length the queue of pending connections may grow to.", "30"}, {"MaxConnectionQueueLength", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 200, NULL, 0, OPT_CLAMD, "Maximum length the queue of pending connections may grow to.", "30"},
{"StreamMaxLength", NULL, 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXFILESIZE, NULL, 0, OPT_CLAMD, "Close the STREAM session when the data size limit is exceeded.\nThe value should match your MTA's limit for the maximum attachment size.", "25M"}, {"StreamMaxLength", NULL, 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXFILESIZE, NULL, 0, OPT_CLAMD, "Close the STREAM session when the data size limit is exceeded.\nThe value should match your MTA's limit for the maximum attachment size.", "100M"},
{"StreamMinPort", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 1024, NULL, 0, OPT_CLAMD, "The STREAM command uses an FTP-like protocol.\nThis option sets the lower boundary for the port range.", "1024"}, {"StreamMinPort", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 1024, NULL, 0, OPT_CLAMD, "The STREAM command uses an FTP-like protocol.\nThis option sets the lower boundary for the port range.", "1024"},
@@ -319,7 +333,7 @@ const struct clam_option __clam_options[] = {
{"DisableCache", "disable-cache", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option allows you to disable clamd's caching feature.", "no"}, {"DisableCache", "disable-cache", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option allows you to disable clamd's caching feature.", "no"},
{"VirusEvent", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD, "Execute a command when a virus is found. In the command string %v will be\nreplaced with the virus name. Additionally, two environment variables will\nbe defined: $CLAM_VIRUSEVENT_FILENAME and $CLAM_VIRUSEVENT_VIRUSNAME.", "/usr/bin/mailx -s \"ClamAV VIRUS ALERT: %v\" alert < /dev/null"}, {"VirusEvent", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD, "Execute a command when a virus is found. In the command string %v will be\nreplaced with the virus name and %f will be replaced with the file name.\nAdditionally, two environment variables will be defined: $CLAM_VIRUSEVENT_FILENAME\nand $CLAM_VIRUSEVENT_VIRUSNAME.", "/usr/bin/mailx -s \"ClamAV VIRUS ALERT: %v\" alert < /dev/null"},
{"ExitOnOOM", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Stop the daemon when libclamav reports an out of memory condition.", "yes"}, {"ExitOnOOM", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Stop the daemon when libclamav reports an out of memory condition.", "yes"},
@@ -331,6 +345,8 @@ const struct clam_option __clam_options[] = {
{"LeaveTemporaryFiles", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Don't remove temporary files (for debugging purposes).", "no"}, {"LeaveTemporaryFiles", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Don't remove temporary files (for debugging purposes).", "no"},
{"GenerateMetadataJson", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Record metadata about the file being scanned.\nScan metadata is useful for file analysis purposes and for debugging scan behavior.\nThe JSON metadata will be printed after the scan is complete if Debug is enabled.\nA metadata.json file will be written to the scan temp directory if LeaveTemporaryFiles is enabled.", "no"},
{"User", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD | OPT_MILTER, "Run the daemon as a specified user (the process must be started by root).", "clamav"}, {"User", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD | OPT_MILTER, "Run the daemon as a specified user (the process must be started by root).", "clamav"},
/* Scan options */ /* Scan options */
@@ -420,22 +436,22 @@ const struct clam_option __clam_options[] = {
{"MaxScanTime", "max-scantime", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum amount of time a scan may take to complete.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result allow scanning\nof certain files to lock up the scanning process/threads resulting in a Denial of Service.\nThe value is in milliseconds.", "120000"}, {"MaxScanTime", "max-scantime", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum amount of time a scan may take to complete.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result allow scanning\nof certain files to lock up the scanning process/threads resulting in a Denial of Service.\nThe value is in milliseconds.", "120000"},
{"MaxScanSize", "max-scansize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXSCANSIZE, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum amount of data to be scanned for each input file.\nArchives and other containers are recursively extracted and scanned up to this\nvalue.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe\ndamage.", "100M"}, {"MaxScanSize", "max-scansize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXSCANSIZE, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum amount of data to be scanned for each input file.\nArchives and other containers are recursively extracted and scanned up to this\nvalue.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe\ndamage.", "400M"},
{"MaxFileSize", "max-filesize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXFILESIZE, NULL, 0, OPT_CLAMD | OPT_MILTER | OPT_CLAMSCAN, "Files/messages larger than this limit won't be scanned. Affects the input\nfile itself as well as files contained inside it (when the input file is\nan archive, a document or some other kind of container).\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe\ndamage to the system.", "25M"}, {"MaxFileSize", "max-filesize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXFILESIZE, NULL, 0, OPT_CLAMD | OPT_MILTER | OPT_CLAMSCAN, "Files/messages larger than this limit won't be scanned. Affects the input\nfile itself as well as files contained inside it (when the input file is\nan archive, a document or some other kind of container).\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe\ndamage to the system.", "100M"},
{"MaxRecursion", "max-recursion", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_MAXRECLEVEL, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Nested archives are scanned recursively, e.g. if a Zip archive contains a RAR\nfile, all files within it will also be scanned. This option specifies how\ndeeply the process should be continued.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe\ndamage to the system.", "17"}, {"MaxRecursion", "max-recursion", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_MAXRECLEVEL, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Nested archives are scanned recursively, e.g. if a Zip archive contains a RAR\nfile, all files within it will also be scanned. This option specifies how\ndeeply the process should be continued.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe\ndamage to the system.", "17"},
{"MaxFiles", "max-files", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_MAXFILES, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Number of files to be scanned within an archive, a document, or any other\ncontainer file.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe\ndamage to the system.", "10000"}, {"MaxFiles", "max-files", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_MAXFILES, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Number of files to be scanned within an archive, a document, or any other\ncontainer file.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe\ndamage to the system.", "10000"},
/* Engine maximums */ /* Engine maximums */
{"MaxEmbeddedPE", "max-embeddedpe", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXEMBEDDEDPE, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum size of a file to check for embedded PE.\nFiles larger than this value will skip the additional analysis step.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "10M"}, {"MaxEmbeddedPE", "max-embeddedpe", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXEMBEDDEDPE, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum size of a file to check for embedded PE.\nFiles larger than this value will skip the additional analysis step.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "40M"},
{"MaxHTMLNormalize", "max-htmlnormalize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXHTMLNORMALIZE, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum size of a HTML file to normalize.\nHTML files larger than this value will not be normalized or scanned.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "10M"}, {"MaxHTMLNormalize", "max-htmlnormalize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXHTMLNORMALIZE, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum size of a HTML file to normalize.\nHTML files larger than this value will not be normalized or scanned.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "40M"},
{"MaxHTMLNoTags", "max-htmlnotags", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXHTMLNOTAGS, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum size of a normalized HTML file to scan.\nHTML files larger than this value after normalization will not be scanned.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "2M"}, {"MaxHTMLNoTags", "max-htmlnotags", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXHTMLNOTAGS, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum size of a normalized HTML file to scan.\nHTML files larger than this value after normalization will not be scanned.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "8M"},
{"MaxScriptNormalize", "max-scriptnormalize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXSCRIPTNORMALIZE, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum size of a script file to normalize.\nScript content larger than this value will not be normalized or scanned.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "5M"}, {"MaxScriptNormalize", "max-scriptnormalize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXSCRIPTNORMALIZE, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum size of a script file to normalize.\nScript content larger than this value will not be normalized or scanned.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "20M"},
{"MaxZipTypeRcg", "max-ziptypercg", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXZIPTYPERCG, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum size of a ZIP file to reanalyze type recognition.\nZIP files larger than this value will skip the step to potentially reanalyze as PE.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "1M"}, {"MaxZipTypeRcg", "max-ziptypercg", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXZIPTYPERCG, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum size of a ZIP file to reanalyze type recognition.\nZIP files larger than this value will skip the step to potentially reanalyze as PE.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "1M"},
@@ -449,7 +465,7 @@ const struct clam_option __clam_options[] = {
{"PCRERecMatchLimit", "pcre-recmatch-limit", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_PCRE_RECMATCH_LIMIT, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum recursive calls to the PCRE match function during an instance of regex matching.\nInstances using more than this limit will be terminated and alert the user but the scan will continue.\nFor more information on match_limit_recursion, see the PCRE documentation.\nNegative values are not allowed and values > PCREMatchLimit are superfluous.\nWARNING: setting this limit too high may severely impact performance.", "5000"}, {"PCRERecMatchLimit", "pcre-recmatch-limit", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_PCRE_RECMATCH_LIMIT, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum recursive calls to the PCRE match function during an instance of regex matching.\nInstances using more than this limit will be terminated and alert the user but the scan will continue.\nFor more information on match_limit_recursion, see the PCRE documentation.\nNegative values are not allowed and values > PCREMatchLimit are superfluous.\nWARNING: setting this limit too high may severely impact performance.", "5000"},
{"PCREMaxFileSize", "pcre-max-filesize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_PCRE_MAX_FILESIZE, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum filesize for which PCRE subsigs will be executed.\nFiles exceeding this limit will not have PCRE subsigs executed unless a subsig is encompassed to a smaller buffer.\nNegative values are not allowed.\nSetting this value to zero disables the limit.\nWARNING: setting this limit too high or disabling it may severely impact performance.", "25M"}, {"PCREMaxFileSize", "pcre-max-filesize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_PCRE_MAX_FILESIZE, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum filesize for which PCRE subsigs will be executed.\nFiles exceeding this limit will not have PCRE subsigs executed unless a subsig is encompassed to a smaller buffer.\nNegative values are not allowed.\nSetting this value to zero disables the limit.\nWARNING: setting this limit too high or disabling it may severely impact performance.", "100M"},
/* OnAccess settings */ /* OnAccess settings */
{"OnAccessMountPath", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option specifies a directory or mount point which should be scanned on access. The mount point specified, or the mount point containing the specified directory will be watched, but only notifications will occur. If any directories are specified, this option will preempt the DDD system. It can also be used multiple times.", "/\n/home/user"}, {"OnAccessMountPath", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option specifies a directory or mount point which should be scanned on access. The mount point specified, or the mount point containing the specified directory will be watched, but only notifications will occur. If any directories are specified, this option will preempt the DDD system. It can also be used multiple times.", "/\n/home/user"},
@@ -458,9 +474,9 @@ const struct clam_option __clam_options[] = {
{"OnAccessExcludePath", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option allows excluding directories from on-access scanning. It can\nbe used multiple times. Only works with DDD system.", "/home/bofh\n/root"}, {"OnAccessExcludePath", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option allows excluding directories from on-access scanning. It can\nbe used multiple times. Only works with DDD system.", "/home/bofh\n/root"},
{"OnAccessExcludeRootUID", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD, "Use this option to whitelist the root UID (0) and allow any processes run under root to access all watched files without triggering scans.", "no"}, {"OnAccessExcludeRootUID", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD, "Use this option to exclude the root UID (0) and allow any processes run under root to access all watched files without triggering scans.", "no"},
{"OnAccessExcludeUID", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "With this option you can whitelist specific UIDs. Processes with these UIDs\nwill be able to access all files.\nThis option can be used multiple times (one per line). Using a value of 0 on any line will disable this option entirely. To whitelist the root UID please enable the OnAccessExcludeRootUID option.", "0"}, {"OnAccessExcludeUID", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "With this option you can exclude specific UIDs. Processes with these UIDs\nwill be able to access all files.\nThis option can be used multiple times (one per line). Using a value of 0 on any line will disable this option entirely. To exclude the root UID please enable the OnAccessExcludeRootUID option.", "0"},
{"OnAccessExcludeUname", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option allows exclusions via user names when using the on-access scanning client. It can\nbe used multiple times.", "clamuser"}, {"OnAccessExcludeUname", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option allows exclusions via user names when using the on-access scanning client. It can\nbe used multiple times.", "clamuser"},
@@ -548,7 +564,7 @@ const struct clam_option __clam_options[] = {
{"ConnectTimeout", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 30, NULL, 0, OPT_FRESHCLAM, "Timeout in seconds when connecting to database server.", "30"}, {"ConnectTimeout", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 30, NULL, 0, OPT_FRESHCLAM, "Timeout in seconds when connecting to database server.", "30"},
{"ReceiveTimeout", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 0, NULL, 0, OPT_FRESHCLAM, "Maximum time in seconds for each download operation. 0 means no timeout.", "0"}, {"ReceiveTimeout", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 60, NULL, 0, OPT_FRESHCLAM, "Timeout in seconds when reading from database server. 0 means no timeout.", "60"},
{"Bytecode", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_FRESHCLAM, "This option enables downloading of bytecode.cvd, which includes additional\ndetection mechanisms and improvements to the ClamAV engine.", "yes"}, {"Bytecode", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_FRESHCLAM, "This option enables downloading of bytecode.cvd, which includes additional\ndetection mechanisms and improvements to the ClamAV engine.", "yes"},
@@ -605,7 +621,9 @@ const struct clam_option __clam_options[] = {
{"Chroot", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "Chroot to the specified directory.\nChrooting is performed just after reading the config file and before\ndropping privileges.", "/newroot"}, {"Chroot", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "Chroot to the specified directory.\nChrooting is performed just after reading the config file and before\ndropping privileges.", "/newroot"},
{"Whitelist", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "This option specifies a file which contains a list of basic POSIX regular\nexpressions. Addresses (sent to or from - see below) matching these regexes\nwill not be scanned. Optionally each line can start with the string \"From:\"\nor \"To:\" (note: no whitespace after the colon) indicating if it is,\nrespectively, the sender or recipient that is to be whitelisted.\nIf the field is missing, \"To:\" is assumed.\nLines starting with #, : or ! are ignored.", "/etc/whitelisted_addresses"}, {"AllowList", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "This option specifies a file which contains a list of basic POSIX regular\nexpressions. Addresses (sent to or from - see below) matching these regexes\nwill not be scanned. Optionally each line can start with the string \"From:\"\nor \"To:\" (note: no whitespace after the colon) indicating if it is,\nrespectively, the sender or recipient that is to be allowed.\nIf the field is missing, \"To:\" is assumed.\nLines starting with #, : or ! are ignored.", "/etc/allowed_addresses"},
// The Whitelist option should remain functional for a version or two, but has been deprecated in the documentation in favor of "AllowList".
{"Whitelist", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "This option specifies a file which contains a list of basic POSIX regular\nexpressions. Addresses (sent to or from - see below) matching these regexes\nwill not be scanned. Optionally each line can start with the string \"From:\"\nor \"To:\" (note: no whitespace after the colon) indicating if it is,\nrespectively, the sender or recipient that is to be allowed.\nIf the field is missing, \"To:\" is assumed.\nLines starting with #, : or ! are ignored.", "/etc/allowed_addresses"},
{"SkipAuthenticated", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "Messages from authenticated SMTP users matching this extended POSIX\nregular expression (egrep-like) will not be scanned.\nAs an alternative, a file containing a plain (not regex) list of names (one\nper line) can be specified using the prefix \"file:\".\ne.g. SkipAuthenticated file:/etc/good_guys\n\nNote: this is the AUTH login name!", "SkipAuthenticated ^(tom|dick|henry)$"}, {"SkipAuthenticated", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "Messages from authenticated SMTP users matching this extended POSIX\nregular expression (egrep-like) will not be scanned.\nAs an alternative, a file containing a plain (not regex) list of names (one\nper line) can be specified using the prefix \"file:\".\ne.g. SkipAuthenticated file:/etc/good_guys\n\nNote: this is the AUTH login name!", "SkipAuthenticated ^(tom|dick|henry)$"},

View File

@@ -298,26 +298,7 @@ void logg_close(void)
#endif #endif
} }
/* int logg(loglevel_t loglevel, const char *str, ...)
* legend:
* ! - ERROR:
* ^ - WARNING:
* ~ - normal
* # - normal, not foreground (logfile and syslog only)
* * - verbose
* $ - debug
* none - normal
*
* Default Foreground LogVerbose Debug Syslog
* ! yes mprintf yes yes LOG_ERR
* ^ yes mprintf yes yes LOG_WARNING
* ~ yes mprintf yes yes LOG_INFO
* # yes no yes yes LOG_INFO
* * no mprintf yes yes LOG_DEBUG
* $ no mprintf no yes LOG_DEBUG
* none yes mprintf yes yes LOG_INFO
*/
int logg(const char *str, ...)
{ {
va_list args; va_list args;
char buffer[1025], *abuffer = NULL, *buff; char buffer[1025], *abuffer = NULL, *buff;
@@ -328,8 +309,8 @@ int logg(const char *str, ...)
struct flock fl; struct flock fl;
#endif #endif
if ((*str == '$' && logg_verbose < 2) || if ((loglevel == LOGG_DEBUG_NV && logg_verbose < 2) ||
(*str == '*' && !logg_verbose)) (loglevel == LOGG_DEBUG && !logg_verbose))
return 0; return 0;
ARGLEN(args, str, len); ARGLEN(args, str, len);
@@ -399,7 +380,7 @@ int logg(const char *str, ...)
/* Need to avoid logging time for verbose messages when logverbose /* Need to avoid logging time for verbose messages when logverbose
is not set or we get a bunch of timestamps in the log without is not set or we get a bunch of timestamps in the log without
newlines... */ newlines... */
if (logg_time && ((*buff != '*') || logg_verbose)) { if (logg_time && ((loglevel != LOGG_DEBUG) || logg_verbose)) {
char timestr[32]; char timestr[32];
time(&currtime); time(&currtime);
cli_ctime(&currtime, timestr, sizeof(timestr)); cli_ctime(&currtime, timestr, sizeof(timestr));
@@ -408,17 +389,17 @@ int logg(const char *str, ...)
fprintf(logg_fp, "%s -> ", timestr); fprintf(logg_fp, "%s -> ", timestr);
} }
if (*buff == '!') { if (loglevel == LOGG_ERROR) {
fprintf(logg_fp, "ERROR: %s", buff + 1); fprintf(logg_fp, "ERROR: %s", buff);
flush = 1; flush = 1;
} else if (*buff == '^') { } else if (loglevel == LOGG_WARNING) {
if (!logg_nowarn) if (!logg_nowarn)
fprintf(logg_fp, "WARNING: %s", buff + 1); fprintf(logg_fp, "WARNING: %s", buff);
flush = 1; flush = 1;
} else if (*buff == '*' || *buff == '$') { } else if (loglevel == LOGG_DEBUG || loglevel == LOGG_DEBUG_NV) {
fprintf(logg_fp, "%s", buff + 1); fprintf(logg_fp, "%s", buff);
} else if (*buff == '#' || *buff == '~') { } else if (loglevel == LOGG_INFO_NF || loglevel == LOGG_INFO) {
fprintf(logg_fp, "%s", buff + 1); fprintf(logg_fp, "%s", buff);
} else } else
fprintf(logg_fp, "%s", buff); fprintf(logg_fp, "%s", buff);
@@ -427,16 +408,16 @@ int logg(const char *str, ...)
} }
if (logg_foreground) { if (logg_foreground) {
if (buff[0] != '#') { if (loglevel != LOGG_INFO_NF) {
if (logg_time) { if (logg_time) {
char timestr[32]; char timestr[32];
time(&currtime); time(&currtime);
cli_ctime(&currtime, timestr, sizeof(timestr)); cli_ctime(&currtime, timestr, sizeof(timestr));
/* cut trailing \n */ /* cut trailing \n */
timestr[strlen(timestr) - 1] = '\0'; timestr[strlen(timestr) - 1] = '\0';
mprintf("%s -> %s", timestr, buff); mprintf(loglevel, "%s -> %s", timestr, buff);
} else { } else {
mprintf("%s", buff); mprintf(loglevel, "%s", buff);
} }
} }
} }
@@ -444,15 +425,13 @@ int logg(const char *str, ...)
#if defined(USE_SYSLOG) && !defined(C_AIX) #if defined(USE_SYSLOG) && !defined(C_AIX)
if (logg_syslog) { if (logg_syslog) {
cli_chomp(buff); cli_chomp(buff);
if (buff[0] == '!') { if (loglevel == LOGG_ERROR) {
syslog(LOG_ERR, "%s", buff + 1); syslog(LOG_ERR, "%s", buff);
} else if (buff[0] == '^') { } else if (loglevel == LOGG_WARNING) {
if (!logg_nowarn) if (!logg_nowarn)
syslog(LOG_WARNING, "%s", buff + 1); syslog(LOG_WARNING, "%s", buff);
} else if (buff[0] == '*' || buff[0] == '$') { } else if (loglevel == LOGG_DEBUG || loglevel == LOGG_DEBUG_NV) {
syslog(LOG_DEBUG, "%s", buff + 1); syslog(LOG_DEBUG, "%s", buff);
} else if (buff[0] == '#' || buff[0] == '~') {
syslog(LOG_INFO, "%s", buff + 1);
} else } else
syslog(LOG_INFO, "%s", buff); syslog(LOG_INFO, "%s", buff);
} }
@@ -467,7 +446,7 @@ int logg(const char *str, ...)
return 0; return 0;
} }
void mprintf(const char *str, ...) void mprintf(loglevel_t loglevel, const char *str, ...)
{ {
va_list args; va_list args;
FILE *fd; FILE *fd;
@@ -479,21 +458,6 @@ void mprintf(const char *str, ...)
fd = stdout; fd = stdout;
/* legend:
* ! - error
* @ - error with logging
* ...
*/
/*
* ERROR WARNING STANDARD
* normal stderr stderr stdout
*
* verbose stderr stderr stdout
*
* quiet stderr no no
*/
ARGLEN(args, str, len); ARGLEN(args, str, len);
if (len <= sizeof(buffer)) { if (len <= sizeof(buffer)) {
len = sizeof(buffer); len = sizeof(buffer);
@@ -541,26 +505,22 @@ void mprintf(const char *str, ...)
len = sizeof(buffer) + 1; len = sizeof(buffer) + 1;
} while (0); } while (0);
#endif #endif
if (buff[0] == '!') { if (loglevel == LOGG_ERROR) {
if (!mprintf_stdout) if (!mprintf_stdout)
fd = stderr; fd = stderr;
fprintf(fd, "ERROR: %s", &buff[1]); fprintf(fd, "ERROR: %s", buff);
} else if (buff[0] == '@') {
if (!mprintf_stdout)
fd = stderr;
fprintf(fd, "ERROR: %s", &buff[1]);
} else if (!mprintf_quiet) { } else if (!mprintf_quiet) {
if (buff[0] == '^') { if (loglevel == LOGG_WARNING) {
if (!mprintf_nowarn) { if (!mprintf_nowarn) {
if (!mprintf_stdout) if (!mprintf_stdout)
fd = stderr; fd = stderr;
fprintf(fd, "WARNING: %s", &buff[1]); fprintf(fd, "WARNING: %s", buff);
} }
} else if (buff[0] == '*') { } else if (loglevel == LOGG_DEBUG) {
if (mprintf_verbose) if (mprintf_verbose)
fprintf(fd, "%s", &buff[1]); fprintf(fd, "%s", buff);
} else if (buff[0] == '~') { } else if (loglevel == LOGG_INFO) {
fprintf(fd, "%s", &buff[1]); fprintf(fd, "%s", buff);
} else } else
fprintf(fd, "%s", buff); fprintf(fd, "%s", buff);
} }

97
clamav/common/output.h Normal file
View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) 2013-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2007-2013 Sourcefire, Inc.
*
* Authors: Tomasz Kojm
*
* 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 __OUTPUT_H
#define __OUTPUT_H
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef __GNUC__
int mdprintf(int desc, const char *str, ...) __attribute__((format(printf, 2, 3)));
#else
int mdprintf(int desc, const char *str, ...);
#endif
/*
* legend:
* NAME EXPLAIN
* LOGG_INFO normal
* LOGG_INFO_NF normal, no foreground (logfile and syslog only)
* LOGG_DEBUG debug, verbose
* LOGG_DEBUG_NV debug, non-verbose
* LOGG_WARNING warning
* LOGG_ERROR ERROR
*/
typedef enum loglevel {
LOGG_INFO,
LOGG_INFO_NF,
LOGG_DEBUG,
LOGG_DEBUG_NV,
LOGG_WARNING,
LOGG_ERROR
} loglevel_t;
/*
* @param loglevel legend:
* NAME EXPLAIN
* LOGG_INFO normal
* LOGG_INFO_NF normal, no foreground (logfile and syslog only)
* LOGG_DEBUG debug, verbose
* LOGG_DEBUG_NV debug, non-verbose
* LOGG_WARNING warning
* LOGG_ERROR ERROR
*
* @return 0 fur success and -1 for error, e.g. log file access problems
*/
#ifdef __GNUC__
int logg(loglevel_t loglevel, const char *str, ...) __attribute__((format(printf, 2, 3)));
#else
int logg(loglevel_t loglevel, const char *str, ...);
#endif
void logg_close(void);
extern short int logg_verbose, logg_nowarn, logg_lock, logg_time, logg_noflush, logg_rotate;
extern off_t logg_size;
extern const char *logg_file;
#if defined(USE_SYSLOG) && !defined(C_AIX)
extern short logg_syslog;
int logg_facility(const char *name);
#endif
#ifdef __GNUC__
void mprintf(loglevel_t loglevel, const char *str, ...) __attribute__((format(printf, 2, 3)));
#else
void mprintf(loglevel_t loglevel, const char *str, ...);
#endif
extern short int mprintf_disabled, mprintf_verbose, mprintf_quiet, mprintf_nowarn, mprintf_stdout, mprintf_send_timeout, mprintf_progress;
#endif

710
clamav/common/scanmem.c Normal file
View File

@@ -0,0 +1,710 @@
/*
* Copyright (C) 2021-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2005-2010 Gianluigi Tiesi <sherpya@netfarm.it>
*
* Authors: Gianluigi Tiesi
*
* 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 <windows.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <windns.h>
#include <clamav.h>
#include <others.h>
#include "actions.h"
#include "output.h"
#include "clamdcom.h"
#include "exescanner.h"
#include "scanmem.h"
typedef int (*proc_callback)(PROCESSENTRY32 ProcStruct, MODULEENTRY32 me32, void *data, struct mem_info *info);
int sock;
struct optstruct *clamdopts;
static inline int lookup_cache(filelist_t **list, const char *filename)
{
filelist_t *current = *list;
while (current) {
/* Cache hit */
if (!_stricmp(filename, current->filename)) {
return current->res;
}
current = current->next;
}
return -1;
}
static inline void insert_cache(filelist_t **list, const char *filename,
int res)
{
filelist_t *current = *list, *prev = NULL;
if (!current) /* New */
*list = current = malloc(sizeof(filelist_t));
else {
while (current->next)
current = current->next;
prev = current;
prev->next = current = malloc(sizeof(filelist_t));
}
current->next = NULL;
current->res = res;
current->filename[0] = 0;
strncat(current->filename, filename,
MAX_PATH - 1 - strlen(current->filename));
current->filename[MAX_PATH - 1] = 0;
}
static inline void free_cache(filelist_t **list)
{
filelist_t *current, *prev;
current = prev = *list;
if (!current)
return;
do {
prev = current;
current = prev->next;
free(prev);
} while (current);
}
static inline char *wc2mb(const wchar_t *wc, DWORD flags)
{
BOOL invalid = FALSE;
DWORD len = 0, res = 0;
char *mb = NULL;
len = WideCharToMultiByte(CP_ACP, flags, wc, -1, NULL, 0, NULL, &invalid);
if (!len && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
fprintf(stderr, "WideCharToMultiByte() failed with %d\n", GetLastError());
return NULL;
}
mb = cli_malloc(len + 1);
if (!mb) return NULL;
res = WideCharToMultiByte(CP_ACP, flags, wc, -1, mb, len, NULL, &invalid);
if (res && ((!invalid || (flags != WC_NO_BEST_FIT_CHARS)))) return mb;
free(mb);
return NULL;
}
/* Needed to Scan System Processes */
int EnablePrivilege(LPCSTR PrivilegeName, DWORD yesno)
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
LUID luid;
if (!LoadLibraryA("advapi32.dll")) {
logg(LOGG_WARNING, "EnablePrivilege functions are missing\n");
return 0;
}
if (!OpenProcessToken(
GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_READ, &hToken))
return 0;
if (!LookupPrivilegeValue(NULL, PrivilegeName, &luid))
return 0;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = yesno;
AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
CloseHandle(hToken);
return (GetLastError() == ERROR_SUCCESS) ? 1 : 0;
}
static char *getaltpath(const wchar_t *filename)
{
WIN32_FIND_DATAW wfdw;
HANDLE hf = INVALID_HANDLE_VALUE;
wchar_t *part = _wcsdup(filename);
wchar_t comprev[MAX_PATH + 1] = L"", compose[MAX_PATH + 1];
wchar_t *rev = comprev, *slash = part, *c = NULL;
size_t l, la;
size_t i;
do {
if (slash != part)
*slash = 0;
/* c: d: etc */
if ((wcslen(part) == 2) && (part[1] == L':')) {
*rev++ = L':';
*rev++ = part[0];
break;
}
hf = FindFirstFileW(part, &wfdw);
if (hf == INVALID_HANDLE_VALUE) /* Network path */
{
for (i = wcslen(part); i > 0; i--)
*rev++ = part[i - 1];
break;
}
FindClose(hf);
l = wcslen(wfdw.cFileName);
la = wcslen(wfdw.cAlternateFileName);
if (la)
for (i = la; i > 0; i--)
*rev++ = *(wfdw.cAlternateFileName + i - 1);
else
for (i = l; i > 0; i--)
*rev++ = *(wfdw.cFileName + i - 1);
*rev++ = '\\';
} while ((slash = wcsrchr(part, L'\\')));
rev = comprev;
c = compose;
for (i = wcslen(rev); i > 0; i--)
*c++ = *(rev + i - 1);
*c = 0;
free(part);
return wc2mb(compose, WC_NO_BEST_FIT_CHARS);
}
int walkmodules_th(proc_callback callback, void *data, struct mem_info *info)
{
HANDLE hSnap = INVALID_HANDLE_VALUE, hModuleSnap = INVALID_HANDLE_VALUE;
PROCESSENTRY32 ps;
MODULEENTRY32 me32;
logg(LOGG_INFO, " *** Memory Scan: using ToolHelp ***\n\n");
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE)
return -1;
ps.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hSnap, &ps)) {
CloseHandle(hSnap);
return -1;
}
do {
/* system process */
if (!ps.th32ProcessID)
continue;
hModuleSnap = CreateToolhelp32Snapshot(
TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, ps.th32ProcessID);
if (hModuleSnap == INVALID_HANDLE_VALUE)
continue;
me32.dwSize = sizeof(MODULEENTRY32);
if (!Module32First(hModuleSnap, &me32)) {
CloseHandle(hModuleSnap);
continue;
}
/* Check and transform non ANSI filenames to ANSI using altnames */
if (GetModuleFileNameEx) {
HANDLE hFile = CreateFile(
me32.szExePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError();
wchar_t name[MAX_PATH + 1];
char *converted = NULL;
HANDLE p;
if (err == ERROR_BAD_NETPATH) {
logg(LOGG_WARNING, "Warning scanning files on non-ansi network paths is not "
"supported\n");
logg(LOGG_WARNING, "File: %s\n", me32.szExePath);
continue;
}
if ((err != ERROR_INVALID_NAME) && (err != ERROR_PATH_NOT_FOUND)) {
logg(LOGG_WARNING, "Expected ERROR_INVALID_NAME/ERROR_PATH_NOT_FOUND but got %d\n",
err);
continue;
}
p = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE,
ps.th32ProcessID);
if (!GetModuleFileNameEx(p, NULL, name, MAX_PATH)) {
logg(LOGG_WARNING, "GetModuleFileNameExW() failed %d\n", GetLastError());
CloseHandle(p);
continue;
}
CloseHandle(p);
if (!(converted = getaltpath(name))) {
logg(LOGG_WARNING, "Cannot map filename to ANSI codepage\n");
continue;
}
strcpy(me32.szExePath, converted);
free(converted);
} else
CloseHandle(hFile);
}
do
if (callback(ps, me32, data, info))
break;
while (Module32Next(hModuleSnap, &me32));
CloseHandle(hModuleSnap);
} while (Process32Next(hSnap, &ps));
CloseHandle(hSnap);
return 0;
}
int walkmodules_psapi(proc_callback callback, void *data, struct mem_info *info)
{
DWORD procs[1024], needed, nprocs, mneeded;
HANDLE hProc;
HMODULE mods[1024];
PROCESSENTRY32 ps;
MODULEENTRY32 me32;
MODULEINFO mi;
int i, j;
logg(LOGG_INFO, " *** Memory Scan: using PsApi ***\n\n");
if (!EnumProcesses(procs, sizeof(procs), &needed))
return -1;
nprocs = needed / sizeof(DWORD);
memset(&ps, 0, sizeof(PROCESSENTRY32));
memset(&me32, 0, sizeof(MODULEENTRY32));
ps.dwSize = sizeof(PROCESSENTRY32);
me32.dwSize = sizeof(MODULEENTRY32);
for (i = 0; i < nprocs; i++) {
if (!procs[i])
continue; /* System process */
hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE,
procs[i]);
if (!hProc)
continue;
if (!EnumProcessModules(hProc, mods, sizeof(mods),
&mneeded)) {
CloseHandle(hProc);
continue;
}
if (!GetModuleBaseName(hProc, mods[0], ps.szExeFile,
MAX_PATH - 1)) {
CloseHandle(hProc);
continue;
}
ps.th32ProcessID = procs[i];
for (j = 0; j < (mneeded / sizeof(HMODULE)); j++) {
if (!GetModuleBaseNameA(hProc, mods[j], me32.szModule,
MAX_PATH - 1))
continue;
if (!GetModuleFileNameExA(hProc, mods[j], me32.szExePath,
MAX_PATH - 1))
continue;
if (!GetModuleInformation(hProc, mods[j], &mi,
sizeof(mi)))
continue;
me32.hModule = mods[j];
me32.th32ProcessID = procs[i];
me32.modBaseAddr = mi.lpBaseOfDll;
me32.modBaseSize = mi.SizeOfImage;
if (callback(ps, me32, data, info))
break;
}
CloseHandle(hProc);
}
return 0;
}
int kill_process(DWORD pid)
{
HANDLE hProc;
if (GetCurrentProcessId() == pid) {
logg(LOGG_WARNING, "Don't want to kill myself\n");
return 1;
}
if ((hProc = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, FALSE, pid))) {
TerminateProcess(hProc, 0);
if (WaitForSingleObject(hProc, TIMEOUT_MODULE) != WAIT_OBJECT_0)
logg(LOGG_WARNING, "Unable to unload process from memory\n");
CloseHandle(hProc);
} else
logg(LOGG_WARNING, "OpenProcess() failed %lu\n", GetLastError());
return 1; /* Skip to next process anyway */
}
/* Not so safe ;) */
int unload_module(DWORD pid, HANDLE hModule)
{
DWORD rc = 1;
HANDLE ht;
HANDLE hProc;
if (GetCurrentProcessId() == pid) {
logg(LOGG_WARNING, "Don't want to unload modules from myself\n");
return 1;
}
hProc = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION |
PROCESS_VM_WRITE | PROCESS_VM_READ,
FALSE, pid);
if (!hProc) {
logg(LOGG_WARNING, "OpenProcess() failed %lu\n", GetLastError());
return 1; /* Skip to next process */
}
if ((ht = CreateRemoteThread(
hProc, 0, 0, (LPTHREAD_START_ROUTINE)FreeLibrary, hModule, 0,
&rc))) {
if (WaitForSingleObject(ht, TIMEOUT_MODULE) == WAIT_TIMEOUT) {
CloseHandle(ht);
CloseHandle(hProc);
logg(LOGG_INFO, "The module may trying to trick us, killing the process, please "
"rescan\n");
return kill_process(pid);
}
CloseHandle(ht);
rc = 0; /* Continue scanning this process */
} else {
DWORD res = GetLastError();
if (res == ERROR_CALL_NOT_IMPLEMENTED) {
logg(LOGG_WARNING, "Module unloading is not supported on this OS\n");
rc = -1; /* Don't complain about removing/moving the file */
} else {
logg(LOGG_ERROR, "CreateRemoteThread() failed %lu\n", res);
rc = 1; /* Skip to next process */
}
}
CloseHandle(hProc);
return rc;
}
#define FILLBYTES(dst) \
if (IsBadReadPtr(seek, sizeof(dst))) { \
logg(LOGG_ERROR, "ScanMem Align: Bad pointer!!!\n"); \
return 1; \
} \
memcpy(&dst, seek, sizeof(dst))
/* PE Realignment - FIXME: a lot of code is copy/paste from exeScanner.c */
int align_pe(unsigned char *buffer, size_t size)
{
int i = 0;
uint16_t e_mz;
uint32_t e_lfanew, e_magic;
unsigned char *seek = buffer;
PIMAGE_FILE_HEADER pehdr;
PIMAGE_OPTIONAL_HEADER32 opthdr;
PIMAGE_SECTION_HEADER sechdr;
FILLBYTES(e_mz);
if (e_mz != IMAGE_DOS_SIGNATURE) {
/* cli_dbgmsg("ScanMem Align: DOS Signature not found\n"); */
return 0;
}
seek += 0x3c;
FILLBYTES(e_lfanew);
if (!e_lfanew) {
/* cli_dbgmsg("ScanMem Align: Invalid PE offset\n"); */
return 0;
}
seek = buffer + e_lfanew;
/* PE Signature 'PE' */
FILLBYTES(e_magic);
if (e_magic != IMAGE_NT_SIGNATURE) {
/* cli_dbgmsg("ScanMem Align: PE Signature not found\n"); */
return 0;
}
seek += sizeof(e_magic);
if (IsBadReadPtr(seek, sizeof(IMAGE_FILE_HEADER)))
return 0;
pehdr = (PIMAGE_FILE_HEADER)seek;
seek += sizeof(IMAGE_FILE_HEADER);
if (IsBadReadPtr(seek, sizeof(IMAGE_OPTIONAL_HEADER32)))
return 0;
opthdr = (PIMAGE_OPTIONAL_HEADER32)seek;
seek += sizeof(IMAGE_OPTIONAL_HEADER32);
/* Invalid sections number */
if ((pehdr->NumberOfSections < 1) || (pehdr->NumberOfSections > 32)) {
/* cli_dbgmsg("ScanMem Align: Invalid sections number\n"); */
return 0;
}
for (i = 0; i < pehdr->NumberOfSections; i++) {
if (IsBadWritePtr(seek, sizeof(IMAGE_SECTION_HEADER)))
return 0;
sechdr = (PIMAGE_SECTION_HEADER)seek;
seek += sizeof(IMAGE_SECTION_HEADER);
sechdr->PointerToRawData = sechdr->VirtualAddress;
sechdr->SizeOfRawData = sechdr->Misc.VirtualSize;
}
return 1;
}
int dump_pe(const char *filename, PROCESSENTRY32 ProcStruct,
MODULEENTRY32 me32)
{
#ifdef _WIN64 /* MinGW has a broken header for ReadProcessMemory() */
size_t bytesread = 0;
#else
DWORD bytesread = 0;
#endif
DWORD byteswrite = 0;
int ret = -1;
HANDLE hFile = INVALID_HANDLE_VALUE, hProc = NULL;
unsigned char *buffer = NULL;
if (!(hProc = OpenProcess(PROCESS_VM_READ, FALSE, ProcStruct.th32ProcessID)))
return -1;
buffer = malloc((size_t)me32.modBaseSize);
if (!ReadProcessMemory(hProc, me32.modBaseAddr, buffer,
(size_t)me32.modBaseSize, &bytesread)) {
free(buffer);
CloseHandle(hProc);
return ret;
}
CloseHandle(hProc);
/* PE Realignment */
align_pe(buffer, me32.modBaseSize);
hFile = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
logg(LOGG_INFO, "Error creating %s\n", filename);
free(buffer);
return ret;
}
if (WriteFile(hFile, buffer, (DWORD)bytesread, &byteswrite, NULL))
ret = _open_osfhandle((intptr_t)hFile, O_RDONLY | O_BINARY);
free(buffer);
return ret;
}
int scanfile(const char *filename, scanmem_data *scan_data, struct mem_info *info)
{
int fd;
int scantype;
int ret = CL_CLEAN;
const char *virname = NULL;
logg(LOGG_DEBUG, "Scanning %s\n", filename);
if ((fd = safe_open(filename, O_RDONLY | O_BINARY)) == -1) {
logg(LOGG_WARNING, "Can't open file %s, %s\n", filename, strerror(errno));
return -1;
}
if (info->d) { // clamdscan
if (optget(info->opts, "stream")->enabled)
scantype = STREAM;
else if (optget(info->opts, "multiscan")->enabled)
scantype = MULTI;
else if (optget(info->opts, "allmatch")->enabled)
scantype = ALLMATCH;
else
scantype = CONT;
if ((sock = dconnect(clamdopts)) < 0) {
info->errors++;
return -1;
}
if (dsresult(sock, scantype, filename, NULL, &info->errors, clamdopts) > 0) {
info->ifiles++;
ret = CL_VIRUS;
}
} else { // clamscan
ret = cl_scandesc(fd, filename, &virname, &info->blocks, info->engine, info->options);
if (ret == CL_VIRUS) {
logg(LOGG_INFO, "%s: %s FOUND\n", filename, virname);
info->ifiles++;
} else if (scan_data->printclean) {
logg(LOGG_INFO, "%s: OK \n", filename);
}
}
close(fd);
return ret;
}
int scanmem_cb(PROCESSENTRY32 ProcStruct, MODULEENTRY32 me32, void *data, struct mem_info *info)
{
scanmem_data *scan_data = data;
int rc = 0;
int isprocess = 0;
char modulename[MAX_PATH] = "";
char expandmodule[MAX_PATH] = "";
if (!scan_data)
return 0;
scan_data->res = CL_CLEAN;
modulename[0] = 0;
/* Special case, btw why I get \SystemRoot\ in process szExePath?
There are also other cases? */
if ((strlen(me32.szExePath) > 12) &&
!strncmp(me32.szExePath, "\\SystemRoot\\", 12)) {
expandmodule[0] = 0;
strncat(expandmodule, me32.szExePath, MAX_PATH - 1 - strlen(expandmodule));
expandmodule[MAX_PATH - 1] = 0;
snprintf(expandmodule, MAX_PATH - 1, "%%SystemRoot%%\\%s",
&me32.szExePath[12]);
expandmodule[MAX_PATH - 1] = 0;
ExpandEnvironmentStrings(expandmodule, modulename, MAX_PATH - 1);
modulename[MAX_PATH - 1] = 0;
}
if (!modulename[0]) {
strncpy(modulename, me32.szExePath, MAX_PATH - 1);
modulename[MAX_PATH - 1] = 0;
}
scan_data->res = lookup_cache(&scan_data->files, modulename);
isprocess = !_stricmp(ProcStruct.szExeFile, modulename) ||
!_stricmp(ProcStruct.szExeFile, me32.szModule);
if (scan_data->res == -1) {
if (isprocess)
scan_data->processes++;
else
scan_data->modules++;
info->files++;
/* check for module exclusion */
scan_data->res = CL_CLEAN;
if (!(scan_data->exclude && chkpath(modulename, clamdopts)))
scan_data->res = scanfile(modulename, scan_data, info);
if ((scan_data->res != CL_VIRUS) && is_packed(modulename)) {
char *dumped = cli_gentemp(NULL);
int fd = -1;
if ((fd = dump_pe(dumped, ProcStruct, me32)) > 0) {
close(fd);
scan_data->res = scanfile(dumped, scan_data, info);
DeleteFile(dumped);
}
free(dumped);
}
insert_cache(&scan_data->files, modulename, scan_data->res);
}
if (scan_data->res == CL_VIRUS) {
if (isprocess && scan_data->kill) {
logg(LOGG_INFO, "Unloading program %s from memory\n", modulename);
rc = kill_process(ProcStruct.th32ProcessID);
} else if (scan_data->unload) {
logg(LOGG_INFO, "Unloading module %s from %s\n", me32.szModule, modulename);
if ((rc = unload_module(ProcStruct.th32ProcessID, me32.hModule)) == -1)
/* CreateProcessThread() is not implemented */
return 0;
}
if (action)
action(modulename);
return rc;
}
return rc;
}
int scanmem(struct mem_info *info)
{
scanmem_data data;
data.files = NULL;
data.printclean = 1;
data.kill = 0;
data.unload = 0;
data.exclude = 0;
data.res = CL_CLEAN;
data.processes = 0;
data.modules = 0;
HMODULE psapi_ok = LoadLibrary("psapi.dll");
HMODULE k32_ok = LoadLibrary("kernel32.dll");
if (!(psapi_ok || k32_ok)) {
logg(LOGG_INFO, " *** Memory Scanning is not supported on this OS ***\n\n");
return -1;
}
if (optget(info->opts, "infected")->enabled)
data.printclean = 0;
if (optget(info->opts, "kill")->enabled)
data.kill = 1;
if (optget(info->opts, "unload")->enabled)
data.unload = 1;
if (optget(info->opts, "exclude")->enabled)
data.exclude = 1;
if (info->d) {
if ((sock = dconnect(clamdopts)) < 0) {
info->errors++;
return -1;
}
}
logg(LOGG_INFO, " *** Scanning Programs in Computer Memory ***\n");
if (!EnablePrivilege(SE_DEBUG_NAME, SE_PRIVILEGE_ENABLED))
logg(LOGG_INFO, "---Please login as an Administrator to scan System processes loaded "
"in computer memory---\n");
if (k32_ok)
walkmodules_th(scanmem_cb, (void *)&data, info);
else
walkmodules_psapi(scanmem_cb, (void *)&data, info);
free_cache(&data.files);
logg(LOGG_INFO, "\n *** Scanned %lu processes - %lu modules ***\n", data.processes,
data.modules);
logg(LOGG_INFO, " *** Computer Memory Scan Completed ***\n\n");
return data.res;
}

68
clamav/common/scanmem.h Normal file
View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2021-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2005-2010 Gianluigi Tiesi <sherpya@netfarm.it>
*
* Authors: Gianluigi Tiesi
*
* 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 __SCANMEM_H
#define __SCANMEM_H
#ifndef TH32CS_SNAPMODULE32
#define TH32CS_SNAPMODULE32 0x00000010
#endif
#define TIMEOUT_MODULE 30000
int scanmem(struct mem_info *info);
/* cache helpers */
typedef struct _filelist_t {
char filename[MAX_PATH];
int res;
struct _filelist_t *next;
} filelist_t;
/* Callback */
typedef struct _cb_data_t {
const char *filename;
size_t size, count;
int oldvalue;
int fd;
} cb_data_t;
typedef struct _scanmem_data_t {
filelist_t *files;
int printclean, kill, unload, exclude;
int res;
uint32_t processes, modules;
} scanmem_data;
struct mem_info {
unsigned int d; /*1 = clamdscan, 0 = clamscan */
unsigned int files; /* number of scanned files */
unsigned int ifiles; /* number of infected files */
unsigned long int blocks; /* number of *scanned* 16kb blocks */
unsigned int errors;
struct cl_engine *engine;
const struct optstruct *opts;
struct cl_scan_options *options;
};
#endif

228
clamav/common/service.c Normal file
View File

@@ -0,0 +1,228 @@
/*
* Copyright (C) 2021-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2008-2010 Gianluigi Tiesi <sherpya@netfarm.it>
*
* Authors: Gianluigi Tiesi
*
* 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 <platform.h>
#include <winsvc.h>
#include "service.h"
#include "output.h"
static SERVICE_STATUS svc;
static SERVICE_STATUS_HANDLE svc_handle;
static SERVICE_TABLE_ENTRYA DT[] = {{"Service", ServiceMain}, {NULL, NULL}};
static HANDLE evStart;
static HANDLE DispatcherThread;
static int checkpoint_every = 5000;
int svc_uninstall(const char *name, int verbose)
{
SC_HANDLE sm, svc;
int ret = 1;
if (!(sm = OpenSCManagerA(NULL, NULL, DELETE))) {
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
fprintf(stderr, "Windows Services are not supported on this Platform\n");
else
fprintf(stderr, "Unable to Open SCManager (%d)\n", GetLastError());
return 0;
}
if ((svc = OpenServiceA(sm, name, DELETE))) {
if (DeleteService(svc)) {
if (verbose) printf("Service %s successfully removed\n", name);
} else {
fprintf(stderr, "Unable to Open Service %s (%d)\n", name, GetLastError());
ret = 0;
}
} else {
if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) {
if (verbose) printf("Service %s does not exist\n", name);
} else {
fprintf(stderr, "Unable to Open Service %s (%d)\n", name, GetLastError());
ret = 0;
}
}
if (svc) CloseServiceHandle(svc);
CloseServiceHandle(sm);
return ret;
}
int svc_install(const char *name, const char *dname, const char *desc)
{
SC_HANDLE sm, svc;
char modulepath[MAX_PATH];
char binpath[MAX_PATH];
SERVICE_DESCRIPTIONA sdesc = {(char *)desc};
if (!GetModuleFileName(NULL, modulepath, MAX_PATH - 1)) {
fprintf(stderr, "Unable to get the executable name (%d)\n", GetLastError());
return 0;
}
if (!svc_uninstall(name, 0)) return 0;
if (!(sm = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE | DELETE))) {
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
fprintf(stderr, "Windows Services are not supported on this Platform\n");
else
fprintf(stderr, "Unable to Open SCManager (%d)\n", GetLastError());
return 0;
}
if (strchr(modulepath, ' '))
snprintf(binpath, MAX_PATH - 1, "\"%s\" --daemon --service-mode", modulepath);
else
snprintf(binpath, MAX_PATH - 1, "%s --daemon --service-mode", modulepath);
svc = CreateServiceA(sm, name, dname, SERVICE_CHANGE_CONFIG,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
binpath,
NULL, /* Load group order */
NULL, /* Tag Id */
NULL, /* Dependencies */
NULL, /* User -> Local System */
"");
if (!svc) {
fprintf(stderr, "Unable to Create Service %s (%d)\n", name, GetLastError());
CloseServiceHandle(sm);
return 0;
}
/* ChangeServiceConfig2A() */
if (!ChangeServiceConfig2A(svc, SERVICE_CONFIG_DESCRIPTION, &sdesc))
fprintf(stderr, "Unable to set description for Service %s (%d)\n", name, GetLastError());
CloseServiceHandle(svc);
CloseServiceHandle(sm);
printf("Service %s successfully created.\n", name);
printf("Use 'net start %s' and 'net stop %s' to start/stop the service.\n", name, name);
return 1;
}
static void svc_getcpvalue(const char *name)
{
HKEY hKey;
DWORD dwType;
DWORD value, vlen = sizeof(DWORD);
char subkey[MAX_PATH];
snprintf(subkey, MAX_PATH - 1, "SYSTEM\\CurrentControlSet\\Services\\%s", name);
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, subkey, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
return;
if ((RegQueryValueExA(hKey, "Checkpoint", NULL, &dwType, (LPBYTE)&value, &vlen) == ERROR_SUCCESS) &&
(vlen == sizeof(DWORD) && (dwType == REG_DWORD)))
checkpoint_every = value;
RegCloseKey(hKey);
}
void svc_register(const char *name)
{
DWORD tid;
DT->lpServiceName = (char *)name;
svc_getcpvalue(name);
evStart = CreateEvent(NULL, TRUE, FALSE, NULL);
DispatcherThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)StartServiceCtrlDispatcherA, (LPVOID)DT, 0, &tid);
}
void svc_ready(void)
{
WaitForSingleObject(evStart, INFINITE);
svc.dwCurrentState = SERVICE_RUNNING;
svc.dwControlsAccepted |= SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
svc.dwCheckPoint = 0;
if (!SetServiceStatus(svc_handle, &svc)) {
logg(LOGG_INFO, "[service] SetServiceStatus() failed with %d\n", GetLastError());
exit(1);
}
}
int svc_checkpoint(const char *type, const char *name, unsigned int custom, void *context)
{
if (svc.dwCurrentState == SERVICE_START_PENDING) {
svc.dwCheckPoint++;
if ((svc.dwCheckPoint % checkpoint_every) == 0)
SetServiceStatus(svc_handle, &svc);
}
return 0;
}
void WINAPI ServiceCtrlHandler(DWORD code)
{
switch (code) {
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
svc.dwCurrentState = SERVICE_STOPPED;
svc.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
SetServiceStatus(svc_handle, &svc);
return;
case SERVICE_CONTROL_INTERROGATE:
break;
}
SetServiceStatus(svc_handle, &svc);
}
BOOL WINAPI cw_stop_ctrl_handler(DWORD CtrlType)
{
if (CtrlType == CTRL_C_EVENT) {
SetConsoleCtrlHandler(cw_stop_ctrl_handler, FALSE);
fprintf(stderr, "Control+C pressed, aborting...\n");
exit(0);
}
return TRUE;
}
void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv)
{
svc.dwServiceType = SERVICE_WIN32;
svc.dwCurrentState = SERVICE_START_PENDING;
svc.dwControlsAccepted = 0;
svc.dwWin32ExitCode = NO_ERROR;
svc.dwServiceSpecificExitCode = 0;
svc.dwCheckPoint = 0;
svc.dwWaitHint = 0;
if (!(svc_handle = RegisterServiceCtrlHandlerA(DT->lpServiceName, ServiceCtrlHandler))) {
logg(LOGG_INFO, "[service] RegisterServiceCtrlHandler() failed with %d\n", GetLastError());
exit(1);
}
if (!SetServiceStatus(svc_handle, &svc)) {
logg(LOGG_INFO, "[service] SetServiceStatus() failed with %d\n", GetLastError());
exit(1);
}
SetEvent(evStart);
WaitForSingleObject(DispatcherThread, INFINITE);
cw_stop_ctrl_handler(CTRL_C_EVENT);
}

38
clamav/common/service.h Normal file
View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2021-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2008-2010 Gianluigi Tiesi <sherpya@netfarm.it>
*
* Authors: Gianluigi Tiesi
*
* 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 __SERVICE_H
#define __SERVICE_H
#include <platform.h>
#include <winsvc.h>
int svc_uninstall(const char *name, int verbose);
int svc_install(const char *name, const char *dname, const char *desc);
static void svc_getcpvalue(const char *name);
void svc_register(const char *name);
void svc_ready(void);
int svc_checkpoint(const char *type, const char *name, unsigned int custom, void *context);
void WINAPI ServiceCtrlHandler(DWORD code);
BOOL WINAPI cw_stop_ctrl_handler(DWORD CtrlType);
void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
#endif

View File

@@ -51,25 +51,25 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
hStore = CertOpenSystemStoreA(NULL, "ROOT"); hStore = CertOpenSystemStoreA(NULL, "ROOT");
if (NULL == hStore) { if (NULL == hStore) {
mprintf("!Failed to open system certificate store.\n"); mprintf(LOGG_ERROR, "Failed to open system certificate store.\n");
goto done; goto done;
} }
store = cert_store_get_int(); store = cert_store_get_int();
if (!store) { if (!store) {
mprintf("!Failed to retrieve cert store\n"); mprintf(LOGG_ERROR, "Failed to retrieve cert store\n");
goto done; goto done;
} }
pt_err = pthread_mutex_lock(&store->mutex); pt_err = pthread_mutex_lock(&store->mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex lock failed\n"); mprintf(LOGG_ERROR, "Mutex lock failed\n");
} }
locked = true; locked = true;
if (store->loaded) { if (store->loaded) {
mprintf("Cert store already loaded\n"); mprintf(LOGG_INFO, "Cert store already loaded\n");
ret = CL_SUCCESS; ret = CL_SUCCESS;
goto done; goto done;
} }
@@ -84,7 +84,7 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
x509 = NULL; x509 = NULL;
x509 = d2i_X509(NULL, &encoded_cert, pWinCertContext->cbCertEncoded); x509 = d2i_X509(NULL, &encoded_cert, pWinCertContext->cbCertEncoded);
if (NULL == x509) { if (NULL == x509) {
mprintf("!Failed to convert system certificate to x509.\n"); mprintf(LOGG_ERROR, "Failed to convert system certificate to x509.\n");
continue; continue;
} }
@@ -92,7 +92,7 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
store->system_certs.certificates, store->system_certs.certificates,
(numCertificatesFound + 1) * sizeof(*store->system_certs.certificates)); (numCertificatesFound + 1) * sizeof(*store->system_certs.certificates));
if (store->system_certs.certificates == NULL) { if (store->system_certs.certificates == NULL) {
mprintf("!Failed to reserve memory for system cert list\n"); mprintf(LOGG_ERROR, "Failed to reserve memory for system cert list\n");
goto done; goto done;
} }
@@ -105,15 +105,15 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
issuer = malloc(issuerLen); issuer = malloc(issuerLen);
if (NULL == issuer) { if (NULL == issuer) {
mprintf("!Failed to allocate memory for certificate name.\n"); mprintf(LOGG_ERROR, "Failed to allocate memory for certificate name.\n");
ret = CURLE_OUT_OF_MEMORY; ret = CURLE_OUT_OF_MEMORY;
goto done; goto done;
} }
if (0 == CertGetNameStringA(pWinCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, issuer, issuerLen)) { if (0 == CertGetNameStringA(pWinCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, issuer, issuerLen)) {
mprintf("!Failed to get friendly display name for certificate.\n"); mprintf(LOGG_ERROR, "Failed to get friendly display name for certificate.\n");
} else { } else {
mprintf("Certificate loaded from Windows certificate store: %s\n", issuer); mprintf(LOGG_INFO, "Certificate loaded from Windows certificate store: %s\n", issuer);
} }
free(issuer); free(issuer);
@@ -125,24 +125,24 @@ cl_error_t cert_store_load(X509 **trusted_certs, size_t trusted_cert_count)
lastError = GetLastError(); lastError = GetLastError();
switch (lastError) { switch (lastError) {
case E_INVALIDARG: case E_INVALIDARG:
mprintf("!The handle in the hCertStore parameter is not the same as that in the certificate context pointed to by pPrevCertContext.\n"); mprintf(LOGG_ERROR, "The handle in the hCertStore parameter is not the same as that in the certificate context pointed to by pPrevCertContext.\n");
break; break;
case CRYPT_E_NOT_FOUND: case CRYPT_E_NOT_FOUND:
case ERROR_NO_MORE_FILES: case ERROR_NO_MORE_FILES:
if (0 == numCertificatesFound) { if (0 == numCertificatesFound) {
mprintf("!No certificates were found.\n"); mprintf(LOGG_ERROR, "No certificates were found.\n");
} }
break; break;
default: default:
mprintf("!Unexpected error code from CertEnumCertificatesInStore()\n"); mprintf(LOGG_ERROR, "Unexpected error code from CertEnumCertificatesInStore()\n");
} }
if (trusted_certs && trusted_cert_count > 0) { if (trusted_certs && trusted_cert_count > 0) {
if (cert_store_set_trusted_int(trusted_certs, trusted_cert_count) == 0) { if (cert_store_set_trusted_int(trusted_certs, trusted_cert_count) == 0) {
mprintf("*Trusted certificates loaded: %zu\n", mprintf(LOGG_DEBUG, "Trusted certificates loaded: %zu\n",
store->trusted_certs.count); store->trusted_certs.count);
} else { } else {
mprintf("^Continuing without trusted certificates\n"); mprintf(LOGG_WARNING, "Continuing without trusted certificates\n");
/* proceed as if we succeeded using only certificates from the /* proceed as if we succeeded using only certificates from the
* system */ * system */
} }
@@ -156,7 +156,7 @@ done:
pt_err = pthread_mutex_unlock(&store->mutex); pt_err = pthread_mutex_unlock(&store->mutex);
if (pt_err) { if (pt_err) {
errno = pt_err; errno = pt_err;
mprintf("!Mutex unlock failed\n"); mprintf(LOGG_ERROR, "Mutex unlock failed\n");
} }
locked = false; locked = false;
} }

View File

@@ -0,0 +1,64 @@
# Copyright (C) 2020-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
if(WIN32)
add_definitions(-DWIN32_LEAN_AND_MEAN)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
# Windows compatibility headers
include_directories(${CMAKE_SOURCE_DIR}/win32/compat)
endif()
# The freshclam executable.
add_executable( freshclam-bin )
target_sources( freshclam-bin
PRIVATE
freshclam.c
execute.c
execute.h
notify.c
notify.h )
if(WIN32)
target_sources( freshclam-bin
PRIVATE
${CMAKE_SOURCE_DIR}/win32/res/freshclam.rc
${CMAKE_SOURCE_DIR}/win32/res/clam.manifest )
endif()
set_target_properties( freshclam-bin PROPERTIES COMPILE_FLAGS "${WARNCFLAGS}" )
if (APPLE AND CLAMAV_SIGN_FILE)
set_target_properties( freshclam-bin PROPERTIES
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ${CODE_SIGN_IDENTITY}
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM ${DEVELOPMENT_TEAM_ID}
)
endif()
target_link_libraries(freshclam-bin
PRIVATE
ClamAV::libfreshclam
ClamAV::libclamav
ClamAV::common )
if(WIN32)
install(TARGETS freshclam-bin DESTINATION . COMPONENT programs)
install(FILES $<TARGET_PDB_FILE:freshclam-bin> DESTINATION . OPTIONAL COMPONENT programs)
else()
install(TARGETS freshclam-bin DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT programs)
endif()
# Install an empty database directory
INSTALL(CODE "FILE(MAKE_DIRECTORY \${ENV}\${CMAKE_INSTALL_PREFIX}/\${DATABASE_DIRECTORY})" COMPONENT programs)
# Now we rename freshclam-bin executable to freshclam using target properties
set_target_properties( freshclam-bin
PROPERTIES OUTPUT_NAME freshclam )
if(SYSTEMD_FOUND)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/clamav-freshclam.service.in
${CMAKE_CURRENT_BINARY_DIR}/clamav-freshclam.service @ONLY)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/clamav-freshclam.service
DESTINATION ${SYSTEMD_UNIT_DIR}
COMPONENT programs)
endif()

21
clamav/freshclam/Doxyfile Normal file
View File

@@ -0,0 +1,21 @@
PROJECT_NAME = ClamAV - FreshClam
OUTPUT_DIRECTORY = ../docs/freshclam
WARNINGS = YES
FILE_PATTERNS = *.c *.h
PERL_PATH = /usr/bin/perl
SEARCHENGINE = YES
GENERATE_LATEX=NO
OPTIMIZE_OUTPUT_FOR_C=YES
HAVE_DOT=YES
CALL_GRAPH=YES
CALLER_GRAPH=YES
JAVADOC_AUTOBRIEF=YES
GENERATE_MAN=NO
EXAMPLE_PATH=examples
DOT_CLEANUP=NO
MAX_DOT_GRAPH_DEPTH=3
EXTRACT_ALL=YES
INPUT = .

View File

@@ -0,0 +1,13 @@
[Unit]
Description=ClamAV virus database updater
Documentation=man:freshclam(1) man:freshclam.conf(5) https://docs.clamav.net/
# If user wants it run from cron, don't start the daemon.
ConditionPathExists=!/etc/cron.d/clamav-freshclam
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=@prefix@/bin/freshclam -d --foreground=true
[Install]
WantedBy=multi-user.target

View File

@@ -43,18 +43,18 @@ void execute(const char *type, const char *text, int bDaemonized)
if (!bDaemonized) { if (!bDaemonized) {
if (sscanf(text, "EXIT_%d", &ret) == 1) { if (sscanf(text, "EXIT_%d", &ret) == 1) {
logg("*%s: EXIT_%d\n", type, ret); logg(LOGG_DEBUG, "%s: EXIT_%d\n", type, ret);
exit(ret); exit(ret);
} }
if (system(text) == -1) if (system(text) == -1)
logg("%s: system(%s) failed\n", type, text); logg(LOGG_INFO, "%s: system(%s) failed\n", type, text);
return; return;
} }
#ifdef _WIN32 #ifdef _WIN32
if (system(text) == -1) { if (system(text) == -1) {
logg("^%s: couldn't execute \"%s\".\n", type, text); logg(LOGG_WARNING, "%s: couldn't execute \"%s\".\n", type, text);
return; return;
} }
#else #else
@@ -63,17 +63,17 @@ void execute(const char *type, const char *text, int bDaemonized)
switch (pid = fork()) { switch (pid = fork()) {
case 0: case 0:
if (-1 == system(text)) { if (-1 == system(text)) {
logg("^%s: couldn't execute \"%s\".\n", type, text); logg(LOGG_WARNING, "%s: couldn't execute \"%s\".\n", type, text);
} }
exit(0); exit(0);
case -1: case -1:
logg("^%s::fork() failed, %s.\n", type, strerror(errno)); logg(LOGG_WARNING, "%s::fork() failed, %s.\n", type, strerror(errno));
break; break;
default: default:
g_active_children++; g_active_children++;
} }
} else { } else {
logg("^%s: already %d processes active.\n", type, g_active_children); logg(LOGG_WARNING, "%s: already %d processes active.\n", type, g_active_children);
} }
#endif #endif
} }

View File

@@ -55,11 +55,15 @@
#include "others.h" #include "others.h"
#include "str.h" #include "str.h"
// shared // common
#include "optparser.h" #include "optparser.h"
#include "output.h" #include "output.h"
#include "misc.h" #include "misc.h"
#ifdef _WIN32
#include "service.h"
#endif
// libfreshclam // libfreshclam
#include "libfreshclam.h" #include "libfreshclam.h"
@@ -115,7 +119,7 @@ sighandler(int sig)
cli_rmdirs(g_freshclamTempDirectory); cli_rmdirs(g_freshclamTempDirectory);
if (g_pidfile) if (g_pidfile)
unlink(g_pidfile); unlink(g_pidfile);
logg("Update process terminated\n"); logg(LOGG_INFO, "Update process terminated\n");
exit(0); exit(0);
} }
@@ -126,9 +130,9 @@ static int writepid(const char *pidfile)
{ {
FILE *fd; FILE *fd;
int old_umask; int old_umask;
old_umask = umask(0002); old_umask = umask(0022);
if ((fd = fopen(pidfile, "w")) == NULL) { if ((fd = fopen(pidfile, "w")) == NULL) {
logg("!Can't save PID to file %s: %s\n", pidfile, strerror(errno)); logg(LOGG_ERROR, "Can't save PID to file %s: %s\n", pidfile, strerror(errno));
return 1; return 1;
} else { } else {
fprintf(fd, "%d\n", (int)getpid()); fprintf(fd, "%d\n", (int)getpid());
@@ -144,7 +148,7 @@ static int writepid(const char *pidfile)
struct passwd *pw = getpwuid(0); struct passwd *pw = getpwuid(0);
int ret = lchown(pidfile, pw->pw_uid, pw->pw_gid); int ret = lchown(pidfile, pw->pw_uid, pw->pw_gid);
if (ret) { if (ret) {
logg("!Can't change ownership of PID file %s '%s'\n", pidfile, strerror(errno)); logg(LOGG_ERROR, "Can't change ownership of PID file %s '%s'\n", pidfile, strerror(errno));
return 1; return 1;
} }
} }
@@ -173,6 +177,10 @@ static void help(void)
printf("\n"); printf("\n");
printf(" --config-file=FILE Read configuration from FILE.\n"); printf(" --config-file=FILE Read configuration from FILE.\n");
printf(" --log=FILE -l FILE Log into FILE\n"); printf(" --log=FILE -l FILE Log into FILE\n");
#ifdef _WIN32
printf(" --install-service Install Windows Service\n");
printf(" --uninstall-service Uninstall Windows Service\n");
#endif
printf(" --daemon -d Run in daemon mode\n"); printf(" --daemon -d Run in daemon mode\n");
printf(" --pid=FILE -p FILE Save daemon's pid in FILE\n"); printf(" --pid=FILE -p FILE Save daemon's pid in FILE\n");
#ifndef _WIN32 #ifndef _WIN32
@@ -199,13 +207,13 @@ static void libclamav_msg_callback(enum cl_msg severity, const char *fullmsg, co
switch (severity) { switch (severity) {
case CL_MSG_ERROR: case CL_MSG_ERROR:
logg("^[LibClamAV] %s", msg); logg(LOGG_WARNING, "[LibClamAV] %s", msg);
break; break;
case CL_MSG_WARN: case CL_MSG_WARN:
logg("~[LibClamAV] %s", msg); logg(LOGG_INFO, "[LibClamAV] %s", msg);
break; break;
default: default:
logg("*[LibClamAV] %s", msg); logg(LOGG_DEBUG, "[LibClamAV] %s", msg);
break; break;
} }
} }
@@ -217,7 +225,7 @@ static void libclamav_msg_callback_quiet(enum cl_msg severity, const char *fullm
switch (severity) { switch (severity) {
case CL_MSG_ERROR: case CL_MSG_ERROR:
logg("^[LibClamAV] %s", msg); logg(LOGG_WARNING, "[LibClamAV] %s", msg);
break; break;
default: default:
break; break;
@@ -240,28 +248,28 @@ fc_error_t download_complete_callback(const char *dbFilename, void *context)
#endif #endif
if ((NULL == context) || (NULL == dbFilename)) { if ((NULL == context) || (NULL == dbFilename)) {
logg("^Invalid arguments to download_complete_callback.\n"); logg(LOGG_WARNING, "Invalid arguments to download_complete_callback.\n");
goto done; goto done;
} }
logg("*download_complete_callback: Download complete for database : %s\n", dbFilename); logg(LOGG_DEBUG, "download_complete_callback: Download complete for database : %s\n", dbFilename);
logg("*download_complete_callback: fc_context->bTestDatabases : %u\n", fc_context->bBytecodeEnabled); logg(LOGG_DEBUG, "download_complete_callback: fc_context->bTestDatabases : %u\n", fc_context->bTestDatabases);
logg("*download_complete_callback: fc_context->bBytecodeEnabled : %u\n", fc_context->bBytecodeEnabled); logg(LOGG_DEBUG, "download_complete_callback: fc_context->bBytecodeEnabled : %u\n", fc_context->bBytecodeEnabled);
logg("Testing database: '%s' ...\n", dbFilename); logg(LOGG_INFO, "Testing database: '%s' ...\n", dbFilename);
if (fc_context->bTestDatabases) { if (fc_context->bTestDatabases) {
#ifdef _WIN32 #ifdef _WIN32
__try { __try {
ret = fc_test_database(dbFilename, fc_context->bBytecodeEnabled); ret = fc_test_database(dbFilename, fc_context->bBytecodeEnabled);
} __except (logg("!Exception during database testing, code %08x\n", } __except (logg(LOGG_ERROR, "Exception during database testing, code %08x\n",
GetExceptionCode()), GetExceptionCode()),
EXCEPTION_CONTINUE_SEARCH) { EXCEPTION_CONTINUE_SEARCH) {
ret = FC_ETESTFAIL; ret = FC_ETESTFAIL;
} }
if (FC_SUCCESS != ret) { if (FC_SUCCESS != ret) {
logg("^Database load exited with \"%s\"\n", fc_strerror(ret)); logg(LOGG_WARNING, "Database load exited with \"%s\"\n", fc_strerror(ret));
status = FC_ETESTFAIL; status = FC_ETESTFAIL;
goto done; goto done;
} }
@@ -273,10 +281,10 @@ fc_error_t download_complete_callback(const char *dbFilename, void *context)
* Failed to create pipe. * Failed to create pipe.
* Test database without using pipe & child process. * Test database without using pipe & child process.
*/ */
logg("^pipe() failed: %s\n", strerror(errno)); logg(LOGG_WARNING, "pipe() failed: %s\n", strerror(errno));
ret = fc_test_database(dbFilename, fc_context->bBytecodeEnabled); ret = fc_test_database(dbFilename, fc_context->bBytecodeEnabled);
if (FC_SUCCESS != ret) { if (FC_SUCCESS != ret) {
logg("^Database load exited with \"%s\"\n", fc_strerror(ret)); logg(LOGG_WARNING, "Database load exited with \"%s\"\n", fc_strerror(ret));
status = FC_ETESTFAIL; status = FC_ETESTFAIL;
goto done; goto done;
} }
@@ -297,12 +305,12 @@ fc_error_t download_complete_callback(const char *dbFilename, void *context)
*/ */
close(pipefd[0]); close(pipefd[0]);
close(pipefd[1]); close(pipefd[1]);
logg("^fork() to test database failed: %s\n", strerror(errno)); logg(LOGG_WARNING, "fork() to test database failed: %s\n", strerror(errno));
/* Test the database without forking. */ /* Test the database without forking. */
ret = fc_test_database(dbFilename, fc_context->bBytecodeEnabled); ret = fc_test_database(dbFilename, fc_context->bBytecodeEnabled);
if (FC_SUCCESS != ret) { if (FC_SUCCESS != ret) {
logg("^Database load exited with \"%s\"\n", fc_strerror(ret)); logg(LOGG_WARNING, "Database load exited with \"%s\"\n", fc_strerror(ret));
status = FC_ETESTFAIL; status = FC_ETESTFAIL;
goto done; goto done;
} }
@@ -316,7 +324,7 @@ fc_error_t download_complete_callback(const char *dbFilename, void *context)
/* Redirect stderr to the pipe for the parent process */ /* Redirect stderr to the pipe for the parent process */
if (dup2(pipefd[1], 2) == -1) { if (dup2(pipefd[1], 2) == -1) {
logg("^dup2() call to redirect stderr to pipe failed: %s\n", strerror(errno)); logg(LOGG_WARNING, "dup2() call to redirect stderr to pipe failed: %s\n", strerror(errno));
} }
/* Test the database */ /* Test the database */
@@ -343,7 +351,7 @@ fc_error_t download_complete_callback(const char *dbFilename, void *context)
/* must read entire output, child doesn't like EPIPE */ /* must read entire output, child doesn't like EPIPE */
while (fgets(lastline, sizeof(firstline), pipeHandle)) { while (fgets(lastline, sizeof(firstline), pipeHandle)) {
/* print the full output only when LogVerbose or -v is given */ /* print the full output only when LogVerbose or -v is given */
logg("*%s", lastline); logg(LOGG_DEBUG, "%s", lastline);
} }
fclose(pipeHandle); fclose(pipeHandle);
pipeHandle = NULL; pipeHandle = NULL;
@@ -353,7 +361,7 @@ fc_error_t download_complete_callback(const char *dbFilename, void *context)
} }
if ((waitpidret == -1) && (errno != ECHILD)) if ((waitpidret == -1) && (errno != ECHILD))
logg("^waitpid() failed: %s\n", strerror(errno)); logg(LOGG_WARNING, "waitpid() failed: %s\n", strerror(errno));
/* Strip trailing whitespace from child error output */ /* Strip trailing whitespace from child error output */
cli_chomp(firstline); cli_chomp(firstline);
@@ -361,26 +369,26 @@ fc_error_t download_complete_callback(const char *dbFilename, void *context)
if (firstline[0]) { if (firstline[0]) {
/* The child process output some error messages */ /* The child process output some error messages */
logg("^Stderr output from database load : %s%s%s\n", firstline, lastline[0] ? " [...] " : "", lastline); logg(LOGG_WARNING, "Stderr output from database load : %s%s%s\n", firstline, lastline[0] ? " [...] " : "", lastline);
} }
if (WIFEXITED(stat_loc)) { if (WIFEXITED(stat_loc)) {
ret = (fc_error_t)WEXITSTATUS(stat_loc); ret = (fc_error_t)WEXITSTATUS(stat_loc);
if (FC_SUCCESS != ret) { if (FC_SUCCESS != ret) {
logg("^Database load exited with \"%s\"\n", fc_strerror(ret)); logg(LOGG_WARNING, "Database load exited with \"%s\"\n", fc_strerror(ret));
status = FC_ETESTFAIL; status = FC_ETESTFAIL;
goto done; goto done;
} }
if (firstline[0]) if (firstline[0])
logg("^Database successfully loaded, but there is stderr output\n"); logg(LOGG_WARNING, "Database successfully loaded, but there is stderr output\n");
} else if (WIFSIGNALED(stat_loc)) { } else if (WIFSIGNALED(stat_loc)) {
logg("!Database load killed by signal %d\n", WTERMSIG(stat_loc)); logg(LOGG_ERROR, "Database load killed by signal %d\n", WTERMSIG(stat_loc));
status = FC_ETESTFAIL; status = FC_ETESTFAIL;
goto done; goto done;
} else { } else {
logg("^Unknown status from wait: %d\n", stat_loc); logg(LOGG_WARNING, "Unknown status from wait: %d\n", stat_loc);
status = FC_ETESTFAIL; status = FC_ETESTFAIL;
goto done; goto done;
} }
@@ -395,9 +403,9 @@ fc_error_t download_complete_callback(const char *dbFilename, void *context)
done: done:
if (FC_SUCCESS == status) { if (FC_SUCCESS == status) {
logg("Database test passed.\n"); logg(LOGG_INFO, "Database test passed.\n");
} else { } else {
logg("!Database test FAILED.\n"); logg(LOGG_ERROR, "Database test FAILED.\n");
} }
/* Re-enable the global handler's child process wait */ /* Re-enable the global handler's child process wait */
@@ -422,7 +430,7 @@ done:
* @param server Server string * @param server Server string
* @param defaultProtocol Default protocol if not already specified. Eg: "https" * @param defaultProtocol Default protocol if not already specified. Eg: "https"
* @param defaultPort Default port if not already specified. Eg: 443 * @param defaultPort Default port if not already specified. Eg: 443
* @param serverUrl [out] A malloced string in the protocol://server:port format. * @param[out] serverUrl A malloced string in the protocol://server:port format.
* @return fc_error_t FC_SUCCESS if success. * @return fc_error_t FC_SUCCESS if success.
* @return fc_error_t FC_EARG if invalid args. * @return fc_error_t FC_EARG if invalid args.
* @return fc_error_t FC_EMEM if malloc failed. * @return fc_error_t FC_EMEM if malloc failed.
@@ -439,7 +447,7 @@ static fc_error_t get_server_node(
size_t urlLen = 0; size_t urlLen = 0;
if ((NULL == server) || (NULL == defaultProtocol) || (NULL == serverUrl)) { if ((NULL == server) || (NULL == defaultProtocol) || (NULL == serverUrl)) {
mprintf("!get_server_node: Invalid args!\n"); mprintf(LOGG_ERROR, "get_server_node: Invalid args!\n");
goto done; goto done;
} }
@@ -451,7 +459,7 @@ static fc_error_t get_server_node(
if (!strncmp(server, "db.", 3) && strstr(server, ".clamav.net")) { if (!strncmp(server, "db.", 3) && strstr(server, ".clamav.net")) {
url = cli_strdup("https://database.clamav.net"); url = cli_strdup("https://database.clamav.net");
if (NULL == url) { if (NULL == url) {
logg("!get_server_node: Failed to duplicate string for database.clamav.net url.\n"); logg(LOGG_ERROR, "get_server_node: Failed to duplicate string for database.clamav.net url.\n");
status = FC_EMEM; status = FC_EMEM;
goto done; goto done;
} }
@@ -459,7 +467,7 @@ static fc_error_t get_server_node(
urlLen = strlen(defaultProtocol) + strlen("://") + strlen(server); urlLen = strlen(defaultProtocol) + strlen("://") + strlen(server);
url = malloc(urlLen + 1); url = malloc(urlLen + 1);
if (NULL == url) { if (NULL == url) {
logg("!get_server_node: Failed to allocate memory for server url.\n"); logg(LOGG_ERROR, "get_server_node: Failed to allocate memory for server url.\n");
status = FC_EMEM; status = FC_EMEM;
goto done; goto done;
} }
@@ -468,7 +476,7 @@ static fc_error_t get_server_node(
urlLen = strlen(server); urlLen = strlen(server);
url = cli_strdup(server); url = cli_strdup(server);
if (NULL == url) { if (NULL == url) {
logg("!get_server_node: Failed to duplicate string for server url.\n"); logg(LOGG_ERROR, "get_server_node: Failed to duplicate string for server url.\n");
status = FC_EMEM; status = FC_EMEM;
goto done; goto done;
} }
@@ -485,8 +493,8 @@ done:
* @brief Add string to list of strings. * @brief Add string to list of strings.
* *
* @param item string to add to list. * @param item string to add to list.
* @param stringList [in/out] String list to add string to. * @param[in,out] stringList String list to add string to.
* @param nListItems [in/out] Number of strings in list. * @param[in,out] nListItems Number of strings in list.
* @return fc_error_t FC_SUCCESS if success. * @return fc_error_t FC_SUCCESS if success.
* @return fc_error_t FC_EARG if invalid args passed to function. * @return fc_error_t FC_EARG if invalid args passed to function.
* @return fc_error_t FC_EMEM if failed to allocate memory. * @return fc_error_t FC_EMEM if failed to allocate memory.
@@ -499,14 +507,14 @@ static fc_error_t string_list_add(const char *item, char ***stringList, uint32_t
uint32_t nItems = 0; uint32_t nItems = 0;
if ((NULL == item) || (NULL == stringList) || (NULL == nListItems)) { if ((NULL == item) || (NULL == stringList) || (NULL == nListItems)) {
mprintf("!string_list_add: Invalid arguments.\n"); mprintf(LOGG_ERROR, "string_list_add: Invalid arguments.\n");
goto done; goto done;
} }
nItems = *nListItems + 1; nItems = *nListItems + 1;
newList = (char **)cli_realloc(*stringList, nItems * sizeof(char *)); newList = (char **)cli_realloc(*stringList, nItems * sizeof(char *));
if (newList == NULL) { if (newList == NULL) {
mprintf("!string_list_add: Failed to allocate memory for optional database list entry.\n"); mprintf(LOGG_ERROR, "string_list_add: Failed to allocate memory for optional database list entry.\n");
status = FC_EMEM; status = FC_EMEM;
goto done; goto done;
} }
@@ -515,7 +523,7 @@ static fc_error_t string_list_add(const char *item, char ***stringList, uint32_t
newList[nItems - 1] = cli_strdup(item); newList[nItems - 1] = cli_strdup(item);
if (newList[nItems - 1] == NULL) { if (newList[nItems - 1] == NULL) {
mprintf("!string_list_add: Failed to allocate memory for optional database list item.\n"); mprintf(LOGG_ERROR, "string_list_add: Failed to allocate memory for optional database list item.\n");
status = FC_EMEM; status = FC_EMEM;
goto done; goto done;
} }
@@ -556,9 +564,9 @@ static void free_string_list(char **stringList, uint32_t nListItems)
* @brief Get the database server list object * @brief Get the database server list object
* *
* @param opts FreshClam options struct. * @param opts FreshClam options struct.
* @param serverList [out] List of servers. * @param[out] serverList List of servers.
* @param nServers [out] Number of servers in list. * @param[out] nServers Number of servers in list.
* @param bPrivate [out] Non-zero if PrivateMirror servers were selected. * @param[out] bPrivate Non-zero if PrivateMirror servers were selected.
* @return fc_error_t * @return fc_error_t
*/ */
static fc_error_t get_database_server_list( static fc_error_t get_database_server_list(
@@ -574,7 +582,7 @@ static fc_error_t get_database_server_list(
uint32_t numServers = 0; uint32_t numServers = 0;
if ((NULL == opts) || (NULL == serverList) || (NULL == nServers) || (NULL == bPrivate)) { if ((NULL == opts) || (NULL == serverList) || (NULL == nServers) || (NULL == bPrivate)) {
mprintf("!get_database_server_list: Invalid args!\n"); mprintf(LOGG_ERROR, "get_database_server_list: Invalid args!\n");
goto done; goto done;
} }
@@ -591,13 +599,13 @@ static fc_error_t get_database_server_list(
char *serverUrl = NULL; char *serverUrl = NULL;
if (cli_strbcasestr(opt->strarg, ".clamav.net")) { if (cli_strbcasestr(opt->strarg, ".clamav.net")) {
logg("!The PrivateMirror config option may not include servers under *.clamav.net.\n"); logg(LOGG_ERROR, "The PrivateMirror config option may not include servers under *.clamav.net.\n");
status = FC_ECONFIG; status = FC_ECONFIG;
goto done; goto done;
} }
if (FC_SUCCESS != (ret = get_server_node(opt->strarg, "http", &serverUrl))) { if (FC_SUCCESS != (ret = get_server_node(opt->strarg, "http", &serverUrl))) {
mprintf("!get_database_server_list: Failed to read PrivateMirror server %s", opt->strarg); mprintf(LOGG_ERROR, "get_database_server_list: Failed to read PrivateMirror server %s", opt->strarg);
status = ret; status = ret;
goto done; goto done;
} }
@@ -605,7 +613,7 @@ static fc_error_t get_database_server_list(
if (FC_SUCCESS != (ret = string_list_add(serverUrl, &servers, &numServers))) { if (FC_SUCCESS != (ret = string_list_add(serverUrl, &servers, &numServers))) {
free(serverUrl); free(serverUrl);
mprintf("!get_database_server_list: Failed to add string to list.\n"); mprintf(LOGG_ERROR, "get_database_server_list: Failed to add string to list.\n");
status = ret; status = ret;
goto done; goto done;
} }
@@ -615,7 +623,7 @@ static fc_error_t get_database_server_list(
/* Check for DatabaseMirrors. */ /* Check for DatabaseMirrors. */
if (!(opt = optget(opts, "DatabaseMirror"))->enabled) { if (!(opt = optget(opts, "DatabaseMirror"))->enabled) {
/* No DatabaseMirror configured. Fail out. */ /* No DatabaseMirror configured. Fail out. */
logg("!No DatabaseMirror or PrivateMirror servers set in freshclam config file.\n"); logg(LOGG_ERROR, "No DatabaseMirror or PrivateMirror servers set in freshclam config file.\n");
status = FC_ECONFIG; status = FC_ECONFIG;
goto done; goto done;
} }
@@ -624,7 +632,7 @@ static fc_error_t get_database_server_list(
char *serverUrl = NULL; char *serverUrl = NULL;
if (FC_SUCCESS != (ret = get_server_node(opt->strarg, "https", &serverUrl))) { if (FC_SUCCESS != (ret = get_server_node(opt->strarg, "https", &serverUrl))) {
mprintf("!get_database_server_list: Failed to parse DatabaseMirror server %s.", opt->strarg); mprintf(LOGG_ERROR, "get_database_server_list: Failed to parse DatabaseMirror server %s.", opt->strarg);
status = ret; status = ret;
goto done; goto done;
} }
@@ -632,7 +640,7 @@ static fc_error_t get_database_server_list(
if (FC_SUCCESS != (ret = string_list_add(serverUrl, &servers, &numServers))) { if (FC_SUCCESS != (ret = string_list_add(serverUrl, &servers, &numServers))) {
free(serverUrl); free(serverUrl);
mprintf("!get_database_server_list: Failed to add string to list.\n"); mprintf(LOGG_ERROR, "get_database_server_list: Failed to add string to list.\n");
status = ret; status = ret;
goto done; goto done;
} }
@@ -657,8 +665,8 @@ done:
* @brief Get a list of strings for a given repeatable opt argument. * @brief Get a list of strings for a given repeatable opt argument.
* *
* @param opt optstruct of repeatable argument to collect in a list. * @param opt optstruct of repeatable argument to collect in a list.
* @param stringList [out] String list. * @param[out] stringList String list.
* @param nListItems [out] Number of strings in list. * @param[out] nListItems Number of strings in list.
* @return fc_error_t FC_SUCCESS if success. * @return fc_error_t FC_SUCCESS if success.
* @return fc_error_t FC_EARG if invalid args passed to function. * @return fc_error_t FC_EARG if invalid args passed to function.
* @return fc_error_t FC_EMEM if failed to allocate memory. * @return fc_error_t FC_EMEM if failed to allocate memory.
@@ -672,7 +680,7 @@ static fc_error_t get_string_list(const struct optstruct *opt, char ***stringLis
uint32_t nItems = 0; uint32_t nItems = 0;
if ((NULL == opt) || (NULL == stringList) || (NULL == nListItems)) { if ((NULL == opt) || (NULL == stringList) || (NULL == nListItems)) {
mprintf("!get_string_list: Invalid arguments.\n"); mprintf(LOGG_ERROR, "get_string_list: Invalid arguments.\n");
goto done; goto done;
} }
@@ -683,7 +691,7 @@ static fc_error_t get_string_list(const struct optstruct *opt, char ***stringLis
if (opt->enabled) { if (opt->enabled) {
while (opt) { while (opt) {
if (FC_SUCCESS != (ret = string_list_add(opt->strarg, stringList, nListItems))) { if (FC_SUCCESS != (ret = string_list_add(opt->strarg, stringList, nListItems))) {
mprintf("!get_string_list: Failed to add string to list.\n"); mprintf(LOGG_ERROR, "get_string_list: Failed to add string to list.\n");
status = ret; status = ret;
goto done; goto done;
} }
@@ -716,7 +724,7 @@ static fc_error_t initialize(struct optstruct *opts)
memset(&fcConfig, 0, sizeof(fc_config)); memset(&fcConfig, 0, sizeof(fc_config));
if (NULL == opts) { if (NULL == opts) {
mprintf("!initialize: Invalid arguments.\n"); mprintf(LOGG_ERROR, "initialize: Invalid arguments.\n");
goto done; goto done;
} }
@@ -741,11 +749,11 @@ static fc_error_t initialize(struct optstruct *opts)
struct passwd *user; struct passwd *user;
#endif #endif
logg("Creating missing database directory: %s\n", fcConfig.databaseDirectory); logg(LOGG_INFO, "Creating missing database directory: %s\n", fcConfig.databaseDirectory);
if (0 != mkdir(fcConfig.databaseDirectory, 0755)) { if (0 != mkdir(fcConfig.databaseDirectory, 0755)) {
logg("!Failed to create database directory: %s\n", fcConfig.databaseDirectory); logg(LOGG_ERROR, "Failed to create database directory: %s\n", fcConfig.databaseDirectory);
logg("Manually prepare the database directory, or re-run freshclam with higher privileges.\n"); logg(LOGG_INFO, "Manually prepare the database directory, or re-run freshclam with higher privileges.\n");
status = FC_EDBDIRACCESS; status = FC_EDBDIRACCESS;
goto done; goto done;
} }
@@ -755,14 +763,14 @@ static fc_error_t initialize(struct optstruct *opts)
/* Running as root user, will assign ownership of database directory to DatabaseOwner */ /* Running as root user, will assign ownership of database directory to DatabaseOwner */
errno = 0; errno = 0;
if ((user = getpwnam(optget(opts, "DatabaseOwner")->strarg)) == NULL) { if ((user = getpwnam(optget(opts, "DatabaseOwner")->strarg)) == NULL) {
logg("ERROR: Failed to get information about user \"%s\".\n", logg(LOGG_INFO, "ERROR: Failed to get information about user \"%s\".\n",
optget(opts, "DatabaseOwner")->strarg); optget(opts, "DatabaseOwner")->strarg);
if (errno == 0) { if (errno == 0) {
logg("Create the \"%s\" user account for freshclam to use, or set the DatabaseOwner config option in freshclam.conf to a different user.\n", logg(LOGG_INFO, "Create the \"%s\" user account for freshclam to use, or set the DatabaseOwner config option in freshclam.conf to a different user.\n",
optget(opts, "DatabaseOwner")->strarg); optget(opts, "DatabaseOwner")->strarg);
logg("For more information, see https://docs.clamav.net/manual/Installing/Installing-from-source-Unix.html\n"); logg(LOGG_INFO, "For more information, see https://docs.clamav.net/manual/Installing/Installing-from-source-Unix.html\n");
} else { } else {
logg("An unexpected error occurred when attempting to query the \"%s\" user account.\n", logg(LOGG_INFO, "An unexpected error occurred when attempting to query the \"%s\" user account.\n",
optget(opts, "DatabaseOwner")->strarg); optget(opts, "DatabaseOwner")->strarg);
} }
status = FC_EDBDIRACCESS; status = FC_EDBDIRACCESS;
@@ -770,12 +778,12 @@ static fc_error_t initialize(struct optstruct *opts)
} }
if (chown(fcConfig.databaseDirectory, user->pw_uid, user->pw_gid)) { if (chown(fcConfig.databaseDirectory, user->pw_uid, user->pw_gid)) {
logg("!Failed to change database directory ownership to user %s. Error: %s\n", optget(opts, "DatabaseOwner")->strarg, strerror(errno)); logg(LOGG_ERROR, "Failed to change database directory ownership to user %s. Error: %s\n", optget(opts, "DatabaseOwner")->strarg, strerror(errno));
status = FC_EDBDIRACCESS; status = FC_EDBDIRACCESS;
goto done; goto done;
} }
logg("Assigned ownership of database directory to user \"%s\".\n", optget(opts, "DatabaseOwner")->strarg); logg(LOGG_INFO, "Assigned ownership of database directory to user \"%s\".\n", optget(opts, "DatabaseOwner")->strarg);
} }
#endif #endif
} }
@@ -793,7 +801,7 @@ static fc_error_t initialize(struct optstruct *opts)
*/ */
ret = drop_privileges(optget(opts, "DatabaseOwner")->strarg, NULL); ret = drop_privileges(optget(opts, "DatabaseOwner")->strarg, NULL);
if (ret) { if (ret) {
logg("!Failed to switch to %s user.\n", optget(opts, "DatabaseOwner")->strarg); logg(LOGG_ERROR, "Failed to switch to %s user.\n", optget(opts, "DatabaseOwner")->strarg);
status = FC_ECONFIG; status = FC_ECONFIG;
goto done; goto done;
} }
@@ -804,7 +812,7 @@ static fc_error_t initialize(struct optstruct *opts)
* Initilize libclamav. * Initilize libclamav.
*/ */
if (CL_SUCCESS != (cl_init_retcode = cl_init(CL_INIT_DEFAULT))) { if (CL_SUCCESS != (cl_init_retcode = cl_init(CL_INIT_DEFAULT))) {
mprintf("!initialize: Can't initialize libclamav: %s\n", cl_strerror(cl_init_retcode)); mprintf(LOGG_ERROR, "initialize: Can't initialize libclamav: %s\n", cl_strerror(cl_init_retcode));
status = FC_EINIT; status = FC_EINIT;
goto done; goto done;
} }
@@ -894,12 +902,12 @@ static fc_error_t initialize(struct optstruct *opts)
cfgfile = optget(opts, "config-file")->strarg; cfgfile = optget(opts, "config-file")->strarg;
if (CLAMSTAT(cfgfile, &statbuf) == -1) { if (CLAMSTAT(cfgfile, &statbuf) == -1) {
logg("^Can't stat %s (critical error)\n", cfgfile); logg(LOGG_WARNING, "Can't stat %s (critical error)\n", cfgfile);
status = FC_ECONFIG; status = FC_ECONFIG;
goto done; goto done;
} }
if (statbuf.st_mode & (S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH)) { if (statbuf.st_mode & (S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH)) {
logg("^Insecure permissions (for HTTPProxyPassword): %s must have no more than 0700 permissions.\n", cfgfile); logg(LOGG_WARNING, "Insecure permissions (for HTTPProxyPassword): %s must have no more than 0700 permissions.\n", cfgfile);
status = FC_ECONFIG; status = FC_ECONFIG;
goto done; goto done;
} }
@@ -917,14 +925,14 @@ static fc_error_t initialize(struct optstruct *opts)
if (optget(opts, "HTTPProxyPassword")->enabled) { if (optget(opts, "HTTPProxyPassword")->enabled) {
fcConfig.proxyPassword = optget(opts, "HTTPProxyPassword")->strarg; fcConfig.proxyPassword = optget(opts, "HTTPProxyPassword")->strarg;
} else { } else {
logg("HTTPProxyUsername requires HTTPProxyPassword\n"); logg(LOGG_INFO, "HTTPProxyUsername requires HTTPProxyPassword\n");
status = FC_ECONFIG; status = FC_ECONFIG;
goto done; goto done;
} }
} }
if (optget(opts, "HTTPProxyPort")->enabled) if (optget(opts, "HTTPProxyPort")->enabled)
fcConfig.proxyPort = (uint16_t)optget(opts, "HTTPProxyPort")->numarg; fcConfig.proxyPort = (uint16_t)optget(opts, "HTTPProxyPort")->numarg;
logg("Connecting via %s\n", fcConfig.proxyServer); logg(LOGG_INFO, "Connecting via %s\n", fcConfig.proxyServer);
} }
if (optget(opts, "HTTPUserAgent")->enabled) { if (optget(opts, "HTTPUserAgent")->enabled) {
@@ -935,9 +943,9 @@ static fc_error_t initialize(struct optstruct *opts)
/* /*
* Using the official project CDN. * Using the official project CDN.
*/ */
logg("In an effort to reduce CDN data costs, HTTPUserAgent may not be used when updating from clamav.net.\n"); logg(LOGG_INFO, "In an effort to reduce CDN data costs, HTTPUserAgent may not be used when updating from clamav.net.\n");
logg("The HTTPUserAgent specified in your config will be ignored so that FreshClam is not blocked by the CDN.\n"); logg(LOGG_INFO, "The HTTPUserAgent specified in your config will be ignored so that FreshClam is not blocked by the CDN.\n");
logg("If ClamAV's user agent is not allowed through your firewall/proxy, please contact your network administrator.\n\n"); logg(LOGG_INFO, "If ClamAV's user agent is not allowed through your firewall/proxy, please contact your network administrator.\n\n");
} else { } else {
/* /*
* Using some other CDN or private mirror. * Using some other CDN or private mirror.
@@ -956,7 +964,7 @@ static fc_error_t initialize(struct optstruct *opts)
* Initilize libfreshclam. * Initilize libfreshclam.
*/ */
if (FC_SUCCESS != (ret = fc_initialize(&fcConfig))) { if (FC_SUCCESS != (ret = fc_initialize(&fcConfig))) {
mprintf("!initialize: libfreshclam init failed.\n"); mprintf(LOGG_ERROR, "initialize: libfreshclam init failed.\n");
status = ret; status = ret;
goto done; goto done;
} }
@@ -981,10 +989,10 @@ done:
* *
* TODO: Implement system to query list of available standard and optional databases. * TODO: Implement system to query list of available standard and optional databases.
* *
* @param standardDatabases [out] Standard database string list. * @param[out] standardDatabases Standard database string list.
* @param nStandardDatabases [out] Number of standard databases in list. * @param[out] nStandardDatabases Number of standard databases in list.
* @param optionalDatabases [out] Optional database string list. * @param[out] optionalDatabases Optional database string list.
* @param nOptionalDatabases [out] Number of optional databases in list. * @param[out] nOptionalDatabases Number of optional databases in list.
* @return fc_error_t FC_SUCCESS if all databases upddated successfully. * @return fc_error_t FC_SUCCESS if all databases upddated successfully.
*/ */
fc_error_t get_official_database_lists( fc_error_t get_official_database_lists(
@@ -1001,7 +1009,7 @@ fc_error_t get_official_database_lists(
const char *hardcodedOptionalDatabaseList[] = {"safebrowsing", "test"}; const char *hardcodedOptionalDatabaseList[] = {"safebrowsing", "test"};
if ((NULL == standardDatabases) || (NULL == nStandardDatabases) || (NULL == optionalDatabases) || (NULL == nOptionalDatabases)) { if ((NULL == standardDatabases) || (NULL == nStandardDatabases) || (NULL == optionalDatabases) || (NULL == nOptionalDatabases)) {
mprintf("!get_official_database_lists: Invalid arguments.\n"); mprintf(LOGG_ERROR, "get_official_database_lists: Invalid arguments.\n");
goto done; goto done;
} }
@@ -1012,7 +1020,7 @@ fc_error_t get_official_database_lists(
for (i = 0; i < sizeof(hardcodedStandardDatabaseList) / sizeof(hardcodedStandardDatabaseList[0]); i++) { for (i = 0; i < sizeof(hardcodedStandardDatabaseList) / sizeof(hardcodedStandardDatabaseList[0]); i++) {
if (FC_SUCCESS != (ret = string_list_add(hardcodedStandardDatabaseList[i], standardDatabases, nStandardDatabases))) { if (FC_SUCCESS != (ret = string_list_add(hardcodedStandardDatabaseList[i], standardDatabases, nStandardDatabases))) {
logg("!Failed to add %s to list of standard databases.\n", hardcodedStandardDatabaseList[i]); logg(LOGG_ERROR, "Failed to add %s to list of standard databases.\n", hardcodedStandardDatabaseList[i]);
status = ret; status = ret;
goto done; goto done;
} }
@@ -1020,13 +1028,13 @@ fc_error_t get_official_database_lists(
for (i = 0; i < sizeof(hardcodedOptionalDatabaseList) / sizeof(hardcodedOptionalDatabaseList[0]); i++) { for (i = 0; i < sizeof(hardcodedOptionalDatabaseList) / sizeof(hardcodedOptionalDatabaseList[0]); i++) {
if (FC_SUCCESS != (ret = string_list_add(hardcodedOptionalDatabaseList[i], optionalDatabases, nOptionalDatabases))) { if (FC_SUCCESS != (ret = string_list_add(hardcodedOptionalDatabaseList[i], optionalDatabases, nOptionalDatabases))) {
logg("!Failed to add %s to list of optional databases.\n", hardcodedOptionalDatabaseList[i]); logg(LOGG_ERROR, "Failed to add %s to list of optional databases.\n", hardcodedOptionalDatabaseList[i]);
status = ret; status = ret;
goto done; goto done;
} }
} }
logg("*Collected lists of official standard and optional databases.\n"); logg(LOGG_DEBUG, "Collected lists of official standard and optional databases.\n");
status = FC_SUCCESS; status = FC_SUCCESS;
@@ -1061,8 +1069,8 @@ done:
* @param nOptIns Number of opt-in database strings in list. * @param nOptIns Number of opt-in database strings in list.
* @param optOutList List of standard databases that are not desired. * @param optOutList List of standard databases that are not desired.
* @param nOptOuts Number of opt-out database strings in list. * @param nOptOuts Number of opt-out database strings in list.
* @param databaseList [out] String list of desired databases. * @param[out] databaseList String list of desired databases.
* @param nDatabases [out] Number of desired databases in list. * @param[out] nDatabases Number of desired databases in list.
* @return fc_error_t * @return fc_error_t
*/ */
fc_error_t select_from_official_databases( fc_error_t select_from_official_databases(
@@ -1085,7 +1093,7 @@ fc_error_t select_from_official_databases(
uint32_t i; uint32_t i;
if ((NULL == databaseList) || (0 == nDatabases)) { if ((NULL == databaseList) || (0 == nDatabases)) {
mprintf("!select_from_official_databases: Invalid arguments.\n"); mprintf(LOGG_ERROR, "select_from_official_databases: Invalid arguments.\n");
goto done; goto done;
} }
@@ -1093,12 +1101,12 @@ fc_error_t select_from_official_databases(
*nDatabases = 0; *nDatabases = 0;
if ((0 < nOptIns) && (NULL == optInList)) { if ((0 < nOptIns) && (NULL == optInList)) {
mprintf("!select_from_official_databases: Invalid arguments. Number of opt-in databases does not match empty database array.\n"); mprintf(LOGG_ERROR, "select_from_official_databases: Invalid arguments. Number of opt-in databases does not match empty database array.\n");
goto done; goto done;
} }
if ((0 < nOptOuts) && (NULL == optOutList)) { if ((0 < nOptOuts) && (NULL == optOutList)) {
mprintf("!select_from_official_databases: Invalid arguments. Number of opt-out databases does not match empty database array.\n"); mprintf(LOGG_ERROR, "select_from_official_databases: Invalid arguments. Number of opt-out databases does not match empty database array.\n");
goto done; goto done;
} }
@@ -1106,7 +1114,7 @@ fc_error_t select_from_official_databases(
* Get lists of available databases. * Get lists of available databases.
*/ */
if (FC_SUCCESS != (ret = get_official_database_lists(&standardDatabases, &nStandardDatabases, &optionalDatabases, &nOptionalDatabases))) { if (FC_SUCCESS != (ret = get_official_database_lists(&standardDatabases, &nStandardDatabases, &optionalDatabases, &nOptionalDatabases))) {
logg("!Failed to get lists of official standard and optional databases.\n"); logg(LOGG_ERROR, "Failed to get lists of official standard and optional databases.\n");
status = ret; status = ret;
goto done; goto done;
} }
@@ -1127,13 +1135,13 @@ fc_error_t select_from_official_databases(
} }
if (skip) { if (skip) {
logg("*Opting out of standard database: %s\n", standardDatabases[i]); logg(LOGG_DEBUG, "Opting out of standard database: %s\n", standardDatabases[i]);
continue; continue;
} }
logg("*Selecting standard database: %s\n", standardDatabases[i]); logg(LOGG_DEBUG, "Selecting standard database: %s\n", standardDatabases[i]);
if (FC_SUCCESS != (ret = string_list_add(standardDatabases[i], &selectedDatabases, &nSelectedDatabases))) { if (FC_SUCCESS != (ret = string_list_add(standardDatabases[i], &selectedDatabases, &nSelectedDatabases))) {
logg("!Failed to add standard database %s to list of selected databases.\n", standardDatabases[i]); logg(LOGG_ERROR, "Failed to add standard database %s to list of selected databases.\n", standardDatabases[i]);
status = ret; status = ret;
goto done; goto done;
} }
@@ -1153,13 +1161,13 @@ fc_error_t select_from_official_databases(
} }
if (!found) { if (!found) {
logg("^Desired optional database \"%s\" is not available.\n", optInList[i]); logg(LOGG_WARNING, "Desired optional database \"%s\" is not available.\n", optInList[i]);
continue; continue;
} }
logg("*Selecting optional database: %s\n", optInList[i]); logg(LOGG_DEBUG, "Selecting optional database: %s\n", optInList[i]);
if (FC_SUCCESS != (ret = string_list_add(optInList[i], &selectedDatabases, &nSelectedDatabases))) { if (FC_SUCCESS != (ret = string_list_add(optInList[i], &selectedDatabases, &nSelectedDatabases))) {
logg("!Failed to add optional database %s to list of selected databases.\n", optInList[i]); logg(LOGG_ERROR, "Failed to add optional database %s to list of selected databases.\n", optInList[i]);
status = ret; status = ret;
goto done; goto done;
} }
@@ -1196,9 +1204,9 @@ done:
* *
* @param specificDatabaseList List of desired databases. * @param specificDatabaseList List of desired databases.
* @param nSpecificDatabases Number of databases in list. * @param nSpecificDatabases Number of databases in list.
* @param databaseList [out] String list of desired databases. * @param[out] databaseList String list of desired databases.
* @param nDatabases [out] Number of desired databases in list. * @param[out] nDatabases Number of desired databases in list.
* @param bCustom [out] "custom" selected. * @param[out] bCustom "custom" selected.
* @return fc_error_t * @return fc_error_t
*/ */
fc_error_t select_specific_databases( fc_error_t select_specific_databases(
@@ -1222,7 +1230,7 @@ fc_error_t select_specific_databases(
if ((NULL == specificDatabaseList) || (0 == nSpecificDatabases) || if ((NULL == specificDatabaseList) || (0 == nSpecificDatabases) ||
(NULL == databaseList) || (0 == nDatabases) || (NULL == databaseList) || (0 == nDatabases) ||
(NULL == bCustom)) { (NULL == bCustom)) {
mprintf("!select_from_official_databases: Invalid arguments.\n"); mprintf(LOGG_ERROR, "select_from_official_databases: Invalid arguments.\n");
goto done; goto done;
} }
@@ -1236,7 +1244,7 @@ fc_error_t select_specific_databases(
* Get lists of available databases. * Get lists of available databases.
*/ */
if (FC_SUCCESS != (ret = get_official_database_lists(&standardDatabases, &nStandardDatabases, &optionalDatabases, &nOptionalDatabases))) { if (FC_SUCCESS != (ret = get_official_database_lists(&standardDatabases, &nStandardDatabases, &optionalDatabases, &nOptionalDatabases))) {
logg("!Failed to get lists of official standard and optional databases.\n"); logg(LOGG_ERROR, "Failed to get lists of official standard and optional databases.\n");
status = ret; status = ret;
goto done; goto done;
} }
@@ -1258,7 +1266,7 @@ fc_error_t select_specific_databases(
for (j = 0; j < nStandardDatabases; j++) { for (j = 0; j < nStandardDatabases; j++) {
if (0 == strcmp(specificDatabaseList[i], standardDatabases[j])) { if (0 == strcmp(specificDatabaseList[i], standardDatabases[j])) {
if (FC_SUCCESS != (ret = string_list_add(standardDatabases[j], &selectedDatabases, &nSelectedDatabases))) { if (FC_SUCCESS != (ret = string_list_add(standardDatabases[j], &selectedDatabases, &nSelectedDatabases))) {
logg("!Failed to add standard database %s to list of selected databases.\n", standardDatabases[j]); logg(LOGG_ERROR, "Failed to add standard database %s to list of selected databases.\n", standardDatabases[j]);
status = ret; status = ret;
goto done; goto done;
} }
@@ -1271,7 +1279,7 @@ fc_error_t select_specific_databases(
for (j = 0; j < nOptionalDatabases; j++) { for (j = 0; j < nOptionalDatabases; j++) {
if (0 == strcmp(specificDatabaseList[i], optionalDatabases[j])) { if (0 == strcmp(specificDatabaseList[i], optionalDatabases[j])) {
if (FC_SUCCESS != (ret = string_list_add(optionalDatabases[j], &selectedDatabases, &nSelectedDatabases))) { if (FC_SUCCESS != (ret = string_list_add(optionalDatabases[j], &selectedDatabases, &nSelectedDatabases))) {
logg("!Failed to add optional database %s to list of selected databases.\n", optionalDatabases[j]); logg(LOGG_ERROR, "Failed to add optional database %s to list of selected databases.\n", optionalDatabases[j]);
status = ret; status = ret;
goto done; goto done;
} }
@@ -1281,7 +1289,7 @@ fc_error_t select_specific_databases(
} }
} }
if (!bFound) { if (!bFound) {
logg("!Requested database is not available: %s.\n", specificDatabaseList[i]); logg(LOGG_ERROR, "Requested database is not available: %s.\n", specificDatabaseList[i]);
status = FC_ECONFIG; status = FC_ECONFIG;
goto done; goto done;
} }
@@ -1320,7 +1328,7 @@ static fc_error_t executeIfNewVersion(
char *replace_version = NULL; char *replace_version = NULL;
if ((NULL == command) || (NULL == newVersion)) { if ((NULL == command) || (NULL == newVersion)) {
logg("!executeIfNewVersion: Invalid args\n"); logg(LOGG_ERROR, "executeIfNewVersion: Invalid args\n");
status = FC_EARG; status = FC_EARG;
goto done; goto done;
} }
@@ -1339,7 +1347,7 @@ static fc_error_t executeIfNewVersion(
while (*version) { while (*version) {
if (!strchr("0123456789.", *version)) { if (!strchr("0123456789.", *version)) {
logg("!executeIfNewVersion: OnOutdatedExecute: Incorrect version number string\n"); logg(LOGG_ERROR, "executeIfNewVersion: OnOutdatedExecute: Incorrect version number string\n");
status = FC_EARG; status = FC_EARG;
goto done; goto done;
} }
@@ -1347,7 +1355,7 @@ static fc_error_t executeIfNewVersion(
} }
modifiedCommand = (char *)malloc(strlen(command) + strlen(version) + 10); modifiedCommand = (char *)malloc(strlen(command) + strlen(version) + 10);
if (NULL == modifiedCommand) { if (NULL == modifiedCommand) {
logg("!executeIfNewVersion: Can't allocate memory for modifiedCommand\n"); logg(LOGG_ERROR, "executeIfNewVersion: Can't allocate memory for modifiedCommand\n");
status = FC_EMEM; status = FC_EMEM;
goto done; goto done;
} }
@@ -1427,17 +1435,17 @@ fc_error_t perform_database_update(
STATBUF statbuf; STATBUF statbuf;
if (NULL == serverList) { if (NULL == serverList) {
mprintf("!perform_database_update: Invalid arguments.\n"); mprintf(LOGG_ERROR, "perform_database_update: Invalid arguments.\n");
goto done; goto done;
} }
if (((NULL == databaseList) || (0 == nDatabases)) && if (((NULL == databaseList) || (0 == nDatabases)) &&
((NULL == urlDatabaseList) || (0 == nUrlDatabases))) { ((NULL == urlDatabaseList) || (0 == nUrlDatabases))) {
mprintf("!perform_database_update: No databases requested.\n"); mprintf(LOGG_ERROR, "perform_database_update: No databases requested.\n");
goto done; goto done;
} }
time(&currtime); time(&currtime);
logg("ClamAV update process started at %s", ctime(&currtime)); logg(LOGG_INFO, "ClamAV update process started at %s", ctime(&currtime));
if (bPrune) { if (bPrune) {
/* /*
@@ -1456,9 +1464,9 @@ fc_error_t perform_database_update(
* Create a temp directory to use for the update process. * Create a temp directory to use for the update process.
*/ */
if (LSTAT(g_freshclamTempDirectory, &statbuf) == -1) { if (LSTAT(g_freshclamTempDirectory, &statbuf) == -1) {
if (0 != mkdir(g_freshclamTempDirectory, 0755)) { if (0 != mkdir(g_freshclamTempDirectory, 0700)) {
logg("!Can't create temporary directory %s\n", g_freshclamTempDirectory); logg(LOGG_ERROR, "Can't create temporary directory %s\n", g_freshclamTempDirectory);
logg("Hint: The database directory must be writable for UID %d or GID %d\n", getuid(), getgid()); logg(LOGG_INFO, "Hint: The database directory must be writable for UID %d or GID %d\n", getuid(), getgid());
status = FC_EDBDIRACCESS; status = FC_EDBDIRACCESS;
goto done; goto done;
} }
@@ -1479,7 +1487,7 @@ fc_error_t perform_database_update(
(void *)fc_context, (void *)fc_context,
&nUpdated); &nUpdated);
if (FC_SUCCESS != ret) { if (FC_SUCCESS != ret) {
logg("!Database update process failed: %s\n", fc_strerror(ret)); logg(LOGG_ERROR, "Database update process failed: %s\n", fc_strerror(ret));
status = ret; status = ret;
goto done; goto done;
} }
@@ -1496,13 +1504,13 @@ fc_error_t perform_database_update(
(void *)fc_context, (void *)fc_context,
&nUpdated); &nUpdated);
if (FC_SUCCESS != ret) { if (FC_SUCCESS != ret) {
logg("!Database update process failed: %s\n", fc_strerror(ret)); logg(LOGG_ERROR, "Database update process failed: %s\n", fc_strerror(ret));
status = ret; status = ret;
goto done; goto done;
} }
nTotalUpdated += nUpdated; nTotalUpdated += nUpdated;
logg("*Database update completed successfully.\n"); logg(LOGG_DEBUG, "Database update completed successfully.\n");
} }
if (0 < nTotalUpdated) { if (0 < nTotalUpdated) {
@@ -1585,7 +1593,7 @@ int _freshclam(int argc, char **argv)
exit(FC_EINIT); exit(FC_EINIT);
if ((opts = optparse(NULL, argc, argv, 1, OPT_FRESHCLAM, 0, NULL)) == NULL) { if ((opts = optparse(NULL, argc, argv, 1, OPT_FRESHCLAM, 0, NULL)) == NULL) {
mprintf("!Can't parse command line options\n"); mprintf(LOGG_ERROR, "Can't parse command line options\n");
status = FC_EINIT; status = FC_EINIT;
goto done; goto done;
} }
@@ -1596,6 +1604,22 @@ int _freshclam(int argc, char **argv)
goto done; goto done;
} }
#ifdef _WIN32
if (optget(opts, "install-service")->enabled) {
svc_install("freshclam", "ClamAV FreshClam",
"Updates virus pattern database for ClamAV");
optfree(opts);
return 0;
}
if (optget(opts, "uninstall-service")->enabled) {
svc_uninstall("freshclam", 1);
optfree(opts);
return 0;
}
#endif
/* check foreground option from command line to override config file */ /* check foreground option from command line to override config file */
for (i = 0; i < argc; i += 1) { for (i = 0; i < argc; i += 1) {
if ((memcmp(argv[i], "--foreground", 12) == 0) || (memcmp(argv[i], "-F", 2) == 0)) { if ((memcmp(argv[i], "--foreground", 12) == 0) || (memcmp(argv[i], "-F", 2) == 0)) {
@@ -1632,7 +1656,7 @@ int _freshclam(int argc, char **argv)
goto done; goto done;
} }
if (optget(opts, "list-mirrors")->enabled) { if (optget(opts, "list-mirrors")->enabled) {
mprintf("^Deprecated option --list-mirrors. Individual mirrors are no longer tracked, as official signature distribution is now done through the CloudFlare CDN.\n"); mprintf(LOGG_WARNING, "Deprecated option --list-mirrors. Individual mirrors are no longer tracked, as official signature distribution is now done through the CloudFlare CDN.\n");
status = FC_SUCCESS; status = FC_SUCCESS;
goto done; goto done;
} }
@@ -1641,7 +1665,7 @@ int _freshclam(int argc, char **argv)
* Collect list of database servers from DatabaseMirror(s) or PrivateMirror(s). * Collect list of database servers from DatabaseMirror(s) or PrivateMirror(s).
*/ */
if (FC_SUCCESS != (ret = get_database_server_list(opts, &serverList, &nServers, &bPrivate))) { if (FC_SUCCESS != (ret = get_database_server_list(opts, &serverList, &nServers, &bPrivate))) {
mprintf("!Unable to find DatabaseMirror or PrivateMirror option(s) that specify database server FQDNs.\n"); mprintf(LOGG_ERROR, "Unable to find DatabaseMirror or PrivateMirror option(s) that specify database server FQDNs.\n");
status = ret; status = ret;
goto done; goto done;
} }
@@ -1661,7 +1685,7 @@ int _freshclam(int argc, char **argv)
* Get list of specific databases from command line args. * Get list of specific databases from command line args.
*/ */
if (FC_SUCCESS != (ret = get_string_list(optget(opts, "update-db"), &specificDatabaseList, &nSpecificDatabases))) { if (FC_SUCCESS != (ret = get_string_list(optget(opts, "update-db"), &specificDatabaseList, &nSpecificDatabases))) {
mprintf("!Error when attempting to read ExtraDatabase entries.\n"); mprintf(LOGG_ERROR, "Error when attempting to read ExtraDatabase entries.\n");
status = ret; status = ret;
goto done; goto done;
} }
@@ -1678,7 +1702,7 @@ int _freshclam(int argc, char **argv)
free_string_list(specificDatabaseList, nSpecificDatabases); free_string_list(specificDatabaseList, nSpecificDatabases);
specificDatabaseList = NULL; specificDatabaseList = NULL;
mprintf("!Failed to select specific databases from available official databases.\n"); mprintf(LOGG_ERROR, "Failed to select specific databases from available official databases.\n");
status = ret; status = ret;
goto done; goto done;
} }
@@ -1690,12 +1714,12 @@ int _freshclam(int argc, char **argv)
* Collect list of "custom"/unofficial URL-based databases. * Collect list of "custom"/unofficial URL-based databases.
*/ */
if (FC_SUCCESS != (ret = get_string_list(optget(opts, "DatabaseCustomURL"), &urlDatabaseList, &nUrlDatabases))) { if (FC_SUCCESS != (ret = get_string_list(optget(opts, "DatabaseCustomURL"), &urlDatabaseList, &nUrlDatabases))) {
mprintf("!Error when attempting to read ExcludeDatabase entries.\n"); mprintf(LOGG_ERROR, "Error when attempting to read ExcludeDatabase entries.\n");
status = ret; status = ret;
goto done; goto done;
} }
if ((NULL == urlDatabaseList) || (0 == nUrlDatabases)) { if ((NULL == urlDatabaseList) || (0 == nUrlDatabases)) {
mprintf("!--update-db=custom requires at least one DatabaseCustomURL in freshclam.conf\n"); mprintf(LOGG_ERROR, "--update-db=custom requires at least one DatabaseCustomURL in freshclam.conf\n");
status = FC_ECONFIG; status = FC_ECONFIG;
goto done; goto done;
} }
@@ -1713,7 +1737,7 @@ int _freshclam(int argc, char **argv)
* Collect list of database opt-ins. * Collect list of database opt-ins.
*/ */
if (FC_SUCCESS != (ret = get_string_list(optget(opts, "ExtraDatabase"), &optInList, &nOptIns))) { if (FC_SUCCESS != (ret = get_string_list(optget(opts, "ExtraDatabase"), &optInList, &nOptIns))) {
mprintf("!Error when attempting to read ExtraDatabase entries.\n"); mprintf(LOGG_ERROR, "Error when attempting to read ExtraDatabase entries.\n");
status = ret; status = ret;
goto done; goto done;
} }
@@ -1725,7 +1749,7 @@ int _freshclam(int argc, char **argv)
free_string_list(optInList, nOptIns); free_string_list(optInList, nOptIns);
optInList = NULL; optInList = NULL;
mprintf("!Error when attempting to read ExcludeDatabase entries.\n"); mprintf(LOGG_ERROR, "Error when attempting to read ExcludeDatabase entries.\n");
status = ret; status = ret;
goto done; goto done;
} }
@@ -1736,7 +1760,7 @@ int _freshclam(int argc, char **argv)
free_string_list(optOutList, nOptOuts); free_string_list(optOutList, nOptOuts);
optOutList = NULL; optOutList = NULL;
mprintf("!Failed to add bytecode to list of opt-out databases.\n"); mprintf(LOGG_ERROR, "Failed to add bytecode to list of opt-out databases.\n");
status = ret; status = ret;
goto done; goto done;
} }
@@ -1757,7 +1781,7 @@ int _freshclam(int argc, char **argv)
free_string_list(optOutList, nOptOuts); free_string_list(optOutList, nOptOuts);
optOutList = NULL; optOutList = NULL;
mprintf("!Failed to select databases from list of official databases.\n"); mprintf(LOGG_ERROR, "Failed to select databases from list of official databases.\n");
status = ret; status = ret;
goto done; goto done;
} }
@@ -1770,7 +1794,7 @@ int _freshclam(int argc, char **argv)
* Collect list of "custom"/unofficial URL-based databases. * Collect list of "custom"/unofficial URL-based databases.
*/ */
if (FC_SUCCESS != (ret = get_string_list(optget(opts, "DatabaseCustomURL"), &urlDatabaseList, &nUrlDatabases))) { if (FC_SUCCESS != (ret = get_string_list(optget(opts, "DatabaseCustomURL"), &urlDatabaseList, &nUrlDatabases))) {
mprintf("!Error when attempting to read ExcludeDatabase entries.\n"); mprintf(LOGG_ERROR, "Error when attempting to read ExcludeDatabase entries.\n");
status = ret; status = ret;
goto done; goto done;
} }
@@ -1783,7 +1807,7 @@ int _freshclam(int argc, char **argv)
* Initialize libraries and configuration options. * Initialize libraries and configuration options.
*/ */
if (FC_SUCCESS != initialize(opts)) { if (FC_SUCCESS != initialize(opts)) {
mprintf("!Initialization error!\n"); mprintf(LOGG_ERROR, "Initialization error!\n");
status = FC_EINIT; status = FC_EINIT;
goto done; goto done;
} }
@@ -1822,7 +1846,7 @@ int _freshclam(int argc, char **argv)
optget(opts, "NotifyClamd")->active ? optget(opts, "NotifyClamd")->strarg : NULL, optget(opts, "NotifyClamd")->active ? optget(opts, "NotifyClamd")->strarg : NULL,
&fc_context); &fc_context);
if (FC_SUCCESS != ret) { if (FC_SUCCESS != ret) {
logg("!Update failed.\n"); logg(LOGG_ERROR, "Update failed.\n");
status = ret; status = ret;
goto done; goto done;
} }
@@ -1849,14 +1873,14 @@ int _freshclam(int argc, char **argv)
checks = optget(opts, "Checks")->numarg; checks = optget(opts, "Checks")->numarg;
if (checks <= 0) { if (checks <= 0) {
logg("^Number of checks must be a positive integer.\n"); logg(LOGG_WARNING, "Number of checks must be a positive integer.\n");
status = FC_ECONFIG; status = FC_ECONFIG;
goto done; goto done;
} }
if (!optget(opts, "DNSDatabaseInfo")->enabled || optget(opts, "no-dns")->enabled) { if (!optget(opts, "DNSDatabaseInfo")->enabled || optget(opts, "no-dns")->enabled) {
if (checks > 50) { if (checks > 50) {
logg("^Number of checks must be between 1 and 50.\n"); logg(LOGG_WARNING, "Number of checks must be between 1 and 50.\n");
status = FC_ECONFIG; status = FC_ECONFIG;
goto done; goto done;
} }
@@ -1872,7 +1896,7 @@ int _freshclam(int argc, char **argv)
/* fork into background */ /* fork into background */
if (g_foreground == 0) { if (g_foreground == 0) {
if (-1 == daemonize_parent_wait(NULL, NULL)) { if (-1 == daemonize_parent_wait(NULL, NULL)) {
logg("!daemonize() failed\n"); logg(LOGG_ERROR, "daemonize() failed\n");
status = FC_EFAILEDUPDATE; status = FC_EFAILEDUPDATE;
goto done; goto done;
} }
@@ -1880,6 +1904,14 @@ int _freshclam(int argc, char **argv)
} }
#endif #endif
#ifdef _WIN32
if (optget(opts, "service-mode")->enabled) {
mprintf_disabled = 1;
svc_register("freshclam");
svc_ready();
}
#endif
/* Write PID of daemon process to pidfile. */ /* Write PID of daemon process to pidfile. */
if ((opt = optget(opts, "PidFile"))->enabled) { if ((opt = optget(opts, "PidFile"))->enabled) {
g_pidfile = opt->strarg; g_pidfile = opt->strarg;
@@ -1916,7 +1948,7 @@ int _freshclam(int argc, char **argv)
STATBUF sb; STATBUF sb;
if ((user = getpwnam(optget(opts, "DatabaseOwner")->strarg)) == NULL) { if ((user = getpwnam(optget(opts, "DatabaseOwner")->strarg)) == NULL) {
logg("^Can't get information about user %s.\n", optget(opts, "DatabaseOwner")->strarg); logg(LOGG_WARNING, "Can't get information about user %s.\n", optget(opts, "DatabaseOwner")->strarg);
fprintf(stderr, "ERROR: Can't get information about user %s.\n", optget(opts, "DatabaseOwner")->strarg); fprintf(stderr, "ERROR: Can't get information about user %s.\n", optget(opts, "DatabaseOwner")->strarg);
status = FC_ECONFIG; status = FC_ECONFIG;
goto done; goto done;
@@ -1928,7 +1960,7 @@ int _freshclam(int argc, char **argv)
if (ret) { if (ret) {
fprintf(stderr, "ERROR: lchown to user '%s' failed on freshclam.dat\n", user->pw_name); fprintf(stderr, "ERROR: lchown to user '%s' failed on freshclam.dat\n", user->pw_name);
fprintf(stderr, "Error was '%s'\n", strerror(errno)); fprintf(stderr, "Error was '%s'\n", strerror(errno));
logg("^lchown to user '%s' failed on freshclam.dat. Error was '%s'\n", logg(LOGG_WARNING, "lchown to user '%s' failed on freshclam.dat. Error was '%s'\n",
user->pw_name, strerror(errno)); user->pw_name, strerror(errno));
status = FC_ECONFIG; status = FC_ECONFIG;
goto done; goto done;
@@ -1942,7 +1974,7 @@ int _freshclam(int argc, char **argv)
*/ */
ret = drop_privileges(optget(opts, "DatabaseOwner")->strarg, logFileName); ret = drop_privileges(optget(opts, "DatabaseOwner")->strarg, logFileName);
if (0 != ret) { if (0 != ret) {
logg("!Failed to switch to %s user.\n", optget(opts, "DatabaseOwner")->strarg); logg(LOGG_ERROR, "Failed to switch to %s user.\n", optget(opts, "DatabaseOwner")->strarg);
status = FC_ECONFIG; status = FC_ECONFIG;
goto done; goto done;
} }
@@ -1950,7 +1982,7 @@ int _freshclam(int argc, char **argv)
g_active_children = 0; g_active_children = 0;
logg("#freshclam daemon %s (OS: " TARGET_OS_TYPE ", ARCH: " TARGET_ARCH_TYPE ", CPU: " TARGET_CPU_TYPE ")\n", get_version()); logg(LOGG_INFO_NF, "freshclam daemon %s (OS: " TARGET_OS_TYPE ", ARCH: " TARGET_ARCH_TYPE ", CPU: " TARGET_CPU_TYPE ")\n", get_version());
while (!g_terminate) { while (!g_terminate) {
ret = perform_database_update( ret = perform_database_update(
@@ -1970,7 +2002,7 @@ int _freshclam(int argc, char **argv)
optget(opts, "NotifyClamd")->active ? optget(opts, "NotifyClamd")->strarg : NULL, optget(opts, "NotifyClamd")->active ? optget(opts, "NotifyClamd")->strarg : NULL,
&fc_context); &fc_context);
if (FC_SUCCESS != ret) { if (FC_SUCCESS != ret) {
logg("!Update failed.\n"); logg(LOGG_ERROR, "Update failed.\n");
} }
#ifndef _WIN32 #ifndef _WIN32
@@ -1989,14 +2021,14 @@ int _freshclam(int argc, char **argv)
if (FC_EFORBIDDEN == ret) { if (FC_EFORBIDDEN == ret) {
/* We're being actively blocked, which is a fatal error. Exit. */ /* We're being actively blocked, which is a fatal error. Exit. */
logg("^FreshClam was forbidden from downloading a database.\n"); logg(LOGG_WARNING, "FreshClam was forbidden from downloading a database.\n");
logg("^This is fatal. Retrying later won't help. Exiting now.\n"); logg(LOGG_WARNING, "This is fatal. Retrying later won't help. Exiting now.\n");
status = ret; status = ret;
goto done; goto done;
} }
} }
logg("#--------------------------------------\n"); logg(LOGG_INFO_NF, "--------------------------------------\n");
#ifdef SIGALRM #ifdef SIGALRM
sigaction(SIGALRM, &sigact, &oldact); sigaction(SIGALRM, &sigact, &oldact);
#endif #endif
@@ -2017,10 +2049,10 @@ int _freshclam(int argc, char **argv)
} while (!g_terminate && (now < wakeup)); } while (!g_terminate && (now < wakeup));
if (g_terminate == -1) { if (g_terminate == -1) {
logg("Received signal: wake up\n"); logg(LOGG_INFO, "Received signal: wake up\n");
g_terminate = 0; g_terminate = 0;
} else if (g_terminate == -2) { } else if (g_terminate == -2) {
logg("Received signal: re-opening log file\n"); logg(LOGG_INFO, "Received signal: re-opening log file\n");
g_terminate = 0; g_terminate = 0;
logg_close(); logg_close();
} }

View File

@@ -57,7 +57,7 @@ int clamd_connect(const char *cfgfile, const char *option)
int sockd; int sockd;
if ((opts = optparse(cfgfile, 0, NULL, 1, OPT_CLAMD, 0, NULL)) == NULL) { if ((opts = optparse(cfgfile, 0, NULL, 1, OPT_CLAMD, 0, NULL)) == NULL) {
logg("!%s: Can't find or parse configuration file %s\n", option, logg(LOGG_ERROR, "%s: Can't find or parse configuration file %s\n", option,
cfgfile); cfgfile);
return -11; return -11;
} }
@@ -70,7 +70,7 @@ int clamd_connect(const char *cfgfile, const char *option)
server.sun_path[sizeof(server.sun_path) - 1] = '\0'; server.sun_path[sizeof(server.sun_path) - 1] = '\0';
if ((sockd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { if ((sockd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
logg("^Clamd was NOT notified: Can't create socket endpoint for %s: %s\n", logg(LOGG_WARNING, "Clamd was NOT notified: Can't create socket endpoint for %s: %s\n",
opt->strarg, strerror(errno)); opt->strarg, strerror(errno));
optfree(opts); optfree(opts);
return -1; return -1;
@@ -78,7 +78,7 @@ int clamd_connect(const char *cfgfile, const char *option)
if (connect(sockd, (struct sockaddr *)&server, if (connect(sockd, (struct sockaddr *)&server,
sizeof(struct sockaddr_un)) < 0) { sizeof(struct sockaddr_un)) < 0) {
logg("^Clamd was NOT notified: Can't connect to clamd through %s: %s\n", logg(LOGG_WARNING, "Clamd was NOT notified: Can't connect to clamd through %s: %s\n",
opt->strarg, strerror(errno)); opt->strarg, strerror(errno));
closesocket(sockd); closesocket(sockd);
optfree(opts); optfree(opts);
@@ -103,7 +103,7 @@ int clamd_connect(const char *cfgfile, const char *option)
ret = getaddrinfo(opt->strarg, port, &hints, &res); ret = getaddrinfo(opt->strarg, port, &hints, &res);
if (ret) { if (ret) {
logg("!%s: Can't resolve hostname %s (%s)\n", option, logg(LOGG_ERROR, "%s: Can't resolve hostname %s (%s)\n", option,
opt->strarg ? opt->strarg : "", opt->strarg ? opt->strarg : "",
(ret == (ret ==
EAI_SYSTEM) EAI_SYSTEM)
@@ -115,13 +115,13 @@ int clamd_connect(const char *cfgfile, const char *option)
for (p = res; p != NULL; p = p->ai_next) { for (p = res; p != NULL; p = p->ai_next) {
if ((sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) { if ((sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
logg("!%s: Can't create TCP socket to connect to %s: %s\n", logg(LOGG_ERROR, "%s: Can't create TCP socket to connect to %s: %s\n",
option, opt->strarg ? opt->strarg : "localhost", strerror(errno)); option, opt->strarg ? opt->strarg : "localhost", strerror(errno));
continue; continue;
} }
if (connect(sockd, p->ai_addr, p->ai_addrlen) == -1) { if (connect(sockd, p->ai_addr, p->ai_addrlen) == -1) {
logg("!%s: Can't connect to clamd on %s:%s: %s\n", option, logg(LOGG_ERROR, "%s: Can't connect to clamd on %s:%s: %s\n", option,
opt->strarg ? opt->strarg : "localhost", port, strerror(errno)); opt->strarg ? opt->strarg : "localhost", port, strerror(errno));
closesocket(sockd); closesocket(sockd);
continue; continue;
@@ -137,7 +137,7 @@ int clamd_connect(const char *cfgfile, const char *option)
opt = opt->nextarg; opt = opt->nextarg;
} }
} else { } else {
logg("!%s: No communication socket specified in %s\n", option, logg(LOGG_ERROR, "%s: No communication socket specified in %s\n", option,
cfgfile); cfgfile);
optfree(opts); optfree(opts);
return 1; return 1;
@@ -156,7 +156,7 @@ int notify(const char *cfgfile)
return 1; return 1;
if (sendln(sockd, "RELOAD", 7) < 0) { if (sendln(sockd, "RELOAD", 7) < 0) {
logg("!NotifyClamd: Could not write to clamd socket: %s\n", strerror(errno)); logg(LOGG_ERROR, "NotifyClamd: Could not write to clamd socket: %s\n", strerror(errno));
closesocket(sockd); closesocket(sockd);
return 1; return 1;
} }
@@ -164,13 +164,13 @@ int notify(const char *cfgfile)
memset(buff, 0, sizeof(buff)); memset(buff, 0, sizeof(buff));
if ((bread = recv(sockd, buff, sizeof(buff), 0)) > 0) { if ((bread = recv(sockd, buff, sizeof(buff), 0)) > 0) {
if (!strstr(buff, "RELOADING")) { if (!strstr(buff, "RELOADING")) {
logg("!NotifyClamd: Unknown answer from clamd: '%s'\n", buff); logg(LOGG_ERROR, "NotifyClamd: Unknown answer from clamd: '%s'\n", buff);
closesocket(sockd); closesocket(sockd);
return -1; return -1;
} }
} }
closesocket(sockd); closesocket(sockd);
logg("Clamd successfully notified about the update.\n"); logg(LOGG_INFO, "Clamd successfully notified about the update.\n");
return 0; return 0;
} }

View File

@@ -0,0 +1,339 @@
diff -wu lzma_orig//7zCrc.c 7z/7zCrc.c
--- lzma_orig//7zCrc.c 2011-06-18 01:48:31.343602685 +0200
+++ 7z/7zCrc.c 2011-06-18 01:27:02.221109100 +0200
@@ -4,24 +4,12 @@
#include "7zCrc.h"
#include "CpuArch.h"
-#define kCrcPoly 0xEDB88320
+const UInt32 g_CrcTable[256] = { 0x0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x4db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0xa00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x5005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d };
-#ifdef MY_CPU_LE
-#define CRC_NUM_TABLES 8
-#else
-#define CRC_NUM_TABLES 1
-#endif
-typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
+#define CRC_UPDATE_BYTE_2(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
-static CRC_FUNC g_CrcUpdate;
-UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
-
-#if CRC_NUM_TABLES == 1
-
-#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
-
-static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
+UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
{
const Byte *p = (const Byte *)data;
for (; size > 0; size--, p++)
@@ -29,46 +17,7 @@
return v;
}
-#else
-
-UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
-UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
-
-#endif
-
-UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
-{
- return g_CrcUpdate(v, data, size, g_CrcTable);
-}
-
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
{
- return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
-}
-
-void MY_FAST_CALL CrcGenerateTable()
-{
- UInt32 i;
- for (i = 0; i < 256; i++)
- {
- UInt32 r = i;
- unsigned j;
- for (j = 0; j < 8; j++)
- r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
- g_CrcTable[i] = r;
- }
- #if CRC_NUM_TABLES == 1
- g_CrcUpdate = CrcUpdateT1;
- #else
- for (; i < 256 * CRC_NUM_TABLES; i++)
- {
- UInt32 r = g_CrcTable[i - 256];
- g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
- }
- g_CrcUpdate = CrcUpdateT4;
- #ifdef MY_CPU_X86_OR_AMD64
- if (!CPU_Is_InOrder())
- g_CrcUpdate = CrcUpdateT8;
- #endif
- #endif
+ return CrcUpdate(CRC_INIT_VAL, data, size) ^ CRC_INIT_VAL;
}
diff -wu lzma_orig//7zCrc.h 7z/7zCrc.h
--- lzma_orig//7zCrc.h 2011-06-18 01:48:31.343602685 +0200
+++ 7z/7zCrc.h 2011-06-18 01:27:02.229109090 +0200
@@ -8,14 +8,7 @@
EXTERN_C_BEGIN
-extern UInt32 g_CrcTable[];
-
-/* Call CrcGenerateTable one time before other CRC functions */
-void MY_FAST_CALL CrcGenerateTable(void);
-
#define CRC_INIT_VAL 0xFFFFFFFF
-#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)
-#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
diff -wu lzma_orig//7zDec.c 7z/7zDec.c
--- lzma_orig//7zDec.c 2011-06-18 01:48:31.347602680 +0200
+++ 7z/7zDec.c 2011-06-18 01:27:02.229109090 +0200
@@ -3,7 +3,7 @@
#include <string.h>
-/* #define _7ZIP_PPMD_SUPPPORT */
+#define _7ZIP_PPMD_SUPPPORT
#include "7z.h"
diff -wu lzma_orig//7zFile.c 7z/7zFile.c
--- lzma_orig//7zFile.h 2011-06-18 01:48:31.347602680 +0200
+++ 7z/7zFile.h 2013-08-13 14:29:34.193054251 +0200
@@ -207,32 +207,6 @@
#endif
}
-WRes File_GetLength(CSzFile *p, UInt64 *length)
-{
- #ifdef USE_WINDOWS_FILE
-
- DWORD sizeHigh;
- DWORD sizeLow = GetFileSize(p->handle, &sizeHigh);
- if (sizeLow == 0xFFFFFFFF)
- {
- DWORD res = GetLastError();
- if (res != NO_ERROR)
- return res;
- }
- *length = (((UInt64)sizeHigh) << 32) + sizeLow;
- return 0;
-
- #else
-
- long pos = ftell(p->file);
- int res = fseek(p->file, 0, SEEK_END);
- *length = ftell(p->file);
- fseek(p->file, pos, SEEK_SET);
- return res;
-
- #endif
-}
-
/* ---------- FileSeqInStream ---------- */
diff -wu lzma_orig//7zFile.h 7z/7zFile.h
--- lzma_orig//7zFile.h 2011-06-18 01:48:31.347602680 +0200
+++ 7z/7zFile.h 2013-08-13 14:27:14.856436384 +0200
@@ -27,6 +27,7 @@
#else
FILE *file;
#endif
+ fmap_t *fmap;
} CSzFile;
void File_Construct(CSzFile *p);
@@ -48,7 +48,6 @@
WRes File_Write(CSzFile *p, const void *data, size_t *size);
WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin);
-WRes File_GetLength(CSzFile *p, UInt64 *length);
/* ---------- FileInStream ---------- */
diff -wu lzma_orig//CpuArch.h 7z/CpuArch.h
--- lzma_orig//CpuArch.h 2011-06-18 01:48:31.363602662 +0200
+++ 7z/CpuArch.h 2011-06-18 01:27:02.229109090 +0200
@@ -5,6 +5,7 @@
#define __CPU_ARCH_H
#include "Types.h"
+#include "others.h"
EXTERN_C_BEGIN
@@ -16,68 +17,8 @@
If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform.
*/
-#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)
-#define MY_CPU_AMD64
-#endif
-
-#if defined(MY_CPU_AMD64) || defined(_M_IA64)
-#define MY_CPU_64BIT
-#endif
-
-#if defined(_M_IX86) || defined(__i386__)
-#define MY_CPU_X86
-#endif
-
-#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
-#define MY_CPU_X86_OR_AMD64
-#endif
-
-#if defined(MY_CPU_X86) || defined(_M_ARM)
-#define MY_CPU_32BIT
-#endif
-
-#if defined(_WIN32) && defined(_M_ARM)
-#define MY_CPU_ARM_LE
-#endif
-
-#if defined(_WIN32) && defined(_M_IA64)
-#define MY_CPU_IA64_LE
-#endif
-
-#if defined(MY_CPU_X86_OR_AMD64)
-#define MY_CPU_LE_UNALIGN
-#endif
-
-#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__)
-#define MY_CPU_LE
-#endif
-
-#if defined(__BIG_ENDIAN__)
-#define MY_CPU_BE
-#endif
-
-#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
-Stop_Compiling_Bad_Endian
-#endif
-
-#ifdef MY_CPU_LE_UNALIGN
-
-#define GetUi16(p) (*(const UInt16 *)(p))
-#define GetUi32(p) (*(const UInt32 *)(p))
-#define GetUi64(p) (*(const UInt64 *)(p))
-#define SetUi16(p, d) *(UInt16 *)(p) = (d);
-#define SetUi32(p, d) *(UInt32 *)(p) = (d);
-#define SetUi64(p, d) *(UInt64 *)(p) = (d);
-
-#else
-
-#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
-
-#define GetUi32(p) ( \
- ((const Byte *)(p))[0] | \
- ((UInt32)((const Byte *)(p))[1] << 8) | \
- ((UInt32)((const Byte *)(p))[2] << 16) | \
- ((UInt32)((const Byte *)(p))[3] << 24))
+#define GetUi16(p) (cli_readint16(p))
+#define GetUi32(p) (cli_readint32(p))
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
@@ -85,71 +26,12 @@
((Byte *)(p))[0] = (Byte)_x_; \
((Byte *)(p))[1] = (Byte)(_x_ >> 8); }
-#define SetUi32(p, d) { UInt32 _x_ = (d); \
- ((Byte *)(p))[0] = (Byte)_x_; \
- ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
- ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
- ((Byte *)(p))[3] = (Byte)(_x_ >> 24); }
+#define SetUi32(p, d) (cli_writeint32(p, d))
#define SetUi64(p, d) { UInt64 _x64_ = (d); \
SetUi32(p, (UInt32)_x64_); \
SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }
-#endif
-
-#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
-
-#pragma intrinsic(_byteswap_ulong)
-#pragma intrinsic(_byteswap_uint64)
-#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
-#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
-
-#else
-
-#define GetBe32(p) ( \
- ((UInt32)((const Byte *)(p))[0] << 24) | \
- ((UInt32)((const Byte *)(p))[1] << 16) | \
- ((UInt32)((const Byte *)(p))[2] << 8) | \
- ((const Byte *)(p))[3] )
-
-#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
-
-#endif
-
-#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])
-
-
-#ifdef MY_CPU_X86_OR_AMD64
-
-typedef struct
-{
- UInt32 maxFunc;
- UInt32 vendor[3];
- UInt32 ver;
- UInt32 b;
- UInt32 c;
- UInt32 d;
-} Cx86cpuid;
-
-enum
-{
- CPU_FIRM_INTEL,
- CPU_FIRM_AMD,
- CPU_FIRM_VIA
-};
-
-Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
-int x86cpuid_GetFirm(const Cx86cpuid *p);
-
-#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)
-#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)
-#define x86cpuid_GetStepping(p) ((p)->ver & 0xF)
-
-Bool CPU_Is_InOrder();
-Bool CPU_Is_Aes_Supported();
-
-#endif
-
EXTERN_C_END
#endif
diff -wu lzma_orig//Types.h 7z/Types.h
--- lzma_orig//Types.h 2011-06-18 01:48:31.379602643 +0200
+++ 7z/Types.h 2011-06-18 01:27:02.229109090 +0200
@@ -21,7 +21,7 @@
#endif
EXTERN_C_BEGIN
-
+#include "fmap.h"
#define SZ_OK 0
#define SZ_ERROR_DATA 1
@@ -164,6 +164,7 @@
{
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
+ off_t curpos;
} ISeekInStream;
typedef struct

View File

@@ -90,7 +90,6 @@ int cli_7unz(cli_ctx *ctx, size_t offset)
int namelen = UTFBUFSZ; int namelen = UTFBUFSZ;
cl_error_t found = CL_CLEAN; cl_error_t found = CL_CLEAN;
Int64 begin_of_archive = offset; Int64 begin_of_archive = offset;
UInt32 viruses_found = 0;
/* Replacement for /* Replacement for
FileInStream_CreateVTable(&archiveStream); */ FileInStream_CreateVTable(&archiveStream); */
@@ -111,7 +110,7 @@ int cli_7unz(cli_ctx *ctx, size_t offset)
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
if (res == SZ_ERROR_ENCRYPTED && SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) { if (res == SZ_ERROR_ENCRYPTED && SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) {
cli_dbgmsg("cli_7unz: Encrypted header found in archive.\n"); cli_dbgmsg("cli_7unz: Encrypted header found in archive.\n");
found = cli_append_virus(ctx, "Heuristics.Encrypted.7Zip"); found = cli_append_potentially_unwanted(ctx, "Heuristics.Encrypted.7Zip");
} else if (res == SZ_OK) { } else if (res == SZ_OK) {
UInt32 i, blockIndex = 0xFFFFFFFF; UInt32 i, blockIndex = 0xFFFFFFFF;
Byte *outBuffer = 0; Byte *outBuffer = 0;
@@ -127,12 +126,14 @@ int cli_7unz(cli_ctx *ctx, size_t offset)
size_t j; size_t j;
int newnamelen, fd; int newnamelen, fd;
// abort if we would exceed max files or max scan time.
if ((found = cli_checklimits("7unz", ctx, 0, 0, 0))) if ((found = cli_checklimits("7unz", ctx, 0, 0, 0)))
break; break;
if (f->IsDir) if (f->IsDir)
continue; continue;
// skip this file if we would exceed max file size or max scan size. (we already checked for the max files and max scan time)
if (cli_checklimits("7unz", ctx, f->Size, 0, 0)) if (cli_checklimits("7unz", ctx, f->Size, 0, 0))
continue; continue;
@@ -164,20 +165,14 @@ int cli_7unz(cli_ctx *ctx, size_t offset)
encrypted = 1; encrypted = 1;
if (SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) { if (SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) {
cli_dbgmsg("cli_7unz: Encrypted files found in archive.\n"); cli_dbgmsg("cli_7unz: Encrypted files found in archive.\n");
found = cli_append_virus(ctx, "Heuristics.Encrypted.7Zip"); found = cli_append_potentially_unwanted(ctx, "Heuristics.Encrypted.7Zip");
if (found != CL_CLEAN) { if (found != CL_SUCCESS) {
if (found == CL_VIRUS) {
if (SCAN_ALLMATCHES)
viruses_found++;
} else
break; break;
} }
} }
} }
if (cli_matchmeta(ctx, name, 0, f->Size, encrypted, i, f->CrcDefined ? f->Crc : 0, NULL)) { if (CL_VIRUS == cli_matchmeta(ctx, name, 0, f->Size, encrypted, i, f->CrcDefined ? f->Crc : 0, NULL)) {
found = CL_VIRUS; found = CL_VIRUS;
viruses_found++;
if (!SCAN_ALLMATCHES)
break; break;
} }
if (res != SZ_OK) if (res != SZ_OK)
@@ -189,17 +184,18 @@ int cli_7unz(cli_ctx *ctx, size_t offset)
break; break;
cli_dbgmsg("cli_7unz: Saving to %s\n", tmp_name); cli_dbgmsg("cli_7unz: Saving to %s\n", tmp_name);
if (cli_writen(fd, outBuffer + offset, outSizeProcessed) != outSizeProcessed) if (cli_writen(fd, outBuffer + offset, outSizeProcessed) != outSizeProcessed) {
found = CL_EWRITE; found = CL_EWRITE;
else if ((found = cli_magic_scan_desc(fd, tmp_name, ctx, name)) == CL_VIRUS) }
viruses_found++;
found = cli_magic_scan_desc(fd, tmp_name, ctx, name, LAYER_ATTRIBUTES_NONE);
close(fd); close(fd);
if (!ctx->engine->keeptmp && cli_unlink(tmp_name)) if (!ctx->engine->keeptmp && cli_unlink(tmp_name))
found = CL_EUNLINK; found = CL_EUNLINK;
free(tmp_name); free(tmp_name);
if (found != CL_CLEAN) if (found != CL_SUCCESS)
if (!(SCAN_ALLMATCHES && found == CL_VIRUS))
break; break;
} }
} }
@@ -222,7 +218,5 @@ int cli_7unz(cli_ctx *ctx, size_t offset)
else else
cli_dbgmsg("cli_7unz: error %d\n", res); cli_dbgmsg("cli_7unz: error %d\n", res);
if (SCAN_ALLMATCHES && viruses_found)
return CL_VIRUS;
return found; return found;
} }

View File

@@ -0,0 +1,689 @@
# Copyright (C) 2020-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
include_directories(
${LIBXML2_INCLUDE_DIR}
${OPENSSL_INCLUDE_DIR}
${ZLIB_INCLUDE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
$<TARGET_PROPERTY:ClamAV::libunrar_iface_iface,INTERFACE_INCLUDE_DIRECTORIES>
${CMAKE_CURRENT_SOURCE_DIR}/..
)
configure_file(version.h.in version.h)
if(WIN32)
add_definitions(-DWIN32_LEAN_AND_MEAN)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
# Windows compatibility headers
include_directories(${CMAKE_SOURCE_DIR}/win32/compat)
endif()
add_definitions(-DTHIS_IS_LIBCLAMAV)
# Enable overflow checks in TomsFastMath's fp_exptmod() function.
add_definitions(-DTFM_CHECK)
# Just enable ASM in in TomsFastMath's on x86-64 where we know it works.
# on i686 we run out of registers with -fPIC, and on ia64 we miscompile.
if(NOT CMAKE_COMPILER_IS_GNUCC OR NOT (CMAKE_SIZEOF_VOID_P EQUAL 8))
add_definitions(-DTFM_NO_ASM)
endif()
# 3rd party libraries included in libclamav
add_library( regex OBJECT )
target_sources( regex
PRIVATE
regex/strlcpy.c
regex/regcomp.c
regex/regerror.c
regex/regexec.c
regex/regfree.c
PUBLIC
regex/cclass.h
regex/cname.h
regex/regex.h
regex/regex2.h
regex/utils.h )
target_include_directories( regex
PRIVATE ${CMAKE_BINARY_DIR}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} )
set_target_properties( regex PROPERTIES
COMPILE_FLAGS "${WARNCFLAGS}" )
target_link_libraries( regex
PRIVATE
PCRE2::pcre2
JSONC::jsonc )
add_library( lzma_sdk OBJECT )
target_sources( lzma_sdk
PRIVATE
7z/7zAlloc.c
7z/7zBuf.c
7z/7zBuf2.c
7z/7zCrc.c
7z/7zCrcOpt.c
7z/7zDec.c
7z/7zFile.c
7z/7zIn.c
7z/7zStream.c
7z/Bcj2.c
7z/Bra.c
7z/Bra86.c
7z/BraIA64.c
7z/CpuArch.c
7z/Delta.c
7z/Lzma2Dec.c
7z/LzmaDec.c
7z/Ppmd7.c
7z/Ppmd7Dec.c
7z/Xz.c
7z/XzCrc64.c
7z/XzDec.c
7z/XzIn.c
PUBLIC
7z/7z.h
7z/Xz.h
7z/Alloc.h
7z/7zFile.h
7z/XzCrc64.h
7z/RotateDefs.h
7z/Types.h
7z/Ppmd7.h
7z/LzmaDec.h
7z/Ppmd.h
7z/Lzma2Dec.h
7z/Delta.h
7z/CpuArch.h
7z/CpuArch.h
7z/Bra.h
7z/Bcj2.h
7z/7zVersion.h
7z/7zCrc.h
7z/7zBuf.h
7z/7zAlloc.h )
target_include_directories( lzma_sdk
PRIVATE ${CMAKE_BINARY_DIR}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} )
set_target_properties( lzma_sdk PROPERTIES
COMPILE_FLAGS "${WARNCFLAGS}" )
target_link_libraries( lzma_sdk
PRIVATE
PCRE2::pcre2
JSONC::jsonc )
if(MAINTAINER_MODE)
bison_target( yara_grammar
yara_grammar.y ${CMAKE_CURRENT_SOURCE_DIR}/yara_grammar.c )
flex_target( yara_lexer
yara_lexer.l ${CMAKE_CURRENT_SOURCE_DIR}/yara_lexer.c )
add_flex_bison_dependency( yara_lexer yara_grammar )
endif()
add_library( yara OBJECT )
target_sources( yara
PRIVATE
yara_compiler.c
yara_exec.c
yara_hash.c
yara_parser.c
yara_arena.c
${BISON_yara_grammar_OUTPUTS}
${FLEX_yara_lexer_OUTPUTS}
PUBLIC
yara_arena.h
yara_compiler.h
yara_clam.h
yara_hash.h
yara_exec.h
yara_parser.h )
if(MAINTAINER_MODE)
target_sources( yara
PRIVATE
${BISON_yara_grammar_OUTPUTS}
${FLEX_yara_lexer_OUTPUTS} )
else()
target_sources( yara
PRIVATE
yara_grammar.c
yara_lexer.c )
endif()
target_include_directories( yara
PRIVATE
${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR} )
set_target_properties( yara PROPERTIES
COMPILE_FLAGS "${WARNCFLAGS}" )
target_link_libraries( yara
PRIVATE
PCRE2::pcre2
JSONC::jsonc )
add_library( tomsfastmath OBJECT )
target_sources( tomsfastmath
PRIVATE
tomsfastmath/addsub/fp_add.c
tomsfastmath/addsub/fp_add_d.c
tomsfastmath/addsub/fp_addmod.c
tomsfastmath/addsub/fp_cmp.c
tomsfastmath/addsub/fp_cmp_d.c
tomsfastmath/addsub/fp_cmp_mag.c
tomsfastmath/addsub/fp_sub.c
tomsfastmath/addsub/fp_sub_d.c
tomsfastmath/addsub/fp_submod.c
tomsfastmath/addsub/s_fp_add.c
tomsfastmath/addsub/s_fp_sub.c
tomsfastmath/bin/fp_radix_size.c
tomsfastmath/bin/fp_read_radix.c
tomsfastmath/bin/fp_read_signed_bin.c
tomsfastmath/bin/fp_read_unsigned_bin.c
tomsfastmath/bin/fp_reverse.c
tomsfastmath/bin/fp_s_rmap.c
tomsfastmath/bin/fp_signed_bin_size.c
tomsfastmath/bin/fp_to_signed_bin.c
tomsfastmath/bin/fp_to_unsigned_bin.c
tomsfastmath/bin/fp_toradix.c
tomsfastmath/bin/fp_toradix_n.c
tomsfastmath/bin/fp_unsigned_bin_size.c
tomsfastmath/bit/fp_cnt_lsb.c
tomsfastmath/bit/fp_count_bits.c
tomsfastmath/bit/fp_div_2.c
tomsfastmath/bit/fp_div_2d.c
tomsfastmath/bit/fp_lshd.c
tomsfastmath/bit/fp_mod_2d.c
tomsfastmath/bit/fp_rshd.c
tomsfastmath/divide/fp_div.c
tomsfastmath/divide/fp_div_d.c
tomsfastmath/divide/fp_mod.c
tomsfastmath/divide/fp_mod_d.c
tomsfastmath/exptmod/fp_2expt.c
tomsfastmath/exptmod/fp_exptmod.c
tomsfastmath/misc/fp_ident.c
tomsfastmath/misc/fp_set.c
tomsfastmath/mont/fp_montgomery_calc_normalization.c
tomsfastmath/mont/fp_montgomery_reduce.c
tomsfastmath/mont/fp_montgomery_setup.c
tomsfastmath/mul/fp_mul.c
tomsfastmath/mul/fp_mul_comba.c
tomsfastmath/mul/fp_mul_2.c
tomsfastmath/mul/fp_mul_2d.c
tomsfastmath/mul/fp_mul_comba_12.c
tomsfastmath/mul/fp_mul_comba_17.c
tomsfastmath/mul/fp_mul_comba_20.c
tomsfastmath/mul/fp_mul_comba_24.c
tomsfastmath/mul/fp_mul_comba_28.c
tomsfastmath/mul/fp_mul_comba_3.c
tomsfastmath/mul/fp_mul_comba_32.c
tomsfastmath/mul/fp_mul_comba_4.c
tomsfastmath/mul/fp_mul_comba_48.c
tomsfastmath/mul/fp_mul_comba_6.c
tomsfastmath/mul/fp_mul_comba_64.c
tomsfastmath/mul/fp_mul_comba_7.c
tomsfastmath/mul/fp_mul_comba_8.c
tomsfastmath/mul/fp_mul_comba_9.c
tomsfastmath/mul/fp_mul_comba_small_set.c
tomsfastmath/mul/fp_mul_d.c
tomsfastmath/mul/fp_mulmod.c
tomsfastmath/numtheory/fp_invmod.c
tomsfastmath/sqr/fp_sqr.c
tomsfastmath/sqr/fp_sqr_comba_12.c
tomsfastmath/sqr/fp_sqr_comba_17.c
tomsfastmath/sqr/fp_sqr_comba_20.c
tomsfastmath/sqr/fp_sqr_comba_24.c
tomsfastmath/sqr/fp_sqr_comba_28.c
tomsfastmath/sqr/fp_sqr_comba_3.c
tomsfastmath/sqr/fp_sqr_comba_32.c
tomsfastmath/sqr/fp_sqr_comba_4.c
tomsfastmath/sqr/fp_sqr_comba_48.c
tomsfastmath/sqr/fp_sqr_comba_6.c
tomsfastmath/sqr/fp_sqr_comba_64.c
tomsfastmath/sqr/fp_sqr_comba_7.c
tomsfastmath/sqr/fp_sqr_comba_8.c
tomsfastmath/sqr/fp_sqr_comba_9.c
tomsfastmath/sqr/fp_sqr_comba_generic.c
tomsfastmath/sqr/fp_sqr_comba_small_set.c
tomsfastmath/sqr/fp_sqrmod.c
PUBLIC
bignum.h )
target_include_directories( tomsfastmath
PRIVATE
${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/tomsfastmath/headers
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} )
set_target_properties( tomsfastmath PROPERTIES
COMPILE_FLAGS "${WARNCFLAGS}" )
# Bytecode Runtime
add_library( bytecode_runtime OBJECT )
if(LLVM_FOUND)
target_sources( bytecode_runtime
PRIVATE
c++/detect.cpp
c++/bytecode2llvm.cpp
bytecode_priv.h
bytecode.h )
set_target_properties( bytecode_runtime PROPERTIES
COMPILE_FLAGS "${WARNCXXFLAGS} ${CXX1XCXXFLAGS}" )
target_compile_definitions( bytecode_runtime PRIVATE -D LLVM_VERSION=${LLVM_VERSION} )
target_include_directories( bytecode_runtime PRIVATE ${LLVM_INCLUDE_DIRS} )
else()
target_sources( bytecode_runtime
PRIVATE
bytecode_nojit.c
bytecode_priv.h
bytecode.h )
set_target_properties( bytecode_runtime PROPERTIES
COMPILE_FLAGS "${WARNCFLAGS}" )
endif()
target_include_directories( bytecode_runtime
PRIVATE ${CMAKE_BINARY_DIR}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} )
target_link_libraries( bytecode_runtime
PRIVATE
PCRE2::pcre2
JSONC::jsonc )
# not using an object library for the sake of Xcode compatibility
# See: https://cmake.org/pipermail/cmake/2016-May/063479.html
set(LIBCLAMAV_SOURCES
# Utils
blob.c blob.h
conv.c conv.h
fpu.c fpu.h
hashtab.c hashtab.h
iowrap.c iowrap.h
json_api.c json_api.h
jsparse/textbuf.h
others_common.c others.h
qsort.c
sf_base64decode.c sf_base64decode.h
str.c str.h
strlcat.c
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
filtering.c filtering.h
matcher-ac.c matcher-ac.h
matcher-bm.c matcher-bm.h
matcher-byte-comp.c matcher-byte-comp.h
matcher-hash.c matcher-hash.h matcher-hash-types.h
matcher-pcre.c matcher-pcre.h
matcher.c matcher.h
regex_pcre.c regex_pcre.h
# Database
cvd.c cvd.h
dconf.c dconf.h
dsig.c dsig.h
readdb.c readdb.h
# Core
cache.c cache.h
crtmgr.c crtmgr.h
crypto.c
default.h
filetypes_int.h filetypes.c filetypes.h
fmap.c fmap.h
mpool.c mpool.h
others.c
perflogging.c perflogging.h
scanners.c scanners.h
textdet.c textdet.h
version.c
# file normalization (for matching)
htmlnorm.c htmlnorm.h
jsparse/generated/keywords.h
jsparse/generated/operators.h
jsparse/js-norm.c
jsparse/js-norm.h
jsparse/lexglobal.h
textnorm.c textnorm.h
# 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
bytecode_api_decl.c
bytecode_api_impl.h
bytecode_api.c bytecode_api.h
bytecode_detect.c bytecode_detect.h
bytecode_hooks.h
bytecode_priv.h
bytecode_vm.c
bytecode.c bytecode.h
events.c events.h
type_desc.h
# utils: compression
7z_iface.c 7z_iface.h
explode.c explode.h
inffixed64.h
inflate64_priv.h inflate64.c inflate64.h
lzma_iface.c lzma_iface.h
lzw/lzwdec.c lzw/lzwdec.h
xz_iface.c xz_iface.h
# utils: encryption
arc4.c arc4.h
rijndael.c rijndael.h
# utils: text conversion
encoding_aliases.h
entconv.c entconv.h
entitylist.h
# Data-Loss-Prevention
dlp.c dlp.h
#
# FILE PARSERS
#
# autoit
autoit.c autoit.h
# binhex
binhex.c binhex.h
# cpio
cpio.c cpio.h
# install shield
ishield.c ishield.h
# cab / chm
libmspack.c libmspack.h
# msszdd
msexpand.c msexpand.h
# nsis
nsis/bzlib_private.h
nsis/bzlib.c
nsis/infblock.c
nsis/nsis_bzlib.h
nsis/nsis_zconf.h
nsis/nsis_zlib.h
nsis/nsis_zutil.h
nsis/nulsft.c nsis/nulsft.h
# office docs
hwp.c hwp.h
msdoc.c msdoc.h
msxml_parser.c msxml_parser.h
msxml.c msxml.h
ole2_extract.c ole2_extract.h
xlm_extract.c xlm_extract.h
ooxml.c ooxml.h
rtf.c rtf.h
vba_extract.c vba_extract.h
# executables
asn1.c asn1.h
elf.c elf.h
execs.c execs.h
macho.c macho.h
pe_icons.c pe_icons.h
pe_structs.h
pe.c pe.h
rebuildpe.c rebuildpe.h
# executable unpackers
aspack.c aspack.h
fsg.c fsg.h
mew.c mew.h
packlibs.c packlibs.h
petite.c petite.h
spin.c spin.h
unsp.c unsp.h
upack.c upack.h
upx.c upx.h
wwunpack.c wwunpack.h
yc.c yc.h
# mail & phishing
iana_cctld.h
iana_tld.h
line.c line.h
mbox.c mbox.h
message.c message.h
phish_domaincheck_db.c phish_domaincheck_db.h
phish_allow_list.c phish_allow_list.h
phishcheck.c phishcheck.h
regex_list.c regex_list.h
regex_suffix.c regex_suffix.h
# sis
sis.c sis.h
# tnef
tnef.c tnef.h
# uuencode
uuencode.c uuencode.h
# swf (flash)
swf.c swf.h
# pdf
pdf.c pdf.h
pdfng.c
pdfdecode.c pdfdecode.h
# xdp
xdp.c xdp.h
# ARJ archive
unarj.c unarj.h
# TAR archive
is_tar.c is_tar.h
untar.c untar.h
# ZIP archive
unzip.c unzip.h
# DMG archive
adc.c adc.h
dmg.c dmg.h
# XAR archive
xar.c xar.h
# EGG archive
egg.c egg.h
# Master Boot Record partition
mbr.c mbr.h
# GUID Parition Table partition
gpt.c gpt.h
# Apple Partition Map partition
apm.c apm.h
# HFS+ partition
hfsplus.c hfsplus.h
# iso9660 partition
iso9660.c iso9660.h
# OpenIOC
openioc.c openioc.h
# JPEG image format checker
jpeg.c jpeg.h
# PNG image format checker
png.c png.h
# TIFF image format checker
tiff.c tiff.h
# GIF image format checker
gif.c gif.h
)
if(ENABLE_SHARED_LIB)
# The clamav shared library.
add_library( clamav SHARED )
set_target_properties( clamav PROPERTIES
VERSION ${LIBCLAMAV_VERSION}
SOVERSION ${LIBCLAMAV_SOVERSION} )
target_sources( clamav
PRIVATE
${LIBCLAMAV_SOURCES}
PUBLIC
clamav.h )
if(WIN32)
target_sources( clamav PRIVATE libclamav_main.c )
endif()
target_include_directories( clamav
PRIVATE ${CMAKE_BINARY_DIR} ${JSONC_INCLUDE_DIRS}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
INTERFACE ${CMAKE_BINARY_DIR} )
target_link_libraries( clamav
PUBLIC
regex
lzma_sdk
yara
tomsfastmath
bytecode_runtime
${LIBMSPACK}
ClamAV::libclamav_rust
ClamAV::libunrar_iface_iface
OpenSSL::SSL
OpenSSL::Crypto
ZLIB::ZLIB
BZip2::BZip2
PCRE2::pcre2
LibXml2::LibXml2
JSONC::jsonc )
if(WIN32)
target_link_libraries( clamav
PUBLIC
PThreadW32::pthreadw32
ClamAV::win32_compat
wsock32 ws2_32 bcrypt )
else()
target_link_libraries( clamav
PUBLIC
Threads::Threads
Iconv::Iconv
${CMAKE_DL_LIBS}
m )
endif()
set_target_properties( clamav PROPERTIES
COMPILE_FLAGS "${WARNCFLAGS}"
VERSION ${LIBCLAMAV_VERSION} SOVERSION ${LIBCLAMAV_SOVERSION} )
if (APPLE AND CLAMAV_SIGN_FILE)
set_target_properties( clamav PROPERTIES
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ${CODE_SIGN_IDENTITY}
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM ${DEVELOPMENT_TEAM_ID}
)
endif()
if(WIN32)
set_target_properties( clamav PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
else()
target_link_libraries( clamav PUBLIC Iconv::Iconv )
endif()
if(WIN32)
install( TARGETS clamav DESTINATION . COMPONENT libraries )
install( FILES $<TARGET_PDB_FILE:clamav> DESTINATION . OPTIONAL COMPONENT libraries )
# Also install shared library (DLL) dependencies
install( CODE [[
file(GET_RUNTIME_DEPENDENCIES
LIBRARIES
$<TARGET_FILE:ClamAV::libclamav>
RESOLVED_DEPENDENCIES_VAR _r_deps
UNRESOLVED_DEPENDENCIES_VAR _u_deps
DIRECTORIES
$<TARGET_FILE_DIR:OpenSSL::SSL>
$<TARGET_FILE_DIR:OpenSSL::Crypto>
$<TARGET_FILE_DIR:ZLIB::ZLIB>
$<TARGET_FILE_DIR:BZip2::BZip2>
$<TARGET_FILE_DIR:PCRE2::pcre2>
$<TARGET_FILE_DIR:LibXml2::LibXml2>
$<TARGET_FILE_DIR:JSONC::jsonc>
)
foreach(_file ${_r_deps})
string(TOLOWER ${_file} _file_lower)
if(NOT ${_file_lower} MATCHES "c:[\\/]windows[\\/]system32.*")
file(INSTALL
DESTINATION "${CMAKE_INSTALL_PREFIX}"
TYPE SHARED_LIBRARY
FOLLOW_SYMLINK_CHAIN
FILES "${_file}"
)
endif()
endforeach()
#message("UNRESOLVED_DEPENDENCIES_VAR: ${_u_deps}")
]]
COMPONENT libraries )
else()
install( TARGETS clamav DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries )
endif()
if(LLVM_FOUND)
target_link_directories( clamav PUBLIC ${LLVM_LIBRARY_DIRS} )
target_link_libraries( clamav PUBLIC ${LLVM_LIBRARIES} )
endif()
add_library( ClamAV::libclamav ALIAS clamav )
endif()
if(ENABLE_STATIC_LIB)
# The clamav static library.
add_library( clamav_static STATIC)
target_sources( clamav_static
PRIVATE
${LIBCLAMAV_SOURCES}
PUBLIC
clamav.h )
if(WIN32)
target_sources( clamav_static PRIVATE libclamav_main.c )
endif()
target_include_directories( clamav_static
PRIVATE ${CMAKE_BINARY_DIR} ${JSONC_INCLUDE_DIRS}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
INTERFACE ${CMAKE_BINARY_DIR} )
target_link_libraries( clamav_static
PUBLIC
regex
lzma_sdk
yara
tomsfastmath
bytecode_runtime
${LIBMSPACK}
ClamAV::libclamav_rust
OpenSSL::SSL
OpenSSL::Crypto
ZLIB::ZLIB
BZip2::BZip2
PCRE2::pcre2
LibXml2::LibXml2
JSONC::jsonc )
if (ENABLE_UNRAR)
target_link_libraries( clamav_static PUBLIC ClamAV::libunrar_iface_static ClamAV::libunrar_iface_iface)
endif()
if (WIN32)
target_link_libraries( clamav_static
PUBLIC
PThreadW32::pthreadw32
ClamAV::win32_compat
wsock32 ws2_32 bcrypt )
else()
target_link_libraries( clamav_static
PUBLIC
Threads::Threads
Iconv::Iconv
${CMAKE_DL_LIBS}
m )
endif()
set_target_properties( clamav_static PROPERTIES
ARCHIVE_OUTPUT_NAME clamav_static
COMPILE_FLAGS "${WARNCFLAGS}"
VERSION ${LIBCLAMAV_VERSION} SOVERSION ${LIBCLAMAV_SOVERSION} )
target_compile_definitions( clamav_static PUBLIC clamav_staticLIB )
if(WIN32)
install( TARGETS clamav_static DESTINATION . COMPONENT libraries )
else()
install( TARGETS clamav_static DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries )
endif()
add_library( ClamAV::libclamav_static ALIAS clamav_static )
if(NOT ENABLE_SHARED_LIB)
add_library( ClamAV::libclamav ALIAS clamav_static )
endif()
endif()
install(
FILES
clamav.h
${CMAKE_BINARY_DIR}/clamav-types.h
${CMAKE_BINARY_DIR}/clamav-version.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
COMPONENT libraries)

125
clamav/libclamav/Doxyfile Normal file
View File

@@ -0,0 +1,125 @@
PROJECT_NAME = ClamAV - Libclamav
OUTPUT_DIRECTORY = ../docs/libclamav
WARNINGS = YES
FILE_PATTERNS = *.c *.h
PERL_PATH = /usr/bin/perl
SEARCHENGINE = YES
GENERATE_LATEX=NO
OPTIMIZE_OUTPUT_FOR_C=YES
HAVE_DOT=YES
CALL_GRAPH=YES
CALLER_GRAPH=YES
JAVADOC_AUTOBRIEF=YES
GENERATE_MAN=NO
EXAMPLE_PATH=examples
DOT_CLEANUP=NO
MAX_DOT_GRAPH_DEPTH=3
EXTRACT_ALL=YES
INPUT = . \
7z \
c++ \
c++/config \
c++/llvm \
c++/llvm/autoconf \
c++/llvm/autoconf/m4 \
c++/llvm/cmake \
c++/llvm/cmake/modules \
c++/llvm/docs \
c++/llvm/include \
c++/llvm/include/llvm \
c++/llvm/include/llvm/ADT \
c++/llvm/include/llvm/Analysis \
c++/llvm/include/llvm/Assembly \
c++/llvm/include/llvm/Bitcode \
c++/llvm/include/llvm-c \
c++/llvm/include/llvm/CodeGen \
c++/llvm/include/llvm/CompilerDriver \
c++/llvm/include/llvm/Config \
c++/llvm/include/llvm-c/Transforms \
c++/llvm/include/llvm/ExecutionEngine \
c++/llvm/include/llvm/MC \
c++/llvm/include/llvm/MC/MCParser \
c++/llvm/include/llvm/Support \
c++/llvm/include/llvm/System \
c++/llvm/include/llvm/Target \
c++/llvm/include/llvm/Transforms \
c++/llvm/include/llvm/Transforms/IPO \
c++/llvm/include/llvm/Transforms/Utils \
c++/llvm/lib \
c++/llvm/lib/Analysis \
c++/llvm/lib/Analysis/IPA \
c++/llvm/lib/CodeGen \
c++/llvm/lib/CodeGen/PBQP \
c++/llvm/lib/CodeGen/PBQP/Heuristics \
c++/llvm/lib/CodeGen/SelectionDAG \
c++/llvm/lib/ExecutionEngine \
c++/llvm/lib/ExecutionEngine/JIT \
c++/llvm/lib/MC \
c++/llvm/lib/Support \
c++/llvm/lib/System \
c++/llvm/lib/System/Unix \
c++/llvm/lib/System/Win32 \
c++/llvm/lib/Target \
c++/llvm/lib/Target/PowerPC \
c++/llvm/lib/Target/PowerPC/TargetInfo \
c++/llvm/lib/Target/X86 \
c++/llvm/lib/Target/X86/TargetInfo \
c++/llvm/lib/Transforms \
c++/llvm/lib/Transforms/Hello \
c++/llvm/lib/Transforms/Instrumentation \
c++/llvm/lib/Transforms/IPO \
c++/llvm/lib/Transforms/Scalar \
c++/llvm/lib/Transforms/Utils \
c++/llvm/lib/VMCore \
c++/llvm/utils \
c++/llvm/utils/bugpoint \
c++/llvm/utils/buildit \
c++/llvm/utils/count \
c++/llvm/utils/crosstool \
c++/llvm/utils/crosstool/ARM \
c++/llvm/utils/emacs \
c++/llvm/utils/git \
c++/llvm/utils/jedit \
c++/llvm/utils/lint \
c++/llvm/utils/lit \
c++/llvm/utils/lit/lit \
c++/llvm/utils/lit/lit/ExampleTests \
c++/llvm/utils/lit/lit/ExampleTests/Clang \
c++/llvm/utils/lit/lit/ExampleTests/LLVM.InTree \
c++/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test \
c++/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar \
c++/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree \
c++/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj \
c++/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test \
c++/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/Foo \
c++/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src \
c++/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test \
c++/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo \
c++/llvm/utils/lit/lit/ExampleTests.ObjDir \
c++/llvm/utils/lit/lit/ExampleTests/ShExternal \
c++/llvm/utils/lit/lit/ExampleTests/ShInternal \
c++/llvm/utils/lit/lit/ExampleTests/TclTest \
c++/llvm/utils/llvm-lit \
c++/llvm/utils/Misc \
c++/llvm/utils/TableGen \
c++/llvm/utils/valgrind \
c++/llvm/utils/vim \
c++/m4 \
jsparse \
jsparse/generated \
nsis \
regex \
tomsfastmath \
tomsfastmath/addsub \
tomsfastmath/bin \
tomsfastmath/bit \
tomsfastmath/divide \
tomsfastmath/exptmod \
tomsfastmath/misc \
tomsfastmath/mont \
tomsfastmath/mul \
tomsfastmath/numtheory \
tomsfastmath/sqr

Some files were not shown because too many files have changed in this diff Show More