2016-03-11 13:32:31 -07:00
|
|
|
/*
|
2025-02-14 10:24:30 -05:00
|
|
|
* Copyright (C) 2013-2025 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
|
2019-01-25 10:15:50 -05:00
|
|
|
* Copyright (C) 2007-2013 Sourcefire, Inc.
|
|
|
|
* Copyright (C) 2002-2007 Tomasz Kojm <tkojm@clamav.net>
|
2016-03-11 13:32:31 -07:00
|
|
|
*
|
|
|
|
* 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 <stdint.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2018-12-03 12:40:13 -05:00
|
|
|
#ifdef HAVE_UNISTD_H
|
2016-03-11 13:32:31 -07:00
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <sys/types.h>
|
2019-03-26 15:09:52 -04:00
|
|
|
#include <dirent.h>
|
2018-12-03 12:40:13 -05:00
|
|
|
#ifndef _WIN32
|
2016-03-11 13:32:31 -07:00
|
|
|
#include <sys/wait.h>
|
|
|
|
#endif
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
2018-12-03 12:40:13 -05:00
|
|
|
#ifdef HAVE_PWD_H
|
2016-03-11 13:32:31 -07:00
|
|
|
#include <pwd.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_GRP_H
|
|
|
|
#include <grp.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(USE_SYSLOG) && !defined(C_AIX)
|
|
|
|
#include <syslog.h>
|
|
|
|
#endif
|
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
#include <curl/curl.h>
|
|
|
|
|
2016-03-11 13:32:31 -07:00
|
|
|
#include "target.h"
|
Add CMake build tooling
This patch adds experimental-quality CMake build tooling.
The libmspack build required a modification to use "" instead of <> for
header #includes. This will hopefully be included in the libmspack
upstream project when adding CMake build tooling to libmspack.
Removed use of libltdl when using CMake.
Flex & Bison are now required to build.
If -DMAINTAINER_MODE, then GPERF is also required, though it currently
doesn't actually do anything. TODO!
I found that the autotools build system was generating the lexer output
but not actually compiling it, instead using previously generated (and
manually renamed) lexer c source. As a consequence, changes to the .l
and .y files weren't making it into the build. To resolve this, I
removed generated flex/bison files and fixed the tooling to use the
freshly generated files. Flex and bison are now required build tools.
On Windows, this adds a dependency on the winflexbison package,
which can be obtained using Chocolatey or may be manually installed.
CMake tooling only has partial support for building with external LLVM
library, and no support for the internal LLVM (to be removed in the
future). I.e. The CMake build currently only supports the bytecode
interpreter.
Many files used include paths relative to the top source directory or
relative to the current project, rather than relative to each build
target. Modern CMake support requires including internal dependency
headers the same way you would external dependency headers (albeit
with "" instead of <>). This meant correcting all header includes to
be relative to the build targets and not relative to the workspace.
For example, ...
```c
include "../libclamav/clamav.h"
include "clamd/clamd_others.h"
```
... becomes:
```c
// libclamav
include "clamav.h"
// clamd
include "clamd_others.h"
```
Fixes header name conflicts by renaming a few of the files.
Converted the "shared" code into a static library, which depends on
libclamav. The ironically named "shared" static library provides
features common to the ClamAV apps which are not required in
libclamav itself and are not intended for use by downstream projects.
This change was required for correct modern CMake practices but was
also required to use the automake "subdir-objects" option.
This eliminates warnings when running autoreconf which, in the next
version of autoconf & automake are likely to break the build.
libclamav used to build in multiple stages where an earlier stage is
a static library containing utils required by the "shared" code.
Linking clamdscan and clamdtop with this libclamav utils static lib
allowed these two apps to function without libclamav. While this is
nice in theory, the practical gains are minimal and it complicates
the build system. As such, the autotools and CMake tooling was
simplified for improved maintainability and this feature was thrown
out. clamdtop and clamdscan now require libclamav to function.
Removed the nopthreads version of the autotools
libclamav_internal_utils static library and added pthread linking to
a couple apps that may have issues building on some platforms without
it, with the intention of removing needless complexity from the
source. Kept the regular version of libclamav_internal_utils.la
though it is no longer used anywhere but in libclamav.
Added an experimental doxygen build option which attempts to build
clamav.h and libfreshclam doxygen html docs.
The CMake build tooling also may build the example program(s), which
isn't a feature in the Autotools build system.
Changed C standard to C90+ due to inline linking issues with socket.h
when linking libfreshclam.so on Linux.
Generate common.rc for win32.
Fix tabs/spaces in shared Makefile.am, and remove vestigial ifndef
from misc.c.
Add CMake files to the automake dist, so users can try the new
CMake tooling w/out having to build from a git clone.
clamonacc changes:
- Renamed FANOTIFY macro to HAVE_SYS_FANOTIFY_H to better match other
similar macros.
- Added a new clamav-clamonacc.service systemd unit file, based on
the work of ChadDevOps & Aaron Brighton.
- Added missing clamonacc man page.
Updates to clamdscan man page, add missing options.
Remove vestigial CL_NOLIBCLAMAV definitions (all apps now use
libclamav).
Rename Windows mspack.dll to libmspack.dll so all ClamAV-built
libraries have the lib-prefix with Visual Studio as with CMake.
2020-08-13 00:25:34 -07:00
|
|
|
|
|
|
|
// libclamav
|
2016-03-11 13:32:31 -07:00
|
|
|
#include "clamav.h"
|
2023-04-12 22:49:17 -07:00
|
|
|
#include "clamav_rust.h"
|
Add CMake build tooling
This patch adds experimental-quality CMake build tooling.
The libmspack build required a modification to use "" instead of <> for
header #includes. This will hopefully be included in the libmspack
upstream project when adding CMake build tooling to libmspack.
Removed use of libltdl when using CMake.
Flex & Bison are now required to build.
If -DMAINTAINER_MODE, then GPERF is also required, though it currently
doesn't actually do anything. TODO!
I found that the autotools build system was generating the lexer output
but not actually compiling it, instead using previously generated (and
manually renamed) lexer c source. As a consequence, changes to the .l
and .y files weren't making it into the build. To resolve this, I
removed generated flex/bison files and fixed the tooling to use the
freshly generated files. Flex and bison are now required build tools.
On Windows, this adds a dependency on the winflexbison package,
which can be obtained using Chocolatey or may be manually installed.
CMake tooling only has partial support for building with external LLVM
library, and no support for the internal LLVM (to be removed in the
future). I.e. The CMake build currently only supports the bytecode
interpreter.
Many files used include paths relative to the top source directory or
relative to the current project, rather than relative to each build
target. Modern CMake support requires including internal dependency
headers the same way you would external dependency headers (albeit
with "" instead of <>). This meant correcting all header includes to
be relative to the build targets and not relative to the workspace.
For example, ...
```c
include "../libclamav/clamav.h"
include "clamd/clamd_others.h"
```
... becomes:
```c
// libclamav
include "clamav.h"
// clamd
include "clamd_others.h"
```
Fixes header name conflicts by renaming a few of the files.
Converted the "shared" code into a static library, which depends on
libclamav. The ironically named "shared" static library provides
features common to the ClamAV apps which are not required in
libclamav itself and are not intended for use by downstream projects.
This change was required for correct modern CMake practices but was
also required to use the automake "subdir-objects" option.
This eliminates warnings when running autoreconf which, in the next
version of autoconf & automake are likely to break the build.
libclamav used to build in multiple stages where an earlier stage is
a static library containing utils required by the "shared" code.
Linking clamdscan and clamdtop with this libclamav utils static lib
allowed these two apps to function without libclamav. While this is
nice in theory, the practical gains are minimal and it complicates
the build system. As such, the autotools and CMake tooling was
simplified for improved maintainability and this feature was thrown
out. clamdtop and clamdscan now require libclamav to function.
Removed the nopthreads version of the autotools
libclamav_internal_utils static library and added pthread linking to
a couple apps that may have issues building on some platforms without
it, with the intention of removing needless complexity from the
source. Kept the regular version of libclamav_internal_utils.la
though it is no longer used anywhere but in libclamav.
Added an experimental doxygen build option which attempts to build
clamav.h and libfreshclam doxygen html docs.
The CMake build tooling also may build the example program(s), which
isn't a feature in the Autotools build system.
Changed C standard to C90+ due to inline linking issues with socket.h
when linking libfreshclam.so on Linux.
Generate common.rc for win32.
Fix tabs/spaces in shared Makefile.am, and remove vestigial ifndef
from misc.c.
Add CMake files to the automake dist, so users can try the new
CMake tooling w/out having to build from a git clone.
clamonacc changes:
- Renamed FANOTIFY macro to HAVE_SYS_FANOTIFY_H to better match other
similar macros.
- Added a new clamav-clamonacc.service systemd unit file, based on
the work of ChadDevOps & Aaron Brighton.
- Added missing clamonacc man page.
Updates to clamdscan man page, add missing options.
Remove vestigial CL_NOLIBCLAMAV definitions (all apps now use
libclamav).
Rename Windows mspack.dll to libmspack.dll so all ClamAV-built
libraries have the lib-prefix with Visual Studio as with CMake.
2020-08-13 00:25:34 -07:00
|
|
|
#include "others.h"
|
|
|
|
#include "regex_list.h"
|
|
|
|
#include "str.h"
|
|
|
|
|
2021-03-04 19:39:50 -08:00
|
|
|
// common
|
Add CMake build tooling
This patch adds experimental-quality CMake build tooling.
The libmspack build required a modification to use "" instead of <> for
header #includes. This will hopefully be included in the libmspack
upstream project when adding CMake build tooling to libmspack.
Removed use of libltdl when using CMake.
Flex & Bison are now required to build.
If -DMAINTAINER_MODE, then GPERF is also required, though it currently
doesn't actually do anything. TODO!
I found that the autotools build system was generating the lexer output
but not actually compiling it, instead using previously generated (and
manually renamed) lexer c source. As a consequence, changes to the .l
and .y files weren't making it into the build. To resolve this, I
removed generated flex/bison files and fixed the tooling to use the
freshly generated files. Flex and bison are now required build tools.
On Windows, this adds a dependency on the winflexbison package,
which can be obtained using Chocolatey or may be manually installed.
CMake tooling only has partial support for building with external LLVM
library, and no support for the internal LLVM (to be removed in the
future). I.e. The CMake build currently only supports the bytecode
interpreter.
Many files used include paths relative to the top source directory or
relative to the current project, rather than relative to each build
target. Modern CMake support requires including internal dependency
headers the same way you would external dependency headers (albeit
with "" instead of <>). This meant correcting all header includes to
be relative to the build targets and not relative to the workspace.
For example, ...
```c
include "../libclamav/clamav.h"
include "clamd/clamd_others.h"
```
... becomes:
```c
// libclamav
include "clamav.h"
// clamd
include "clamd_others.h"
```
Fixes header name conflicts by renaming a few of the files.
Converted the "shared" code into a static library, which depends on
libclamav. The ironically named "shared" static library provides
features common to the ClamAV apps which are not required in
libclamav itself and are not intended for use by downstream projects.
This change was required for correct modern CMake practices but was
also required to use the automake "subdir-objects" option.
This eliminates warnings when running autoreconf which, in the next
version of autoconf & automake are likely to break the build.
libclamav used to build in multiple stages where an earlier stage is
a static library containing utils required by the "shared" code.
Linking clamdscan and clamdtop with this libclamav utils static lib
allowed these two apps to function without libclamav. While this is
nice in theory, the practical gains are minimal and it complicates
the build system. As such, the autotools and CMake tooling was
simplified for improved maintainability and this feature was thrown
out. clamdtop and clamdscan now require libclamav to function.
Removed the nopthreads version of the autotools
libclamav_internal_utils static library and added pthread linking to
a couple apps that may have issues building on some platforms without
it, with the intention of removing needless complexity from the
source. Kept the regular version of libclamav_internal_utils.la
though it is no longer used anywhere but in libclamav.
Added an experimental doxygen build option which attempts to build
clamav.h and libfreshclam doxygen html docs.
The CMake build tooling also may build the example program(s), which
isn't a feature in the Autotools build system.
Changed C standard to C90+ due to inline linking issues with socket.h
when linking libfreshclam.so on Linux.
Generate common.rc for win32.
Fix tabs/spaces in shared Makefile.am, and remove vestigial ifndef
from misc.c.
Add CMake files to the automake dist, so users can try the new
CMake tooling w/out having to build from a git clone.
clamonacc changes:
- Renamed FANOTIFY macro to HAVE_SYS_FANOTIFY_H to better match other
similar macros.
- Added a new clamav-clamonacc.service systemd unit file, based on
the work of ChadDevOps & Aaron Brighton.
- Added missing clamonacc man page.
Updates to clamdscan man page, add missing options.
Remove vestigial CL_NOLIBCLAMAV definitions (all apps now use
libclamav).
Rename Windows mspack.dll to libmspack.dll so all ClamAV-built
libraries have the lib-prefix with Visual Studio as with CMake.
2020-08-13 00:25:34 -07:00
|
|
|
#include "cert_util.h"
|
|
|
|
#include "output.h"
|
|
|
|
#include "misc.h"
|
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
#include "libfreshclam.h"
|
|
|
|
#include "libfreshclam_internal.h"
|
|
|
|
#include "dns.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Private functions
|
|
|
|
*/
|
2016-03-11 13:32:31 -07:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
/*
|
|
|
|
* libclamav API functions
|
|
|
|
*/
|
|
|
|
const char *fc_strerror(fc_error_t fcerror)
|
|
|
|
{
|
|
|
|
switch (fcerror) {
|
|
|
|
case FC_SUCCESS:
|
|
|
|
return "Success";
|
|
|
|
case FC_UPTODATE:
|
|
|
|
return "Up-to-date";
|
|
|
|
case FC_EINIT:
|
2023-11-26 15:01:19 -08:00
|
|
|
return "Failed to initialize";
|
2019-03-26 15:09:52 -04:00
|
|
|
case FC_EDIRECTORY:
|
2023-11-26 15:01:19 -08:00
|
|
|
return "Invalid, nonexistent, or inaccessible directory";
|
2019-03-26 15:09:52 -04:00
|
|
|
case FC_EFILE:
|
2023-11-26 15:01:19 -08:00
|
|
|
return "Invalid, nonexistent, or inaccessible file";
|
2019-03-26 15:09:52 -04:00
|
|
|
case FC_ECONNECTION:
|
|
|
|
return "Connection failed";
|
|
|
|
case FC_EEMPTYFILE:
|
|
|
|
return "Empty file";
|
|
|
|
case FC_EBADCVD:
|
|
|
|
return "Invalid or corrupted CVD/CLD database";
|
|
|
|
case FC_ETESTFAIL:
|
|
|
|
return "Test failed";
|
|
|
|
case FC_ECONFIG:
|
|
|
|
return "Invalid configuration settings(s)";
|
|
|
|
case FC_EDBDIRACCESS:
|
|
|
|
return "Failed to read/write file to database directory";
|
|
|
|
case FC_EFAILEDGET:
|
|
|
|
return "HTTP GET failed";
|
|
|
|
case FC_EMIRRORNOTSYNC:
|
|
|
|
return "Downloaded database had lower version than advertised";
|
|
|
|
case FC_ELOGGING:
|
|
|
|
return "Failed to write to log";
|
|
|
|
case FC_EFAILEDUPDATE:
|
|
|
|
return "Failed to update database";
|
|
|
|
case FC_EMEM:
|
|
|
|
return "Memory allocation error";
|
|
|
|
case FC_EARG:
|
|
|
|
return "Invalid argument(s)";
|
2021-03-20 21:25:18 -07:00
|
|
|
case FC_EFORBIDDEN:
|
2021-03-25 13:31:46 -07:00
|
|
|
return "Forbidden; Blocked by CDN";
|
2021-03-20 21:25:18 -07:00
|
|
|
case FC_ERETRYLATER:
|
2021-03-25 13:31:46 -07:00
|
|
|
return "Too many requests; Retry later";
|
2019-03-26 15:09:52 -04:00
|
|
|
default:
|
|
|
|
return "Unknown libfreshclam error code!";
|
|
|
|
}
|
|
|
|
}
|
2016-03-11 13:32:31 -07:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
fc_error_t fc_initialize(fc_config *fcConfig)
|
2016-03-11 13:32:31 -07:00
|
|
|
{
|
2019-03-26 15:09:52 -04:00
|
|
|
fc_error_t status = FC_EARG;
|
|
|
|
STATBUF statbuf;
|
FIPS-compliant CVD signing and verification
Add X509 certificate chain based signing with PKCS7-PEM external
signatures distributed alongside CVD's in a custom .cvd.sign format.
This new signing and verification mechanism is primarily in support
of FIPS compliance.
Fixes: https://github.com/Cisco-Talos/clamav/issues/564
Add a Rust implementation for parsing, verifying, and unpacking CVD
files.
Now installs a 'certs' directory in the app config directory
(e.g. <prefix>/etc/certs). The install location is configurable.
The CMake option to configure the CVD certs directory is:
`-D CVD_CERTS_DIRECTORY=PATH`
New options to set an alternative CVD certs directory:
- Commandline for freshclam, clamd, clamscan, and sigtool is:
`--cvdcertsdir PATH`
- Env variable for freshclam, clamd, clamscan, and sigtool is:
`CVD_CERTS_DIR`
- Config option for freshclam and clamd is:
`CVDCertsDirectory PATH`
Sigtool:
- Add sign/verify commands.
- Also verify CDIFF external digital signatures when applying CDIFFs.
- Place commonly used commands at the top of --help string.
- Fix up manpage.
Freshclam:
- Will try to download .sign files to verify CVDs and CDIFFs.
- Fix an issue where making a CLD would only include the CFG file for
daily and not if patching any other database.
libclamav.so:
- Bump version to 13:0:1 (aka 12.1.0).
- Also remove libclamav.map versioning.
Resolves: https://github.com/Cisco-Talos/clamav/issues/1304
- Add two new API's to the public clamav.h header:
```c
extern cl_error_t cl_cvdverify_ex(const char *file,
const char *certs_directory);
extern cl_error_t cl_cvdunpack_ex(const char *file,
const char *dir,
bool dont_verify,
const char *certs_directory);
```
The original `cl_cvdverify` and `cl_cvdunpack` are deprecated.
- Add `cl_engine_field` enum option `CL_ENGINE_CVDCERTSDIR`.
You may set this option with `cl_engine_set_str` and get it
with `cl_engine_get_str`, to override the compiled in default
CVD certs directory.
libfreshclam.so: Bump version to 4:0:0 (aka 4.0.0).
Add sigtool sign/verify tests and test certs.
Make it so downloadFile doesn't throw a warning if the server
doesn't have the .sign file.
Replace use of md5-based FP signatures in the unit tests with
sha256-based FP signatures because the md5 implementation used
by Python may be disabled in FIPS mode.
Fixes: https://github.com/Cisco-Talos/clamav/issues/1411
CMake: Add logic to enable the Rust openssl-sys / openssl-rs crates
to build against the same OpenSSL library as is used for the C build.
The Rust unit test application must also link directly with libcrypto
and libssl.
Fix some log messages with missing new lines.
Fix missing environment variable notes in --help messages and manpages.
Deconflict CONFDIR/DATADIR/CERTSDIR variable names that are defined in
clamav-config.h.in for libclamav from variable that had the same name
for use in clamav applications that use the optparser.
The 'clamav-test' certs for the unit tests will live for 10 years.
The 'clamav-beta.crt' public cert will only live for 120 days and will
be replaced before the stable release with a production 'clamav.crt'.
2024-11-21 14:01:09 -05:00
|
|
|
char *certsDirectory = NULL;
|
|
|
|
FFIError *new_verifier_error = NULL;
|
2019-03-26 15:09:52 -04:00
|
|
|
|
|
|
|
if (NULL == fcConfig) {
|
|
|
|
printf("fc_initialize: Invalid arguments.\n");
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2023-04-12 22:49:17 -07:00
|
|
|
/* Rust logging initialization */
|
|
|
|
if (!clrs_log_init()) {
|
|
|
|
cli_dbgmsg("Unexpected problem occurred while setting up rust logging... continuing without rust logging. \
|
|
|
|
Please submit an issue to https://github.com/Cisco-Talos/clamav");
|
|
|
|
}
|
|
|
|
|
2023-11-26 15:01:19 -08:00
|
|
|
/* Initialize libcurl */
|
2019-03-26 15:09:52 -04:00
|
|
|
curl_global_init(CURL_GLOBAL_ALL);
|
|
|
|
|
|
|
|
/* Initialize mprintf options */
|
|
|
|
if (fcConfig->msgFlags & FC_CONFIG_MSG_DEBUG) cl_debug();
|
|
|
|
mprintf_verbose = (fcConfig->msgFlags & FC_CONFIG_MSG_VERBOSE) ? 1 : 0;
|
|
|
|
mprintf_quiet = (fcConfig->msgFlags & FC_CONFIG_MSG_QUIET) ? 1 : 0;
|
|
|
|
mprintf_nowarn = (fcConfig->msgFlags & FC_CONFIG_MSG_NOWARN) ? 1 : 0;
|
|
|
|
mprintf_stdout = (fcConfig->msgFlags & FC_CONFIG_MSG_STDOUT) ? 1 : 0;
|
|
|
|
mprintf_progress = (fcConfig->msgFlags & FC_CONFIG_MSG_SHOWPROGRESS) ? 1 : 0;
|
|
|
|
|
|
|
|
/* Initialize logger */
|
|
|
|
logg_verbose = (fcConfig->logFlags & FC_CONFIG_LOG_VERBOSE) ? 1 : 0;
|
|
|
|
logg_nowarn = (fcConfig->logFlags & FC_CONFIG_LOG_NOWARN) ? 1 : 0;
|
|
|
|
logg_time = (fcConfig->logFlags & FC_CONFIG_LOG_TIME) ? 1 : 0;
|
|
|
|
logg_rotate = (fcConfig->logFlags & FC_CONFIG_LOG_ROTATE) ? 1 : 0;
|
|
|
|
logg_size = fcConfig->maxLogSize;
|
2019-05-21 14:49:42 -04:00
|
|
|
/* Set a log file if requested, and is not already set */
|
|
|
|
if ((NULL == logg_file) && (NULL != fcConfig->logFile)) {
|
2024-01-09 17:44:33 -05:00
|
|
|
logg_file = cli_safer_strdup(fcConfig->logFile);
|
2022-02-16 00:13:55 +01:00
|
|
|
if (0 != logg(LOGG_INFO_NF, "--------------------------------------\n")) {
|
|
|
|
mprintf(LOGG_ERROR, "Problem with internal logger (UpdateLogFile = %s).\n", logg_file);
|
2019-03-26 15:09:52 -04:00
|
|
|
status = FC_ELOGGING;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(USE_SYSLOG) && !defined(C_AIX)
|
2019-05-21 14:49:42 -04:00
|
|
|
/* Initialize syslog if available and requested, and is not already set */
|
2019-03-26 15:09:52 -04:00
|
|
|
if (fcConfig->logFlags & FC_CONFIG_LOG_SYSLOG) {
|
|
|
|
int logFacility = LOG_LOCAL6;
|
2019-05-21 14:49:42 -04:00
|
|
|
if ((0 == logg_syslog) && (NULL != fcConfig->logFacility) && (-1 == (logFacility = logg_facility(fcConfig->logFacility)))) {
|
2022-02-16 00:13:55 +01:00
|
|
|
mprintf(LOGG_ERROR, "LogFacility: %s: No such facility.\n", fcConfig->logFacility);
|
2019-03-26 15:09:52 -04:00
|
|
|
status = FC_ELOGGING;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
openlog("freshclam", LOG_PID, logFacility);
|
|
|
|
logg_syslog = 1;
|
|
|
|
}
|
2016-03-11 13:32:31 -07:00
|
|
|
#endif
|
2019-03-26 15:09:52 -04:00
|
|
|
|
|
|
|
/* Optional connection settings. */
|
|
|
|
if (NULL != fcConfig->localIP) {
|
2019-09-18 14:38:43 -04:00
|
|
|
#if !((LIBCURL_VERSION_MAJOR > 7) || ((LIBCURL_VERSION_MAJOR == 7) && (LIBCURL_VERSION_MINOR >= 33)))
|
2022-02-16 00:13:55 +01:00
|
|
|
mprintf(LOGG_ERROR, "The LocalIP feature was requested but this local IP support is not presently available.\n");
|
|
|
|
mprintf(LOGG_ERROR, "Your installation was built with libcurl version %u.%u.%u.\n", LIBCURL_VERSION_MAJOR, LIBCURL_VERSION_MINOR, LIBCURL_VERSION_PATCH);
|
|
|
|
mprintf(LOGG_ERROR, "LocalIP requires libcurl version 7.33.0 or higher and must include the c-ares optional dependency.\n");
|
2019-03-26 15:09:52 -04:00
|
|
|
#else
|
2024-01-09 17:44:33 -05:00
|
|
|
g_localIP = cli_safer_strdup(fcConfig->localIP);
|
2019-03-26 15:09:52 -04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
if (NULL != fcConfig->userAgent) {
|
2024-01-09 17:44:33 -05:00
|
|
|
g_userAgent = cli_safer_strdup(fcConfig->userAgent);
|
2019-03-26 15:09:52 -04:00
|
|
|
}
|
|
|
|
if (NULL != fcConfig->proxyServer) {
|
2024-01-09 17:44:33 -05:00
|
|
|
g_proxyServer = cli_safer_strdup(fcConfig->proxyServer);
|
2019-03-26 15:09:52 -04:00
|
|
|
if (0 != fcConfig->proxyPort) {
|
|
|
|
g_proxyPort = fcConfig->proxyPort;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Proxy port not provided. Look up the default port for
|
|
|
|
* webcache in /etc/services.
|
|
|
|
* Default to 8080 if not provided.
|
|
|
|
*/
|
|
|
|
const struct servent *webcache = getservbyname("webcache", "TCP");
|
|
|
|
|
|
|
|
if (webcache)
|
|
|
|
g_proxyPort = ntohs(webcache->s_port);
|
|
|
|
else
|
|
|
|
g_proxyPort = 8080;
|
|
|
|
|
|
|
|
endservent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (NULL != fcConfig->proxyUsername) {
|
2024-01-09 17:44:33 -05:00
|
|
|
g_proxyUsername = cli_safer_strdup(fcConfig->proxyUsername);
|
2019-03-26 15:09:52 -04:00
|
|
|
}
|
|
|
|
if (NULL != fcConfig->proxyPassword) {
|
2024-01-09 17:44:33 -05:00
|
|
|
g_proxyPassword = cli_safer_strdup(fcConfig->proxyPassword);
|
2019-03-26 15:09:52 -04:00
|
|
|
}
|
|
|
|
|
2019-05-21 16:12:17 -04:00
|
|
|
#ifdef _WIN32
|
|
|
|
if ((fcConfig->databaseDirectory[strlen(fcConfig->databaseDirectory) - 1] != '/') &&
|
|
|
|
((fcConfig->databaseDirectory[strlen(fcConfig->databaseDirectory) - 1] != '\\'))) {
|
|
|
|
#else
|
|
|
|
if (fcConfig->databaseDirectory[strlen(fcConfig->databaseDirectory) - 1] != '/') {
|
|
|
|
#endif
|
Remove max-allocation limits where not required
The cli_max_malloc, cli_max_calloc, and cli_max_realloc functions
provide a way to protect against allocating too much memory
when the size of the allocation is derived from the untrusted input.
Specifically, we worry about values in the file being scanned being
manipulated to exhaust the RAM and crash the application.
There is no need to check the limits if the size of the allocation
is fixed, or if the size of the allocation is necessary for signature
loading, or the general operation of the applications.
E.g. checking the max-allocation limit for the size of a hash, or
for the size of the scan recursion stack, is a complete waste of
time.
Although we significantly increased the max-allocation limit in
a recent release, it is best not to check an allocation if the
allocation will be safe. It would be a waste of time.
I am also hopeful that if we can reduce the number allocations
that require a limit-check to those that require it for the safe
scan of a file, then eventually we can store the limit in the scan-
context, and make it configurable.
2024-01-08 22:48:28 -05:00
|
|
|
g_databaseDirectory = malloc(strlen(fcConfig->databaseDirectory) + strlen(PATHSEP) + 1);
|
2019-05-21 16:12:17 -04:00
|
|
|
snprintf(
|
|
|
|
g_databaseDirectory,
|
|
|
|
strlen(fcConfig->databaseDirectory) + strlen(PATHSEP) + 1,
|
|
|
|
"%s" PATHSEP,
|
|
|
|
fcConfig->databaseDirectory);
|
|
|
|
} else {
|
2024-01-09 17:44:33 -05:00
|
|
|
g_databaseDirectory = cli_safer_strdup(fcConfig->databaseDirectory);
|
2019-05-21 16:12:17 -04:00
|
|
|
}
|
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
/* Validate that the database directory exists, and store it. */
|
2019-05-21 16:12:17 -04:00
|
|
|
if (LSTAT(g_databaseDirectory, &statbuf) == -1) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_ERROR, "Database directory does not exist: %s\n", g_databaseDirectory);
|
2019-03-26 15:09:52 -04:00
|
|
|
status = FC_EDIRECTORY;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if (!S_ISDIR(statbuf.st_mode)) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_ERROR, "Database directory is not a directory: %s\n", g_databaseDirectory);
|
2019-03-26 15:09:52 -04:00
|
|
|
status = FC_EDIRECTORY;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
FIPS-compliant CVD signing and verification
Add X509 certificate chain based signing with PKCS7-PEM external
signatures distributed alongside CVD's in a custom .cvd.sign format.
This new signing and verification mechanism is primarily in support
of FIPS compliance.
Fixes: https://github.com/Cisco-Talos/clamav/issues/564
Add a Rust implementation for parsing, verifying, and unpacking CVD
files.
Now installs a 'certs' directory in the app config directory
(e.g. <prefix>/etc/certs). The install location is configurable.
The CMake option to configure the CVD certs directory is:
`-D CVD_CERTS_DIRECTORY=PATH`
New options to set an alternative CVD certs directory:
- Commandline for freshclam, clamd, clamscan, and sigtool is:
`--cvdcertsdir PATH`
- Env variable for freshclam, clamd, clamscan, and sigtool is:
`CVD_CERTS_DIR`
- Config option for freshclam and clamd is:
`CVDCertsDirectory PATH`
Sigtool:
- Add sign/verify commands.
- Also verify CDIFF external digital signatures when applying CDIFFs.
- Place commonly used commands at the top of --help string.
- Fix up manpage.
Freshclam:
- Will try to download .sign files to verify CVDs and CDIFFs.
- Fix an issue where making a CLD would only include the CFG file for
daily and not if patching any other database.
libclamav.so:
- Bump version to 13:0:1 (aka 12.1.0).
- Also remove libclamav.map versioning.
Resolves: https://github.com/Cisco-Talos/clamav/issues/1304
- Add two new API's to the public clamav.h header:
```c
extern cl_error_t cl_cvdverify_ex(const char *file,
const char *certs_directory);
extern cl_error_t cl_cvdunpack_ex(const char *file,
const char *dir,
bool dont_verify,
const char *certs_directory);
```
The original `cl_cvdverify` and `cl_cvdunpack` are deprecated.
- Add `cl_engine_field` enum option `CL_ENGINE_CVDCERTSDIR`.
You may set this option with `cl_engine_set_str` and get it
with `cl_engine_get_str`, to override the compiled in default
CVD certs directory.
libfreshclam.so: Bump version to 4:0:0 (aka 4.0.0).
Add sigtool sign/verify tests and test certs.
Make it so downloadFile doesn't throw a warning if the server
doesn't have the .sign file.
Replace use of md5-based FP signatures in the unit tests with
sha256-based FP signatures because the md5 implementation used
by Python may be disabled in FIPS mode.
Fixes: https://github.com/Cisco-Talos/clamav/issues/1411
CMake: Add logic to enable the Rust openssl-sys / openssl-rs crates
to build against the same OpenSSL library as is used for the C build.
The Rust unit test application must also link directly with libcrypto
and libssl.
Fix some log messages with missing new lines.
Fix missing environment variable notes in --help messages and manpages.
Deconflict CONFDIR/DATADIR/CERTSDIR variable names that are defined in
clamav-config.h.in for libclamav from variable that had the same name
for use in clamav applications that use the optparser.
The 'clamav-test' certs for the unit tests will live for 10 years.
The 'clamav-beta.crt' public cert will only live for 120 days and will
be replaced before the stable release with a production 'clamav.crt'.
2024-11-21 14:01:09 -05:00
|
|
|
#ifdef _WIN32
|
|
|
|
if ((fcConfig->certsDirectory[strlen(fcConfig->certsDirectory) - 1] != '/') &&
|
|
|
|
((fcConfig->certsDirectory[strlen(fcConfig->certsDirectory) - 1] != '\\'))) {
|
|
|
|
#else
|
|
|
|
if (fcConfig->certsDirectory[strlen(fcConfig->certsDirectory) - 1] != '/') {
|
|
|
|
#endif
|
|
|
|
certsDirectory = malloc(strlen(fcConfig->certsDirectory) + strlen(PATHSEP) + 1);
|
|
|
|
snprintf(
|
|
|
|
certsDirectory,
|
|
|
|
strlen(fcConfig->certsDirectory) + strlen(PATHSEP) + 1,
|
|
|
|
"%s" PATHSEP,
|
|
|
|
fcConfig->certsDirectory);
|
|
|
|
} else {
|
|
|
|
certsDirectory = cli_safer_strdup(fcConfig->certsDirectory);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!codesign_verifier_new(certsDirectory, &g_signVerifier, &new_verifier_error)) {
|
|
|
|
logg(LOGG_ERROR, "Failed to create a new code-signature verifier: %s\n", ffierror_fmt(new_verifier_error));
|
|
|
|
status = FC_EINIT;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2024-01-09 17:44:33 -05:00
|
|
|
g_tempDirectory = cli_safer_strdup(fcConfig->tempDirectory);
|
2019-03-26 15:09:52 -04:00
|
|
|
|
|
|
|
g_maxAttempts = fcConfig->maxAttempts;
|
|
|
|
g_connectTimeout = fcConfig->connectTimeout;
|
|
|
|
g_requestTimeout = fcConfig->requestTimeout;
|
|
|
|
|
|
|
|
g_bCompressLocalDatabase = fcConfig->bCompressLocalDatabase;
|
|
|
|
|
FIPS & FIPS-like limits on hash algs for cryptographic uses
ClamAV will not function when using a FIPS-enabled OpenSSL 3.x.
This is because ClamAV uses MD5 and SHA1 algorithms for a variety of
purposes including matching for malware detection, matching to prevent
false positives on known-clean files, and for verification of MD5-based
RSA digital signatures for determining CVD (signature database archive)
authenticity.
Interestingly, FIPS had been intentionally bypassed when creating hashes
based whole buffers and whole files (by descriptor or `FILE`-pointer):
https://github.com/Cisco-Talos/clamav/commit/78d4a9985a06a418dd1338c94ee5db461035d75b
Note: this bypassed FIPS the 1.x way with:
`EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);`
It was NOT disabled when using `cl_hash_init()` / `cl_update_hash()` /
`cl_finish_hash()`. That likely worked by coincidence in that the hash
was already calculated most of the time. It certainly would have made
use of those functions if the hash had not been calculated prior:
https://github.com/Cisco-Talos/clamav/blob/78d4a9985a06a418dd1338c94ee5db461035d75b/libclamav/matcher.c#L743
Regardless, bypassing FIPS entirely is not the correct solution.
The FIPS restrictions against using MD5 and SHA1 are valid, particularly
when verifying CVD digital siganatures, but also I think when using a
hash to determine if the file is known-clean (i.e. the "clean cache" and
also MD5-based and SHA1-based FP signatures).
This commit extends the work to bypass FIPS using the newer 3.x method:
`md = EVP_MD_fetch(NULL, alg, "-fips");`
It does this for the legacy `cl_hash*()` functions including
`cl_hash_init()` / `cl_update_hash()` / `cl_finish_hash()`.
It also introduces extended versions that allow the caller to choose if
they want to bypass FIPS:
- `cl_hash_data_ex()`
- `cl_hash_init_ex()`
- `cl_update_hash_ex()`
- `cl_finish_hash_ex()`
- `cl_hash_destroy_ex()`
- `cl_hash_file_fd_ex()`
See the `flags` parameter for each.
Ironically, this commit does NOT use the new functions at this time.
The rational is that ClamAV may need MD5, SHA1, and SHA-256 hashes of
the same files both for determining if the file is malware, and for
determining if the file is clean.
So instead, this commit will do a checks when:
1. Creating a new ClamAV scanning engine. If FIPS-mode enabled, it will
automatically toggle the "FIPS limits" engine option.
When loading signatures, if the engine "FIPS limits" option is enabled,
then MD5 and SHA1 FP signatures will be skipped.
2. Before verifying a CVD (e.g. also for loading, unpacking when
verification enabled).
If "FIPS limits" or FIPS-mode are enabled, then the legacy MD5-based RSA
method is disabled.
Note: This commit also refactors the interface for `cl_cvdverify_ex()`
and `cl_cvdunpack_ex()` so they take a `flags` parameters, rather than a
single `bool`. As these functions are new in this version, it does not
break the ABI.
The cache was already switched to use SHA2-256, so that's not a concern
for checking FIPS-mode / FIPS limits options.
This adds an option for `freshclam.conf` and `clamd.conf`:
FIPSCryptoHashLimits yes
And an equivalent command-line option for `clamscan` and `sigtool`:
--fips-limits
You may programmatically enable FIPS-limits for a ClamAV engine like this:
```C
cl_engine_set_num(engine, CL_ENGINE_FIPS_LIMITS, 1);
```
CLAM-2792
2025-07-01 20:41:47 -04:00
|
|
|
g_bFipsLimits = fcConfig->bFipsLimits;
|
|
|
|
|
2021-05-24 18:37:33 -07:00
|
|
|
/* Load or create freshclam.dat */
|
|
|
|
if (FC_SUCCESS != load_freshclam_dat()) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_DEBUG, "Failed to load freshclam.dat; will create a new freshclam.dat\n");
|
2021-03-21 19:47:21 -07:00
|
|
|
|
2021-05-24 18:37:33 -07:00
|
|
|
if (FC_SUCCESS != new_freshclam_dat()) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "Failed to create a new freshclam.dat!\n");
|
2021-03-21 19:47:21 -07:00
|
|
|
status = FC_EINIT;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
status = FC_SUCCESS;
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (FC_SUCCESS != status) {
|
|
|
|
fc_cleanup();
|
|
|
|
}
|
FIPS-compliant CVD signing and verification
Add X509 certificate chain based signing with PKCS7-PEM external
signatures distributed alongside CVD's in a custom .cvd.sign format.
This new signing and verification mechanism is primarily in support
of FIPS compliance.
Fixes: https://github.com/Cisco-Talos/clamav/issues/564
Add a Rust implementation for parsing, verifying, and unpacking CVD
files.
Now installs a 'certs' directory in the app config directory
(e.g. <prefix>/etc/certs). The install location is configurable.
The CMake option to configure the CVD certs directory is:
`-D CVD_CERTS_DIRECTORY=PATH`
New options to set an alternative CVD certs directory:
- Commandline for freshclam, clamd, clamscan, and sigtool is:
`--cvdcertsdir PATH`
- Env variable for freshclam, clamd, clamscan, and sigtool is:
`CVD_CERTS_DIR`
- Config option for freshclam and clamd is:
`CVDCertsDirectory PATH`
Sigtool:
- Add sign/verify commands.
- Also verify CDIFF external digital signatures when applying CDIFFs.
- Place commonly used commands at the top of --help string.
- Fix up manpage.
Freshclam:
- Will try to download .sign files to verify CVDs and CDIFFs.
- Fix an issue where making a CLD would only include the CFG file for
daily and not if patching any other database.
libclamav.so:
- Bump version to 13:0:1 (aka 12.1.0).
- Also remove libclamav.map versioning.
Resolves: https://github.com/Cisco-Talos/clamav/issues/1304
- Add two new API's to the public clamav.h header:
```c
extern cl_error_t cl_cvdverify_ex(const char *file,
const char *certs_directory);
extern cl_error_t cl_cvdunpack_ex(const char *file,
const char *dir,
bool dont_verify,
const char *certs_directory);
```
The original `cl_cvdverify` and `cl_cvdunpack` are deprecated.
- Add `cl_engine_field` enum option `CL_ENGINE_CVDCERTSDIR`.
You may set this option with `cl_engine_set_str` and get it
with `cl_engine_get_str`, to override the compiled in default
CVD certs directory.
libfreshclam.so: Bump version to 4:0:0 (aka 4.0.0).
Add sigtool sign/verify tests and test certs.
Make it so downloadFile doesn't throw a warning if the server
doesn't have the .sign file.
Replace use of md5-based FP signatures in the unit tests with
sha256-based FP signatures because the md5 implementation used
by Python may be disabled in FIPS mode.
Fixes: https://github.com/Cisco-Talos/clamav/issues/1411
CMake: Add logic to enable the Rust openssl-sys / openssl-rs crates
to build against the same OpenSSL library as is used for the C build.
The Rust unit test application must also link directly with libcrypto
and libssl.
Fix some log messages with missing new lines.
Fix missing environment variable notes in --help messages and manpages.
Deconflict CONFDIR/DATADIR/CERTSDIR variable names that are defined in
clamav-config.h.in for libclamav from variable that had the same name
for use in clamav applications that use the optparser.
The 'clamav-test' certs for the unit tests will live for 10 years.
The 'clamav-beta.crt' public cert will only live for 120 days and will
be replaced before the stable release with a production 'clamav.crt'.
2024-11-21 14:01:09 -05:00
|
|
|
if (NULL != certsDirectory) {
|
|
|
|
free(certsDirectory);
|
|
|
|
}
|
|
|
|
if (NULL != new_verifier_error) {
|
|
|
|
ffierror_free(new_verifier_error);
|
|
|
|
}
|
2019-03-26 15:09:52 -04:00
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
void fc_cleanup(void)
|
|
|
|
{
|
|
|
|
/* Cleanup libcurl */
|
|
|
|
curl_global_cleanup();
|
|
|
|
|
|
|
|
if (NULL != logg_file) {
|
|
|
|
free((void *)logg_file);
|
|
|
|
logg_file = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != g_localIP) {
|
|
|
|
free(g_localIP);
|
|
|
|
g_localIP = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != g_userAgent) {
|
|
|
|
free(g_userAgent);
|
|
|
|
g_userAgent = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != g_proxyServer) {
|
|
|
|
free(g_proxyServer);
|
|
|
|
g_proxyServer = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != g_proxyUsername) {
|
|
|
|
free(g_proxyUsername);
|
|
|
|
g_proxyUsername = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != g_proxyPassword) {
|
|
|
|
free(g_proxyPassword);
|
|
|
|
g_proxyPassword = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != g_databaseDirectory) {
|
|
|
|
free(g_databaseDirectory);
|
|
|
|
g_databaseDirectory = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != g_tempDirectory) {
|
|
|
|
free(g_tempDirectory);
|
|
|
|
g_tempDirectory = NULL;
|
|
|
|
}
|
2021-05-24 18:37:33 -07:00
|
|
|
if (NULL != g_freshclamDat) {
|
|
|
|
free(g_freshclamDat);
|
|
|
|
g_freshclamDat = NULL;
|
2021-03-25 13:31:46 -07:00
|
|
|
}
|
FIPS-compliant CVD signing and verification
Add X509 certificate chain based signing with PKCS7-PEM external
signatures distributed alongside CVD's in a custom .cvd.sign format.
This new signing and verification mechanism is primarily in support
of FIPS compliance.
Fixes: https://github.com/Cisco-Talos/clamav/issues/564
Add a Rust implementation for parsing, verifying, and unpacking CVD
files.
Now installs a 'certs' directory in the app config directory
(e.g. <prefix>/etc/certs). The install location is configurable.
The CMake option to configure the CVD certs directory is:
`-D CVD_CERTS_DIRECTORY=PATH`
New options to set an alternative CVD certs directory:
- Commandline for freshclam, clamd, clamscan, and sigtool is:
`--cvdcertsdir PATH`
- Env variable for freshclam, clamd, clamscan, and sigtool is:
`CVD_CERTS_DIR`
- Config option for freshclam and clamd is:
`CVDCertsDirectory PATH`
Sigtool:
- Add sign/verify commands.
- Also verify CDIFF external digital signatures when applying CDIFFs.
- Place commonly used commands at the top of --help string.
- Fix up manpage.
Freshclam:
- Will try to download .sign files to verify CVDs and CDIFFs.
- Fix an issue where making a CLD would only include the CFG file for
daily and not if patching any other database.
libclamav.so:
- Bump version to 13:0:1 (aka 12.1.0).
- Also remove libclamav.map versioning.
Resolves: https://github.com/Cisco-Talos/clamav/issues/1304
- Add two new API's to the public clamav.h header:
```c
extern cl_error_t cl_cvdverify_ex(const char *file,
const char *certs_directory);
extern cl_error_t cl_cvdunpack_ex(const char *file,
const char *dir,
bool dont_verify,
const char *certs_directory);
```
The original `cl_cvdverify` and `cl_cvdunpack` are deprecated.
- Add `cl_engine_field` enum option `CL_ENGINE_CVDCERTSDIR`.
You may set this option with `cl_engine_set_str` and get it
with `cl_engine_get_str`, to override the compiled in default
CVD certs directory.
libfreshclam.so: Bump version to 4:0:0 (aka 4.0.0).
Add sigtool sign/verify tests and test certs.
Make it so downloadFile doesn't throw a warning if the server
doesn't have the .sign file.
Replace use of md5-based FP signatures in the unit tests with
sha256-based FP signatures because the md5 implementation used
by Python may be disabled in FIPS mode.
Fixes: https://github.com/Cisco-Talos/clamav/issues/1411
CMake: Add logic to enable the Rust openssl-sys / openssl-rs crates
to build against the same OpenSSL library as is used for the C build.
The Rust unit test application must also link directly with libcrypto
and libssl.
Fix some log messages with missing new lines.
Fix missing environment variable notes in --help messages and manpages.
Deconflict CONFDIR/DATADIR/CERTSDIR variable names that are defined in
clamav-config.h.in for libclamav from variable that had the same name
for use in clamav applications that use the optparser.
The 'clamav-test' certs for the unit tests will live for 10 years.
The 'clamav-beta.crt' public cert will only live for 120 days and will
be replaced before the stable release with a production 'clamav.crt'.
2024-11-21 14:01:09 -05:00
|
|
|
if (NULL != g_signVerifier) {
|
|
|
|
codesign_verifier_free(g_signVerifier);
|
|
|
|
}
|
2019-03-26 15:09:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
fc_error_t fc_prune_database_directory(char **databaseList, uint32_t nDatabases)
|
|
|
|
{
|
|
|
|
fc_error_t status = FC_EARG;
|
|
|
|
|
|
|
|
DIR *dir = NULL;
|
|
|
|
struct dirent *dent;
|
|
|
|
char *extension = NULL;
|
|
|
|
|
2019-05-21 17:28:07 -04:00
|
|
|
/* Change directory to database directory */
|
|
|
|
if (chdir(g_databaseDirectory)) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_ERROR, "Can't change dir to %s\n", g_databaseDirectory);
|
2019-05-21 17:28:07 -04:00
|
|
|
status = FC_EDIRECTORY;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_DEBUG, "Current working dir is %s\n", g_databaseDirectory);
|
2019-05-21 17:28:07 -04:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
if (!(dir = opendir(g_databaseDirectory))) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_ERROR, "checkdbdir: Can't open directory %s\n", g_databaseDirectory);
|
2019-03-26 15:09:52 -04:00
|
|
|
status = FC_EDBDIRACCESS;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((dent = readdir(dir))) {
|
|
|
|
if (dent->d_ino) {
|
FIPS-compliant CVD signing and verification
Add X509 certificate chain based signing with PKCS7-PEM external
signatures distributed alongside CVD's in a custom .cvd.sign format.
This new signing and verification mechanism is primarily in support
of FIPS compliance.
Fixes: https://github.com/Cisco-Talos/clamav/issues/564
Add a Rust implementation for parsing, verifying, and unpacking CVD
files.
Now installs a 'certs' directory in the app config directory
(e.g. <prefix>/etc/certs). The install location is configurable.
The CMake option to configure the CVD certs directory is:
`-D CVD_CERTS_DIRECTORY=PATH`
New options to set an alternative CVD certs directory:
- Commandline for freshclam, clamd, clamscan, and sigtool is:
`--cvdcertsdir PATH`
- Env variable for freshclam, clamd, clamscan, and sigtool is:
`CVD_CERTS_DIR`
- Config option for freshclam and clamd is:
`CVDCertsDirectory PATH`
Sigtool:
- Add sign/verify commands.
- Also verify CDIFF external digital signatures when applying CDIFFs.
- Place commonly used commands at the top of --help string.
- Fix up manpage.
Freshclam:
- Will try to download .sign files to verify CVDs and CDIFFs.
- Fix an issue where making a CLD would only include the CFG file for
daily and not if patching any other database.
libclamav.so:
- Bump version to 13:0:1 (aka 12.1.0).
- Also remove libclamav.map versioning.
Resolves: https://github.com/Cisco-Talos/clamav/issues/1304
- Add two new API's to the public clamav.h header:
```c
extern cl_error_t cl_cvdverify_ex(const char *file,
const char *certs_directory);
extern cl_error_t cl_cvdunpack_ex(const char *file,
const char *dir,
bool dont_verify,
const char *certs_directory);
```
The original `cl_cvdverify` and `cl_cvdunpack` are deprecated.
- Add `cl_engine_field` enum option `CL_ENGINE_CVDCERTSDIR`.
You may set this option with `cl_engine_set_str` and get it
with `cl_engine_get_str`, to override the compiled in default
CVD certs directory.
libfreshclam.so: Bump version to 4:0:0 (aka 4.0.0).
Add sigtool sign/verify tests and test certs.
Make it so downloadFile doesn't throw a warning if the server
doesn't have the .sign file.
Replace use of md5-based FP signatures in the unit tests with
sha256-based FP signatures because the md5 implementation used
by Python may be disabled in FIPS mode.
Fixes: https://github.com/Cisco-Talos/clamav/issues/1411
CMake: Add logic to enable the Rust openssl-sys / openssl-rs crates
to build against the same OpenSSL library as is used for the C build.
The Rust unit test application must also link directly with libcrypto
and libssl.
Fix some log messages with missing new lines.
Fix missing environment variable notes in --help messages and manpages.
Deconflict CONFDIR/DATADIR/CERTSDIR variable names that are defined in
clamav-config.h.in for libclamav from variable that had the same name
for use in clamav applications that use the optparser.
The 'clamav-test' certs for the unit tests will live for 10 years.
The 'clamav-beta.crt' public cert will only live for 120 days and will
be replaced before the stable release with a production 'clamav.crt'.
2024-11-21 14:01:09 -05:00
|
|
|
// prune any CVD/CLD files that are not in the database list
|
2019-03-26 15:09:52 -04:00
|
|
|
if ((NULL != (extension = strstr(dent->d_name, ".cld"))) ||
|
|
|
|
(NULL != (extension = strstr(dent->d_name, ".cvd")))) {
|
|
|
|
|
FIPS-compliant CVD signing and verification
Add X509 certificate chain based signing with PKCS7-PEM external
signatures distributed alongside CVD's in a custom .cvd.sign format.
This new signing and verification mechanism is primarily in support
of FIPS compliance.
Fixes: https://github.com/Cisco-Talos/clamav/issues/564
Add a Rust implementation for parsing, verifying, and unpacking CVD
files.
Now installs a 'certs' directory in the app config directory
(e.g. <prefix>/etc/certs). The install location is configurable.
The CMake option to configure the CVD certs directory is:
`-D CVD_CERTS_DIRECTORY=PATH`
New options to set an alternative CVD certs directory:
- Commandline for freshclam, clamd, clamscan, and sigtool is:
`--cvdcertsdir PATH`
- Env variable for freshclam, clamd, clamscan, and sigtool is:
`CVD_CERTS_DIR`
- Config option for freshclam and clamd is:
`CVDCertsDirectory PATH`
Sigtool:
- Add sign/verify commands.
- Also verify CDIFF external digital signatures when applying CDIFFs.
- Place commonly used commands at the top of --help string.
- Fix up manpage.
Freshclam:
- Will try to download .sign files to verify CVDs and CDIFFs.
- Fix an issue where making a CLD would only include the CFG file for
daily and not if patching any other database.
libclamav.so:
- Bump version to 13:0:1 (aka 12.1.0).
- Also remove libclamav.map versioning.
Resolves: https://github.com/Cisco-Talos/clamav/issues/1304
- Add two new API's to the public clamav.h header:
```c
extern cl_error_t cl_cvdverify_ex(const char *file,
const char *certs_directory);
extern cl_error_t cl_cvdunpack_ex(const char *file,
const char *dir,
bool dont_verify,
const char *certs_directory);
```
The original `cl_cvdverify` and `cl_cvdunpack` are deprecated.
- Add `cl_engine_field` enum option `CL_ENGINE_CVDCERTSDIR`.
You may set this option with `cl_engine_set_str` and get it
with `cl_engine_get_str`, to override the compiled in default
CVD certs directory.
libfreshclam.so: Bump version to 4:0:0 (aka 4.0.0).
Add sigtool sign/verify tests and test certs.
Make it so downloadFile doesn't throw a warning if the server
doesn't have the .sign file.
Replace use of md5-based FP signatures in the unit tests with
sha256-based FP signatures because the md5 implementation used
by Python may be disabled in FIPS mode.
Fixes: https://github.com/Cisco-Talos/clamav/issues/1411
CMake: Add logic to enable the Rust openssl-sys / openssl-rs crates
to build against the same OpenSSL library as is used for the C build.
The Rust unit test application must also link directly with libcrypto
and libssl.
Fix some log messages with missing new lines.
Fix missing environment variable notes in --help messages and manpages.
Deconflict CONFDIR/DATADIR/CERTSDIR variable names that are defined in
clamav-config.h.in for libclamav from variable that had the same name
for use in clamav applications that use the optparser.
The 'clamav-test' certs for the unit tests will live for 10 years.
The 'clamav-beta.crt' public cert will only live for 120 days and will
be replaced before the stable release with a production 'clamav.crt'.
2024-11-21 14:01:09 -05:00
|
|
|
// find the first '-' or '.' in the filename
|
|
|
|
// Use this to determine the database name.
|
|
|
|
// We need this so we can ALSO prune the .sign files for unwanted databases.
|
|
|
|
// Will also be useful in case the database filename includes a hyphenated version number.
|
|
|
|
const char *first_dash_or_dot = strchr(dent->d_name, '-');
|
|
|
|
if (NULL == first_dash_or_dot) {
|
|
|
|
first_dash_or_dot = extension;
|
|
|
|
}
|
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
uint32_t i;
|
|
|
|
int bFound = 0;
|
|
|
|
for (i = 0; i < nDatabases; i++) {
|
FIPS-compliant CVD signing and verification
Add X509 certificate chain based signing with PKCS7-PEM external
signatures distributed alongside CVD's in a custom .cvd.sign format.
This new signing and verification mechanism is primarily in support
of FIPS compliance.
Fixes: https://github.com/Cisco-Talos/clamav/issues/564
Add a Rust implementation for parsing, verifying, and unpacking CVD
files.
Now installs a 'certs' directory in the app config directory
(e.g. <prefix>/etc/certs). The install location is configurable.
The CMake option to configure the CVD certs directory is:
`-D CVD_CERTS_DIRECTORY=PATH`
New options to set an alternative CVD certs directory:
- Commandline for freshclam, clamd, clamscan, and sigtool is:
`--cvdcertsdir PATH`
- Env variable for freshclam, clamd, clamscan, and sigtool is:
`CVD_CERTS_DIR`
- Config option for freshclam and clamd is:
`CVDCertsDirectory PATH`
Sigtool:
- Add sign/verify commands.
- Also verify CDIFF external digital signatures when applying CDIFFs.
- Place commonly used commands at the top of --help string.
- Fix up manpage.
Freshclam:
- Will try to download .sign files to verify CVDs and CDIFFs.
- Fix an issue where making a CLD would only include the CFG file for
daily and not if patching any other database.
libclamav.so:
- Bump version to 13:0:1 (aka 12.1.0).
- Also remove libclamav.map versioning.
Resolves: https://github.com/Cisco-Talos/clamav/issues/1304
- Add two new API's to the public clamav.h header:
```c
extern cl_error_t cl_cvdverify_ex(const char *file,
const char *certs_directory);
extern cl_error_t cl_cvdunpack_ex(const char *file,
const char *dir,
bool dont_verify,
const char *certs_directory);
```
The original `cl_cvdverify` and `cl_cvdunpack` are deprecated.
- Add `cl_engine_field` enum option `CL_ENGINE_CVDCERTSDIR`.
You may set this option with `cl_engine_set_str` and get it
with `cl_engine_get_str`, to override the compiled in default
CVD certs directory.
libfreshclam.so: Bump version to 4:0:0 (aka 4.0.0).
Add sigtool sign/verify tests and test certs.
Make it so downloadFile doesn't throw a warning if the server
doesn't have the .sign file.
Replace use of md5-based FP signatures in the unit tests with
sha256-based FP signatures because the md5 implementation used
by Python may be disabled in FIPS mode.
Fixes: https://github.com/Cisco-Talos/clamav/issues/1411
CMake: Add logic to enable the Rust openssl-sys / openssl-rs crates
to build against the same OpenSSL library as is used for the C build.
The Rust unit test application must also link directly with libcrypto
and libssl.
Fix some log messages with missing new lines.
Fix missing environment variable notes in --help messages and manpages.
Deconflict CONFDIR/DATADIR/CERTSDIR variable names that are defined in
clamav-config.h.in for libclamav from variable that had the same name
for use in clamav applications that use the optparser.
The 'clamav-test' certs for the unit tests will live for 10 years.
The 'clamav-beta.crt' public cert will only live for 120 days and will
be replaced before the stable release with a production 'clamav.crt'.
2024-11-21 14:01:09 -05:00
|
|
|
// check that the database name is in the database list
|
|
|
|
if (0 == strncmp(databaseList[i], dent->d_name, first_dash_or_dot - dent->d_name)) {
|
2019-03-26 15:09:52 -04:00
|
|
|
bFound = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!bFound) {
|
|
|
|
/* Prune CVD/CLD */
|
2022-02-16 00:13:55 +01:00
|
|
|
mprintf(LOGG_INFO, "Pruning unwanted or deprecated database file %s.\n", dent->d_name);
|
2019-05-21 17:28:07 -04:00
|
|
|
if (unlink(dent->d_name)) {
|
2022-02-16 00:13:55 +01:00
|
|
|
mprintf(LOGG_ERROR, "Failed to prune unwanted database file %s, consider removing it manually.\n", dent->d_name);
|
2019-03-26 15:09:52 -04:00
|
|
|
status = FC_EDBDIRACCESS;
|
|
|
|
goto done;
|
2016-03-11 13:32:31 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
status = FC_SUCCESS;
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (NULL != dir) {
|
|
|
|
closedir(dir);
|
|
|
|
}
|
2019-05-21 17:28:07 -04:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
return status;
|
2016-03-11 13:32:31 -07:00
|
|
|
}
|
|
|
|
|
2019-08-06 17:59:11 -04:00
|
|
|
/**
|
|
|
|
* @brief Compare two version strings.
|
|
|
|
*
|
|
|
|
* @param v1 Version string 1
|
|
|
|
* @param v2 Version string 2
|
|
|
|
* @return int 1 if v1 is greater, 0 if equal, -1 if smaller.
|
|
|
|
*/
|
|
|
|
int version_string_compare(char *v1, size_t v1_len, char *v2, size_t v2_len)
|
|
|
|
{
|
|
|
|
size_t i, j;
|
|
|
|
int vnum1 = 0, vnum2 = 0;
|
|
|
|
|
|
|
|
for (i = 0, j = 0; (i < v1_len || j < v2_len);) {
|
|
|
|
while (i < v1_len && v1[i] != '.') {
|
|
|
|
vnum1 = vnum1 * 10 + (v1[i] - '0');
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (j < v2_len && v2[j] != '.') {
|
|
|
|
vnum2 = vnum2 * 10 + (v2[j] - '0');
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vnum1 > vnum2)
|
|
|
|
return 1;
|
|
|
|
if (vnum2 > vnum1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
vnum1 = vnum2 = 0;
|
|
|
|
i++;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
fc_error_t fc_test_database(const char *dbFilename, int bBytecodeEnabled)
|
2018-12-03 12:40:13 -05:00
|
|
|
{
|
2019-03-26 15:09:52 -04:00
|
|
|
fc_error_t status = FC_EARG;
|
|
|
|
struct cl_engine *engine = NULL;
|
|
|
|
unsigned newsigs = 0;
|
|
|
|
cl_error_t cl_ret;
|
FIPS & FIPS-like limits on hash algs for cryptographic uses
ClamAV will not function when using a FIPS-enabled OpenSSL 3.x.
This is because ClamAV uses MD5 and SHA1 algorithms for a variety of
purposes including matching for malware detection, matching to prevent
false positives on known-clean files, and for verification of MD5-based
RSA digital signatures for determining CVD (signature database archive)
authenticity.
Interestingly, FIPS had been intentionally bypassed when creating hashes
based whole buffers and whole files (by descriptor or `FILE`-pointer):
https://github.com/Cisco-Talos/clamav/commit/78d4a9985a06a418dd1338c94ee5db461035d75b
Note: this bypassed FIPS the 1.x way with:
`EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);`
It was NOT disabled when using `cl_hash_init()` / `cl_update_hash()` /
`cl_finish_hash()`. That likely worked by coincidence in that the hash
was already calculated most of the time. It certainly would have made
use of those functions if the hash had not been calculated prior:
https://github.com/Cisco-Talos/clamav/blob/78d4a9985a06a418dd1338c94ee5db461035d75b/libclamav/matcher.c#L743
Regardless, bypassing FIPS entirely is not the correct solution.
The FIPS restrictions against using MD5 and SHA1 are valid, particularly
when verifying CVD digital siganatures, but also I think when using a
hash to determine if the file is known-clean (i.e. the "clean cache" and
also MD5-based and SHA1-based FP signatures).
This commit extends the work to bypass FIPS using the newer 3.x method:
`md = EVP_MD_fetch(NULL, alg, "-fips");`
It does this for the legacy `cl_hash*()` functions including
`cl_hash_init()` / `cl_update_hash()` / `cl_finish_hash()`.
It also introduces extended versions that allow the caller to choose if
they want to bypass FIPS:
- `cl_hash_data_ex()`
- `cl_hash_init_ex()`
- `cl_update_hash_ex()`
- `cl_finish_hash_ex()`
- `cl_hash_destroy_ex()`
- `cl_hash_file_fd_ex()`
See the `flags` parameter for each.
Ironically, this commit does NOT use the new functions at this time.
The rational is that ClamAV may need MD5, SHA1, and SHA-256 hashes of
the same files both for determining if the file is malware, and for
determining if the file is clean.
So instead, this commit will do a checks when:
1. Creating a new ClamAV scanning engine. If FIPS-mode enabled, it will
automatically toggle the "FIPS limits" engine option.
When loading signatures, if the engine "FIPS limits" option is enabled,
then MD5 and SHA1 FP signatures will be skipped.
2. Before verifying a CVD (e.g. also for loading, unpacking when
verification enabled).
If "FIPS limits" or FIPS-mode are enabled, then the legacy MD5-based RSA
method is disabled.
Note: This commit also refactors the interface for `cl_cvdverify_ex()`
and `cl_cvdunpack_ex()` so they take a `flags` parameters, rather than a
single `bool`. As these functions are new in this version, it does not
break the ABI.
The cache was already switched to use SHA2-256, so that's not a concern
for checking FIPS-mode / FIPS limits options.
This adds an option for `freshclam.conf` and `clamd.conf`:
FIPSCryptoHashLimits yes
And an equivalent command-line option for `clamscan` and `sigtool`:
--fips-limits
You may programmatically enable FIPS-limits for a ClamAV engine like this:
```C
cl_engine_set_num(engine, CL_ENGINE_FIPS_LIMITS, 1);
```
CLAM-2792
2025-07-01 20:41:47 -04:00
|
|
|
unsigned int dboptions = 0;
|
2019-03-26 15:09:52 -04:00
|
|
|
|
|
|
|
if ((NULL == dbFilename)) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "fc_test_database: Invalid arguments.\n");
|
2019-03-26 15:09:52 -04:00
|
|
|
goto done;
|
|
|
|
}
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_DEBUG, "Loading signatures from %s\n", dbFilename);
|
2019-03-26 15:09:52 -04:00
|
|
|
if (NULL == (engine = cl_engine_new())) {
|
|
|
|
status = FC_ETESTFAIL;
|
|
|
|
goto done;
|
|
|
|
}
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2023-03-31 17:20:54 -04:00
|
|
|
// Disable cache as testing the database doesn't need caching,
|
|
|
|
// having cache will only waste time and memory.
|
|
|
|
engine->engine_options |= ENGINE_OPTIONS_DISABLE_CACHE;
|
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
cl_engine_set_clcb_stats_submit(engine, NULL);
|
|
|
|
|
FIPS & FIPS-like limits on hash algs for cryptographic uses
ClamAV will not function when using a FIPS-enabled OpenSSL 3.x.
This is because ClamAV uses MD5 and SHA1 algorithms for a variety of
purposes including matching for malware detection, matching to prevent
false positives on known-clean files, and for verification of MD5-based
RSA digital signatures for determining CVD (signature database archive)
authenticity.
Interestingly, FIPS had been intentionally bypassed when creating hashes
based whole buffers and whole files (by descriptor or `FILE`-pointer):
https://github.com/Cisco-Talos/clamav/commit/78d4a9985a06a418dd1338c94ee5db461035d75b
Note: this bypassed FIPS the 1.x way with:
`EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);`
It was NOT disabled when using `cl_hash_init()` / `cl_update_hash()` /
`cl_finish_hash()`. That likely worked by coincidence in that the hash
was already calculated most of the time. It certainly would have made
use of those functions if the hash had not been calculated prior:
https://github.com/Cisco-Talos/clamav/blob/78d4a9985a06a418dd1338c94ee5db461035d75b/libclamav/matcher.c#L743
Regardless, bypassing FIPS entirely is not the correct solution.
The FIPS restrictions against using MD5 and SHA1 are valid, particularly
when verifying CVD digital siganatures, but also I think when using a
hash to determine if the file is known-clean (i.e. the "clean cache" and
also MD5-based and SHA1-based FP signatures).
This commit extends the work to bypass FIPS using the newer 3.x method:
`md = EVP_MD_fetch(NULL, alg, "-fips");`
It does this for the legacy `cl_hash*()` functions including
`cl_hash_init()` / `cl_update_hash()` / `cl_finish_hash()`.
It also introduces extended versions that allow the caller to choose if
they want to bypass FIPS:
- `cl_hash_data_ex()`
- `cl_hash_init_ex()`
- `cl_update_hash_ex()`
- `cl_finish_hash_ex()`
- `cl_hash_destroy_ex()`
- `cl_hash_file_fd_ex()`
See the `flags` parameter for each.
Ironically, this commit does NOT use the new functions at this time.
The rational is that ClamAV may need MD5, SHA1, and SHA-256 hashes of
the same files both for determining if the file is malware, and for
determining if the file is clean.
So instead, this commit will do a checks when:
1. Creating a new ClamAV scanning engine. If FIPS-mode enabled, it will
automatically toggle the "FIPS limits" engine option.
When loading signatures, if the engine "FIPS limits" option is enabled,
then MD5 and SHA1 FP signatures will be skipped.
2. Before verifying a CVD (e.g. also for loading, unpacking when
verification enabled).
If "FIPS limits" or FIPS-mode are enabled, then the legacy MD5-based RSA
method is disabled.
Note: This commit also refactors the interface for `cl_cvdverify_ex()`
and `cl_cvdunpack_ex()` so they take a `flags` parameters, rather than a
single `bool`. As these functions are new in this version, it does not
break the ABI.
The cache was already switched to use SHA2-256, so that's not a concern
for checking FIPS-mode / FIPS limits options.
This adds an option for `freshclam.conf` and `clamd.conf`:
FIPSCryptoHashLimits yes
And an equivalent command-line option for `clamscan` and `sigtool`:
--fips-limits
You may programmatically enable FIPS-limits for a ClamAV engine like this:
```C
cl_engine_set_num(engine, CL_ENGINE_FIPS_LIMITS, 1);
```
CLAM-2792
2025-07-01 20:41:47 -04:00
|
|
|
dboptions = CL_DB_PHISHING | CL_DB_PHISHING_URLS | CL_DB_BYTECODE | CL_DB_PUA | CL_DB_ENHANCED;
|
|
|
|
if (g_bFipsLimits) {
|
|
|
|
dboptions |= CL_DB_FIPS_LIMITS;
|
|
|
|
}
|
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
if (CL_SUCCESS != (cl_ret = cl_load(
|
FIPS & FIPS-like limits on hash algs for cryptographic uses
ClamAV will not function when using a FIPS-enabled OpenSSL 3.x.
This is because ClamAV uses MD5 and SHA1 algorithms for a variety of
purposes including matching for malware detection, matching to prevent
false positives on known-clean files, and for verification of MD5-based
RSA digital signatures for determining CVD (signature database archive)
authenticity.
Interestingly, FIPS had been intentionally bypassed when creating hashes
based whole buffers and whole files (by descriptor or `FILE`-pointer):
https://github.com/Cisco-Talos/clamav/commit/78d4a9985a06a418dd1338c94ee5db461035d75b
Note: this bypassed FIPS the 1.x way with:
`EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);`
It was NOT disabled when using `cl_hash_init()` / `cl_update_hash()` /
`cl_finish_hash()`. That likely worked by coincidence in that the hash
was already calculated most of the time. It certainly would have made
use of those functions if the hash had not been calculated prior:
https://github.com/Cisco-Talos/clamav/blob/78d4a9985a06a418dd1338c94ee5db461035d75b/libclamav/matcher.c#L743
Regardless, bypassing FIPS entirely is not the correct solution.
The FIPS restrictions against using MD5 and SHA1 are valid, particularly
when verifying CVD digital siganatures, but also I think when using a
hash to determine if the file is known-clean (i.e. the "clean cache" and
also MD5-based and SHA1-based FP signatures).
This commit extends the work to bypass FIPS using the newer 3.x method:
`md = EVP_MD_fetch(NULL, alg, "-fips");`
It does this for the legacy `cl_hash*()` functions including
`cl_hash_init()` / `cl_update_hash()` / `cl_finish_hash()`.
It also introduces extended versions that allow the caller to choose if
they want to bypass FIPS:
- `cl_hash_data_ex()`
- `cl_hash_init_ex()`
- `cl_update_hash_ex()`
- `cl_finish_hash_ex()`
- `cl_hash_destroy_ex()`
- `cl_hash_file_fd_ex()`
See the `flags` parameter for each.
Ironically, this commit does NOT use the new functions at this time.
The rational is that ClamAV may need MD5, SHA1, and SHA-256 hashes of
the same files both for determining if the file is malware, and for
determining if the file is clean.
So instead, this commit will do a checks when:
1. Creating a new ClamAV scanning engine. If FIPS-mode enabled, it will
automatically toggle the "FIPS limits" engine option.
When loading signatures, if the engine "FIPS limits" option is enabled,
then MD5 and SHA1 FP signatures will be skipped.
2. Before verifying a CVD (e.g. also for loading, unpacking when
verification enabled).
If "FIPS limits" or FIPS-mode are enabled, then the legacy MD5-based RSA
method is disabled.
Note: This commit also refactors the interface for `cl_cvdverify_ex()`
and `cl_cvdunpack_ex()` so they take a `flags` parameters, rather than a
single `bool`. As these functions are new in this version, it does not
break the ABI.
The cache was already switched to use SHA2-256, so that's not a concern
for checking FIPS-mode / FIPS limits options.
This adds an option for `freshclam.conf` and `clamd.conf`:
FIPSCryptoHashLimits yes
And an equivalent command-line option for `clamscan` and `sigtool`:
--fips-limits
You may programmatically enable FIPS-limits for a ClamAV engine like this:
```C
cl_engine_set_num(engine, CL_ENGINE_FIPS_LIMITS, 1);
```
CLAM-2792
2025-07-01 20:41:47 -04:00
|
|
|
dbFilename,
|
|
|
|
engine,
|
|
|
|
&newsigs,
|
|
|
|
dboptions))) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_ERROR, "Failed to load new database: %s\n", cl_strerror(cl_ret));
|
2019-03-26 15:09:52 -04:00
|
|
|
status = FC_ETESTFAIL;
|
|
|
|
goto done;
|
2016-03-11 13:32:31 -07:00
|
|
|
}
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
if (bBytecodeEnabled && (CL_SUCCESS != (cl_ret = cli_bytecode_prepare2(
|
|
|
|
engine, &engine->bcs,
|
|
|
|
engine->dconf->bytecode
|
|
|
|
/*FIXME: dconf has no sense here */)))) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_ERROR, "Failed to compile/load bytecode: %s\n", cl_strerror(cl_ret));
|
2019-03-26 15:09:52 -04:00
|
|
|
status = FC_ETESTFAIL;
|
|
|
|
goto done;
|
|
|
|
}
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_DEBUG, "Properly loaded %u signatures from %s\n", newsigs, dbFilename);
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
status = FC_SUCCESS;
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
done:
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
if (NULL != engine) {
|
2025-06-03 19:03:20 -04:00
|
|
|
if (engine->domain_list_matcher && engine->domain_list_matcher->sha2_256_pfx_set.keys)
|
|
|
|
cli_hashset_destroy(&engine->domain_list_matcher->sha2_256_pfx_set);
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
cl_engine_free(engine);
|
2016-03-11 13:32:31 -07:00
|
|
|
}
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
return status;
|
|
|
|
}
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
fc_error_t fc_dns_query_update_info(
|
|
|
|
const char *dnsUpdateInfoServer,
|
|
|
|
char **dnsUpdateInfo,
|
|
|
|
char **newVersion)
|
|
|
|
{
|
|
|
|
fc_error_t status = FC_EFAILEDGET;
|
|
|
|
char *dnsReply = NULL;
|
|
|
|
|
|
|
|
#ifdef HAVE_RESOLV_H
|
|
|
|
unsigned int ttl;
|
|
|
|
char *reply_token = NULL;
|
|
|
|
int recordTime;
|
|
|
|
time_t currentTime;
|
|
|
|
int vwarning = 1;
|
|
|
|
char version_string[32];
|
|
|
|
#endif /* HAVE_RESOLV_H */
|
|
|
|
|
|
|
|
if ((NULL == dnsUpdateInfo) || (NULL == newVersion)) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "dns_query_update_info: Invalid arguments.\n");
|
2019-03-26 15:09:52 -04:00
|
|
|
status = FC_EARG;
|
|
|
|
goto done;
|
|
|
|
}
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
*dnsUpdateInfo = NULL;
|
|
|
|
*newVersion = NULL;
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
#ifdef HAVE_RESOLV_H
|
|
|
|
|
|
|
|
if (dnsUpdateInfoServer == NULL) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "DNS Update Info disabled. Falling back to HTTP mode.\n");
|
2019-03-26 15:09:52 -04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL == (dnsReply = dnsquery(dnsUpdateInfoServer, T_TXT, &ttl))) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "Invalid DNS reply. Falling back to HTTP mode.\n");
|
2019-03-26 15:09:52 -04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_DEBUG, "TTL: %d\n", ttl);
|
2019-03-26 15:09:52 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check Record Time.
|
|
|
|
*/
|
|
|
|
if (NULL == (reply_token = cli_strtok(dnsReply, DNS_UPDATEINFO_RECORDTIME, ":"))) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "Failed to find Record Time field in DNS Update Info.\n");
|
2019-03-26 15:09:52 -04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
recordTime = atoi(reply_token);
|
|
|
|
free(reply_token);
|
|
|
|
reply_token = NULL;
|
|
|
|
|
|
|
|
time(¤tTime);
|
2022-07-12 15:04:49 -04:00
|
|
|
if ((int)currentTime - recordTime > DNS_WARNING_THRESHOLD_SECONDS) {
|
|
|
|
logg(LOGG_WARNING, "DNS record is older than %d hours.\n", DNS_WARNING_THRESHOLD_HOURS);
|
2019-03-26 15:09:52 -04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check Version Warning Flag.
|
|
|
|
*/
|
|
|
|
if (NULL == (reply_token = cli_strtok(dnsReply, DNS_UPDATEINFO_VERSIONWARNING, ":"))) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "Failed to find Version Warning Flag in DNS Update Info.\n");
|
2019-03-26 15:09:52 -04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*reply_token == '0')
|
|
|
|
vwarning = 0;
|
|
|
|
free(reply_token);
|
|
|
|
reply_token = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check the latest available ClamAV software version.
|
|
|
|
*/
|
|
|
|
if (NULL == (reply_token = cli_strtok(dnsReply, DNS_UPDATEINFO_NEWVERSION, ":"))) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "Failed to find New Version field in DNS Update Info.\n");
|
2019-03-26 15:09:52 -04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_DEBUG, "fc_dns_query_update_info: Software version from DNS: %s\n", reply_token);
|
2019-03-26 15:09:52 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Compare the latest available ClamAV version with this ClamAV version.
|
|
|
|
* Only throw a warning if the Version Warning Flag was set,
|
|
|
|
* and this is not a beta, release candidate, or development version.
|
|
|
|
*/
|
|
|
|
strncpy(version_string, get_version(), sizeof(version_string));
|
|
|
|
version_string[31] = 0;
|
|
|
|
|
|
|
|
if (vwarning) {
|
|
|
|
if (!strstr(version_string, "devel") &&
|
|
|
|
!strstr(version_string, "beta") &&
|
|
|
|
!strstr(version_string, "rc")) {
|
|
|
|
|
|
|
|
char *suffix = strchr(version_string, '-');
|
|
|
|
|
2019-08-06 17:59:11 -04:00
|
|
|
if ((suffix && (0 > version_string_compare(version_string, suffix - version_string, reply_token, strlen(reply_token)))) ||
|
|
|
|
(!suffix && (0 > version_string_compare(version_string, strlen(version_string), reply_token, strlen(reply_token))))) {
|
2019-03-26 15:09:52 -04:00
|
|
|
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "Your ClamAV installation is OUTDATED!\n");
|
|
|
|
logg(LOGG_WARNING, "Local version: %s Recommended version: %s\n", version_string, reply_token);
|
|
|
|
logg(LOGG_INFO, "DON'T PANIC! Read https://docs.clamav.net/manual/Installing.html\n");
|
2024-01-09 17:44:33 -05:00
|
|
|
*newVersion = cli_safer_strdup(reply_token);
|
2016-03-11 13:32:31 -07:00
|
|
|
}
|
|
|
|
}
|
2019-03-26 15:09:52 -04:00
|
|
|
}
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
free(reply_token);
|
|
|
|
reply_token = NULL;
|
|
|
|
|
|
|
|
*dnsUpdateInfo = dnsReply;
|
|
|
|
|
|
|
|
status = FC_SUCCESS;
|
|
|
|
|
|
|
|
#endif /* HAVE_RESOLV_H */
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
|
|
|
if (FC_SUCCESS != status) {
|
|
|
|
free(dnsReply);
|
2016-03-11 13:32:31 -07:00
|
|
|
}
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
fc_error_t fc_update_database(
|
|
|
|
const char *database,
|
|
|
|
char **serverList,
|
|
|
|
uint32_t nServers,
|
|
|
|
int bPrivateMirror,
|
|
|
|
const char *dnsUpdateInfo,
|
|
|
|
int bScriptedUpdates,
|
|
|
|
void *context,
|
|
|
|
int *bUpdated)
|
|
|
|
{
|
|
|
|
fc_error_t ret;
|
|
|
|
fc_error_t status = FC_EARG;
|
|
|
|
|
|
|
|
char *dbFilename = NULL;
|
2020-01-03 15:53:29 -05:00
|
|
|
int signo = 0;
|
|
|
|
long attempt = 1;
|
2019-03-26 15:09:52 -04:00
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
if ((NULL == database) || (NULL == serverList) || (NULL == bUpdated)) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "fc_update_database: Invalid arguments.\n");
|
2019-03-26 15:09:52 -04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
*bUpdated = 0;
|
|
|
|
|
|
|
|
/* Change directory to database directory */
|
|
|
|
if (chdir(g_databaseDirectory)) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_ERROR, "Can't change dir to %s\n", g_databaseDirectory);
|
2019-03-26 15:09:52 -04:00
|
|
|
status = FC_EDIRECTORY;
|
|
|
|
goto done;
|
|
|
|
}
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_DEBUG, "Current working dir is %s\n", g_databaseDirectory);
|
2019-03-26 15:09:52 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Attempt to update official database using DatabaseMirrors or PrivateMirrors.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < nServers; i++) {
|
|
|
|
for (attempt = 1; attempt <= g_maxAttempts; attempt++) {
|
|
|
|
ret = updatedb(
|
|
|
|
database,
|
|
|
|
dnsUpdateInfo,
|
|
|
|
serverList[i],
|
|
|
|
bPrivateMirror,
|
|
|
|
context,
|
|
|
|
bScriptedUpdates,
|
|
|
|
attempt == g_maxAttempts ? 1 : 0,
|
|
|
|
&signo,
|
|
|
|
&dbFilename,
|
|
|
|
bUpdated);
|
|
|
|
|
|
|
|
switch (ret) {
|
|
|
|
case FC_SUCCESS: {
|
2019-08-21 14:25:59 -07:00
|
|
|
if (*bUpdated) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_DEBUG, "fc_update_database: %s updated.\n", dbFilename);
|
2019-03-26 15:09:52 -04:00
|
|
|
} else {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_DEBUG, "fc_update_database: %s already up-to-date.\n", dbFilename);
|
2019-03-26 15:09:52 -04:00
|
|
|
}
|
|
|
|
goto success;
|
|
|
|
}
|
|
|
|
case FC_ECONNECTION:
|
|
|
|
case FC_EBADCVD:
|
2021-03-20 21:25:18 -07:00
|
|
|
case FC_EFAILEDGET: {
|
2019-03-26 15:09:52 -04:00
|
|
|
if (attempt < g_maxAttempts) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_INFO, "Trying again in 5 secs...\n");
|
2019-03-26 15:09:52 -04:00
|
|
|
sleep(5);
|
|
|
|
} else {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_INFO, "Giving up on %s...\n", serverList[i]);
|
2019-03-26 15:09:52 -04:00
|
|
|
if (i == nServers - 1) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_ERROR, "Update failed for database: %s\n", database);
|
2019-03-26 15:09:52 -04:00
|
|
|
status = ret;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
2019-05-21 17:40:45 -04:00
|
|
|
break;
|
2019-03-26 15:09:52 -04:00
|
|
|
}
|
2021-03-20 21:25:18 -07:00
|
|
|
case FC_EMIRRORNOTSYNC: {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_INFO, "Received an older %s CVD than was advertised. We'll retry so the incremental update will ensure we're up-to-date.\n", database);
|
2021-03-22 13:36:02 -07:00
|
|
|
break;
|
2021-03-20 21:25:18 -07:00
|
|
|
}
|
|
|
|
case FC_EFORBIDDEN: {
|
2021-10-06 17:02:44 -07:00
|
|
|
char retry_after_string[26];
|
|
|
|
struct tm *tm_info;
|
|
|
|
tm_info = localtime(&g_freshclamDat->retry_after);
|
|
|
|
if (NULL == tm_info) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_ERROR, "Failed to query the local time for the retry-after date!\n");
|
2021-10-06 17:02:44 -07:00
|
|
|
status = FC_ERROR;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
strftime(retry_after_string, 26, "%Y-%m-%d %H:%M:%S", tm_info);
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "FreshClam received error code 403 from the ClamAV Content Delivery Network (CDN).\n");
|
|
|
|
logg(LOGG_INFO, "This could mean several things:\n");
|
|
|
|
logg(LOGG_INFO, " 1. You are running an out-of-date version of ClamAV / FreshClam.\n");
|
|
|
|
logg(LOGG_INFO, " Ensure you are the most updated version by visiting https://www.clamav.net/downloads\n");
|
|
|
|
logg(LOGG_INFO, " 2. Your network is explicitly denied by the FreshClam CDN.\n");
|
|
|
|
logg(LOGG_INFO, " In order to rectify this please check that you are:\n");
|
|
|
|
logg(LOGG_INFO, " a. Running an up-to-date version of FreshClam\n");
|
|
|
|
logg(LOGG_INFO, " b. Running FreshClam no more than once an hour\n");
|
2024-03-15 16:40:20 -04:00
|
|
|
logg(LOGG_INFO, " c. Connecting from an IP in a blocked region\n");
|
|
|
|
logg(LOGG_INFO, " Please see https://www.cisco.com/c/m/en_us/crisissupport.html\n");
|
|
|
|
logg(LOGG_INFO, " d. If you have checked (a), (b) and (c), please open a ticket at\n");
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_INFO, " https://github.com/Cisco-Talos/clamav/issues\n");
|
|
|
|
logg(LOGG_INFO, " and we will investigate why your network is blocked.\n");
|
2024-03-15 16:40:20 -04:00
|
|
|
if (0 != g_lastRay[0]) {
|
|
|
|
logg(LOGG_INFO, " Please provide the following cf-ray id with your ticket: %s\n", g_lastRay);
|
|
|
|
logg(LOGG_INFO, "\n");
|
|
|
|
}
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "You are on cool-down until after: %s\n", retry_after_string);
|
2021-03-20 21:25:18 -07:00
|
|
|
status = ret;
|
|
|
|
goto done;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FC_ERETRYLATER: {
|
2021-03-21 19:47:21 -07:00
|
|
|
char retry_after_string[26];
|
|
|
|
struct tm *tm_info;
|
2021-05-24 18:37:33 -07:00
|
|
|
tm_info = localtime(&g_freshclamDat->retry_after);
|
2021-03-25 13:31:46 -07:00
|
|
|
if (NULL == tm_info) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_ERROR, "Failed to query the local time for the retry-after date!\n");
|
2021-03-25 13:31:46 -07:00
|
|
|
status = FC_ERROR;
|
|
|
|
goto done;
|
|
|
|
}
|
2021-03-21 19:47:21 -07:00
|
|
|
strftime(retry_after_string, 26, "%Y-%m-%d %H:%M:%S", tm_info);
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "FreshClam received error code 429 from the ClamAV Content Delivery Network (CDN).\n");
|
|
|
|
logg(LOGG_INFO, "This means that you have been rate limited by the CDN.\n");
|
|
|
|
logg(LOGG_INFO, " 1. Run FreshClam no more than once an hour to check for updates.\n");
|
|
|
|
logg(LOGG_INFO, " FreshClam should check DNS first to see if an update is needed.\n");
|
|
|
|
logg(LOGG_INFO, " 2. If you have more than 10 hosts on your network attempting to download,\n");
|
|
|
|
logg(LOGG_INFO, " it is recommended that you set up a private mirror on your network using\n");
|
|
|
|
logg(LOGG_INFO, " cvdupdate (https://pypi.org/project/cvdupdate/) to save bandwidth on the\n");
|
|
|
|
logg(LOGG_INFO, " CDN and your own network.\n");
|
|
|
|
logg(LOGG_INFO, " 3. Please do not open a ticket asking for an exemption from the rate limit,\n");
|
|
|
|
logg(LOGG_INFO, " it will not be granted.\n");
|
|
|
|
logg(LOGG_WARNING, "You are on cool-down until after: %s\n", retry_after_string);
|
2021-03-20 21:25:18 -07:00
|
|
|
goto success;
|
|
|
|
break;
|
|
|
|
}
|
2019-03-26 15:09:52 -04:00
|
|
|
default: {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_ERROR, "Unexpected error when attempting to update %s: %s\n", database, fc_strerror(ret));
|
2019-03-26 15:09:52 -04:00
|
|
|
status = ret;
|
|
|
|
goto done;
|
|
|
|
}
|
2016-03-11 13:32:31 -07:00
|
|
|
}
|
|
|
|
}
|
2019-03-26 15:09:52 -04:00
|
|
|
}
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
success:
|
|
|
|
|
|
|
|
status = FC_SUCCESS;
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
|
|
|
if (NULL != dbFilename) {
|
|
|
|
free(dbFilename);
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
fc_error_t fc_update_databases(
|
|
|
|
char **databaseList,
|
|
|
|
uint32_t nDatabases,
|
|
|
|
char **serverList,
|
|
|
|
uint32_t nServers,
|
|
|
|
int bPrivateMirror,
|
|
|
|
const char *dnsUpdateInfo,
|
|
|
|
int bScriptedUpdates,
|
|
|
|
void *context,
|
|
|
|
uint32_t *nUpdated)
|
|
|
|
{
|
|
|
|
fc_error_t ret;
|
|
|
|
fc_error_t status = FC_EARG;
|
|
|
|
uint32_t i;
|
|
|
|
int bUpdated = 0;
|
|
|
|
uint32_t numUpdated = 0;
|
|
|
|
|
|
|
|
if ((NULL == databaseList) || (0 == nDatabases) || (NULL == serverList) || (NULL == nUpdated)) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "fc_update_databases: Invalid arguments.\n");
|
2019-03-26 15:09:52 -04:00
|
|
|
goto done;
|
2016-03-11 13:32:31 -07:00
|
|
|
}
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
*nUpdated = 0;
|
|
|
|
|
2021-05-24 18:37:33 -07:00
|
|
|
if (g_freshclamDat->retry_after > 0) {
|
|
|
|
if (g_freshclamDat->retry_after > time(NULL)) {
|
2021-03-21 19:47:21 -07:00
|
|
|
/* We're on cool-down, try again later. */
|
|
|
|
char retry_after_string[26];
|
|
|
|
struct tm *tm_info;
|
2021-05-24 18:37:33 -07:00
|
|
|
tm_info = localtime(&g_freshclamDat->retry_after);
|
2021-03-25 13:31:46 -07:00
|
|
|
if (NULL == tm_info) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_ERROR, "Failed to query the local time for the retry-after date!\n");
|
2021-03-25 13:31:46 -07:00
|
|
|
status = FC_ERROR;
|
|
|
|
goto done;
|
|
|
|
}
|
2021-03-21 19:47:21 -07:00
|
|
|
strftime(retry_after_string, 26, "%Y-%m-%d %H:%M:%S", tm_info);
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "FreshClam previously received error code 429 or 403 from the ClamAV Content Delivery Network (CDN).\n");
|
|
|
|
logg(LOGG_INFO, "This means that you have been rate limited or blocked by the CDN.\n");
|
|
|
|
logg(LOGG_INFO, " 1. Verify that you're running a supported ClamAV version.\n");
|
|
|
|
logg(LOGG_INFO, " See https://docs.clamav.net/faq/faq-eol.html for details.\n");
|
|
|
|
logg(LOGG_INFO, " 2. Run FreshClam no more than once an hour to check for updates.\n");
|
|
|
|
logg(LOGG_INFO, " FreshClam should check DNS first to see if an update is needed.\n");
|
|
|
|
logg(LOGG_INFO, " 3. If you have more than 10 hosts on your network attempting to download,\n");
|
|
|
|
logg(LOGG_INFO, " it is recommended that you set up a private mirror on your network using\n");
|
|
|
|
logg(LOGG_INFO, " cvdupdate (https://pypi.org/project/cvdupdate/) to save bandwidth on the\n");
|
|
|
|
logg(LOGG_INFO, " CDN and your own network.\n");
|
|
|
|
logg(LOGG_INFO, " 4. Please do not open a ticket asking for an exemption from the rate limit,\n");
|
|
|
|
logg(LOGG_INFO, " it will not be granted.\n");
|
2024-03-15 16:40:20 -04:00
|
|
|
if (0 != g_lastRay[0]) {
|
|
|
|
logg(LOGG_INFO, " 5. If you have verified that you are not blocked due to your region, and have\n");
|
|
|
|
logg(LOGG_INFO, " not exceeded the rate limit, please provide the following cf-ray id when\n");
|
|
|
|
logg(LOGG_INFO, " submitting a ticket: %s\n", g_lastRay);
|
|
|
|
logg(LOGG_INFO, "\n");
|
|
|
|
}
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "You are still on cool-down until after: %s\n", retry_after_string);
|
2024-03-15 16:40:20 -04:00
|
|
|
|
2021-03-21 19:47:21 -07:00
|
|
|
status = FC_SUCCESS;
|
|
|
|
goto done;
|
|
|
|
} else {
|
2021-05-24 18:37:33 -07:00
|
|
|
g_freshclamDat->retry_after = 0;
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "Cool-down expired, ok to try again.\n");
|
2021-05-24 18:37:33 -07:00
|
|
|
save_freshclam_dat();
|
2021-03-21 19:47:21 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-15 16:40:20 -04:00
|
|
|
/* Clear the old cf-ray ids. This is really only so that
|
|
|
|
* we don't have stale ones when we are running in daemon mode. */
|
|
|
|
memset(&g_lastRay, 0, sizeof(g_lastRay));
|
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
for (i = 0; i < nDatabases; i++) {
|
|
|
|
if (FC_SUCCESS != (ret = fc_update_database(
|
|
|
|
databaseList[i],
|
|
|
|
serverList,
|
|
|
|
nServers,
|
|
|
|
bPrivateMirror,
|
|
|
|
dnsUpdateInfo,
|
|
|
|
bScriptedUpdates,
|
|
|
|
context,
|
|
|
|
&bUpdated))) {
|
|
|
|
status = ret;
|
|
|
|
goto done;
|
2016-03-11 13:32:31 -07:00
|
|
|
}
|
2019-03-26 15:09:52 -04:00
|
|
|
if (bUpdated) {
|
|
|
|
numUpdated++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*nUpdated = numUpdated;
|
|
|
|
status = FC_SUCCESS;
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
fc_error_t fc_download_url_database(
|
|
|
|
const char *urlDatabase,
|
|
|
|
void *context,
|
|
|
|
int *bUpdated)
|
|
|
|
{
|
|
|
|
fc_error_t ret;
|
|
|
|
fc_error_t status = FC_EARG;
|
|
|
|
|
|
|
|
long attempt = 1;
|
|
|
|
char *dbFilename = NULL;
|
|
|
|
|
|
|
|
if ((NULL == urlDatabase) || (NULL == bUpdated)) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "fc_download_url_database: Invalid arguments.\n");
|
2019-03-26 15:09:52 -04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
*bUpdated = 0;
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
/* Change directory to database directory */
|
|
|
|
if (chdir(g_databaseDirectory)) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_ERROR, "Can't change dir to %s\n", g_databaseDirectory);
|
2019-03-26 15:09:52 -04:00
|
|
|
status = FC_EDIRECTORY;
|
|
|
|
goto done;
|
|
|
|
}
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_DEBUG, "Current working dir is %s\n", g_databaseDirectory);
|
2019-03-26 15:09:52 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Attempt to update official database using DatabaseMirrors or PrivateMirrors.
|
|
|
|
*/
|
|
|
|
for (attempt = 1; attempt <= g_maxAttempts; attempt++) {
|
|
|
|
int signo = 0;
|
|
|
|
|
|
|
|
ret = updatecustomdb(
|
|
|
|
urlDatabase,
|
|
|
|
context,
|
|
|
|
attempt == g_maxAttempts ? 1 : 0,
|
|
|
|
&signo,
|
|
|
|
&dbFilename,
|
|
|
|
bUpdated);
|
|
|
|
|
|
|
|
switch (ret) {
|
|
|
|
case FC_SUCCESS: {
|
2019-08-21 14:25:59 -07:00
|
|
|
if (*bUpdated) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_DEBUG, "fc_download_url_database: %s updated.\n", dbFilename);
|
2019-03-26 15:09:52 -04:00
|
|
|
} else {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_DEBUG, "fc_download_url_database: %s already up-to-date.\n", dbFilename);
|
2019-03-26 15:09:52 -04:00
|
|
|
}
|
|
|
|
goto success;
|
2016-03-11 13:32:31 -07:00
|
|
|
}
|
2019-03-26 15:09:52 -04:00
|
|
|
case FC_ECONNECTION:
|
|
|
|
case FC_EBADCVD:
|
|
|
|
case FC_EFAILEDGET: {
|
|
|
|
if (attempt < g_maxAttempts) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_INFO, "Trying again in 5 secs...\n");
|
2019-03-26 15:09:52 -04:00
|
|
|
sleep(5);
|
|
|
|
} else {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_INFO, "Update failed for custom database URL: %s\n", urlDatabase);
|
2019-03-26 15:09:52 -04:00
|
|
|
status = ret;
|
|
|
|
goto done;
|
2016-03-11 13:32:31 -07:00
|
|
|
}
|
2019-05-21 17:40:45 -04:00
|
|
|
break;
|
2016-03-11 13:32:31 -07:00
|
|
|
}
|
2021-03-21 19:47:21 -07:00
|
|
|
case FC_EFORBIDDEN: {
|
2021-10-06 17:02:44 -07:00
|
|
|
char retry_after_string[26];
|
|
|
|
struct tm *tm_info;
|
|
|
|
tm_info = localtime(&g_freshclamDat->retry_after);
|
|
|
|
if (NULL == tm_info) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_ERROR, "Failed to query the local time for the retry-after date!\n");
|
2021-10-06 17:02:44 -07:00
|
|
|
status = FC_ERROR;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
strftime(retry_after_string, 26, "%Y-%m-%d %H:%M:%S", tm_info);
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "FreshClam received error code 403 from the ClamAV Content Delivery Network (CDN).\n");
|
|
|
|
logg(LOGG_INFO, "This could mean several things:\n");
|
|
|
|
logg(LOGG_INFO, " 1. You are running an out-of-date version of ClamAV / FreshClam.\n");
|
|
|
|
logg(LOGG_INFO, " Ensure you are the most updated version by visiting https://www.clamav.net/downloads\n");
|
|
|
|
logg(LOGG_INFO, " 2. Your network is explicitly denied by the FreshClam CDN.\n");
|
|
|
|
logg(LOGG_INFO, " In order to rectify this please check that you are:\n");
|
|
|
|
logg(LOGG_INFO, " a. Running an up-to-date version of FreshClam\n");
|
|
|
|
logg(LOGG_INFO, " b. Running FreshClam no more than once an hour\n");
|
|
|
|
logg(LOGG_INFO, " c. If you have checked (a) and (b), please open a ticket at\n");
|
|
|
|
logg(LOGG_INFO, " https://github.com/Cisco-Talos/clamav/issues\n");
|
|
|
|
logg(LOGG_INFO, " and we will investigate why your network is blocked.\n");
|
2024-03-15 16:40:20 -04:00
|
|
|
if (0 != g_lastRay[0]) {
|
|
|
|
logg(LOGG_INFO, " Please provide the following cf-ray id with your ticket: %s\n", g_lastRay);
|
|
|
|
logg(LOGG_INFO, "\n");
|
|
|
|
}
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "You are on cool-down until after: %s\n", retry_after_string);
|
2024-03-15 16:40:20 -04:00
|
|
|
|
2021-03-21 19:47:21 -07:00
|
|
|
status = ret;
|
|
|
|
goto done;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FC_ERETRYLATER: {
|
|
|
|
char retry_after_string[26];
|
|
|
|
struct tm *tm_info;
|
2021-05-24 18:37:33 -07:00
|
|
|
tm_info = localtime(&g_freshclamDat->retry_after);
|
2021-03-25 13:31:46 -07:00
|
|
|
if (NULL == tm_info) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_ERROR, "Failed to query the local time for the retry-after date!\n");
|
2021-03-25 13:31:46 -07:00
|
|
|
status = FC_ERROR;
|
|
|
|
goto done;
|
|
|
|
}
|
2021-03-21 19:47:21 -07:00
|
|
|
strftime(retry_after_string, 26, "%Y-%m-%d %H:%M:%S", tm_info);
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "FreshClam received error code 429 from the ClamAV Content Delivery Network (CDN).\n");
|
|
|
|
logg(LOGG_INFO, "This means that you have been rate limited by the CDN.\n");
|
|
|
|
logg(LOGG_INFO, " 1. Run FreshClam no more than once an hour to check for updates.\n");
|
|
|
|
logg(LOGG_INFO, " FreshClam should check DNS first to see if an update is needed.\n");
|
|
|
|
logg(LOGG_INFO, " 2. If you have more than 10 hosts on your network attempting to download,\n");
|
|
|
|
logg(LOGG_INFO, " it is recommended that you set up a private mirror on your network using\n");
|
|
|
|
logg(LOGG_INFO, " cvdupdate (https://pypi.org/project/cvdupdate/) to save bandwidth on the\n");
|
|
|
|
logg(LOGG_INFO, " CDN and your own network.\n");
|
|
|
|
logg(LOGG_INFO, " 3. Please do not open a ticket asking for an exemption from the rate limit,\n");
|
|
|
|
logg(LOGG_INFO, " it will not be granted.\n");
|
|
|
|
logg(LOGG_WARNING, "You are on cool-down until after: %s\n", retry_after_string);
|
2021-03-21 19:47:21 -07:00
|
|
|
goto success;
|
|
|
|
break;
|
|
|
|
}
|
2019-03-26 15:09:52 -04:00
|
|
|
default: {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_INFO, "Unexpected error when attempting to update from custom database URL: %s\n", urlDatabase);
|
2019-03-26 15:09:52 -04:00
|
|
|
status = ret;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
success:
|
|
|
|
|
|
|
|
status = FC_SUCCESS;
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
|
|
|
if (NULL != dbFilename) {
|
|
|
|
free(dbFilename);
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
fc_error_t fc_download_url_databases(
|
|
|
|
char **urlDatabaseList,
|
|
|
|
uint32_t nUrlDatabases,
|
|
|
|
void *context,
|
|
|
|
uint32_t *nUpdated)
|
|
|
|
{
|
|
|
|
fc_error_t ret;
|
|
|
|
fc_error_t status = FC_EARG;
|
|
|
|
int bUpdated = 0;
|
|
|
|
uint32_t numUpdated = 0;
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
if ((NULL == urlDatabaseList) || (0 == nUrlDatabases) || (NULL == nUpdated)) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "fc_download_url_databases: Invalid arguments.\n");
|
2019-03-26 15:09:52 -04:00
|
|
|
goto done;
|
|
|
|
}
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
*nUpdated = 0;
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
for (i = 0; i < nUrlDatabases; i++) {
|
|
|
|
if (FC_SUCCESS != (ret = fc_download_url_database(
|
|
|
|
urlDatabaseList[i],
|
|
|
|
context,
|
|
|
|
&bUpdated))) {
|
2022-02-16 00:13:55 +01:00
|
|
|
logg(LOGG_WARNING, "fc_download_url_databases: fc_download_url_database failed: %s (%d)\n", fc_strerror(ret), ret);
|
2019-03-26 15:09:52 -04:00
|
|
|
status = ret;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if (bUpdated) {
|
|
|
|
numUpdated++;
|
|
|
|
}
|
2016-03-11 13:32:31 -07:00
|
|
|
}
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
*nUpdated = numUpdated;
|
|
|
|
status = FC_SUCCESS;
|
|
|
|
|
|
|
|
done:
|
2018-12-03 12:40:13 -05:00
|
|
|
|
2019-03-26 15:09:52 -04:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
void fc_set_fccb_download_complete(fccb_download_complete callback)
|
|
|
|
{
|
|
|
|
g_cb_download_complete = callback;
|
2016-03-11 13:32:31 -07:00
|
|
|
}
|