Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/lavabit/magma.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLadar Levison <ladar@lavabit.com>2022-04-05 17:23:21 +0300
committerLadar Levison <ladar@lavabit.com>2022-04-06 01:27:54 +0300
commit0fe89455712db142b144256ef2178a9f7f1110b9 (patch)
tree78808758e176a2fc21b8ea894956cbf3b33d47b1
parenteddef7cf97bdcf059c464b4723dba0310b0e8d38 (diff)
ClamAV updated to 0.103.5. Patches for 0.104.2 generated but currently unused.
-rw-r--r--dev/scripts/builders/build.lib.params.sh4
-rwxr-xr-xdev/scripts/builders/build.lib.sh11
-rw-r--r--lib/archives/clamav-0.103.5.tar.gz (renamed from lib/archives/clamav-0.102.3.tar.gz)bin13226108 -> 16434316 bytes
-rw-r--r--lib/check/magma.open.symbols.c20
-rw-r--r--lib/check/magma.open.symbols.h20
-rw-r--r--lib/patches/clamav/freshclam_cafile_option_01035.patch107
-rw-r--r--lib/patches/clamav/shutdown_rarload_01035.patch256
-rw-r--r--lib/patches/clamav/shutdown_rarload_01042.patch52
-rw-r--r--lib/patches/clamav/version_0984.patch1
-rw-r--r--sandbox/etc/freshclam.conf1
-rw-r--r--src/providers/symbols.c20
-rw-r--r--src/providers/symbols.h20
12 files changed, 455 insertions, 57 deletions
diff --git a/dev/scripts/builders/build.lib.params.sh b/dev/scripts/builders/build.lib.params.sh
index fb07d7f2..b48c4882 100644
--- a/dev/scripts/builders/build.lib.params.sh
+++ b/dev/scripts/builders/build.lib.params.sh
@@ -13,7 +13,9 @@ PCRE="pcre2-10.31"
BZIP2="bzip2-1.0.8"
DSPAM="dspam-3.10.2"
GEOIP="GeoIP-1.4.8"
-CLAMAV="clamav-0.102.3"
+#CLAMAV="clamav-0.104.2"
+CLAMAV="clamav-0.103.5"
+#CLAMAV="clamav-0.102.3"
MARIADB="mariadb-connector-c-2.3.7"
CHECKER="check-0.11.0"
OPENSSL="openssl-1.0.2u"
diff --git a/dev/scripts/builders/build.lib.sh b/dev/scripts/builders/build.lib.sh
index fccf0c82..4b92f2a9 100755
--- a/dev/scripts/builders/build.lib.sh
+++ b/dev/scripts/builders/build.lib.sh
@@ -1308,11 +1308,20 @@ clamav() {
# Output the version number and not the git commit hash.
cat "$M_PATCHES/clamav/"version_0984.patch | patch -p1 --verbose &>> "$M_LOGS/clamav.txt"; error
+ elif [[ $CLAMAV =~ "clamav-0.103.5" ]]; then
+ # Add the shutdown and clean up functions and fix the rar library dynamic loading logic.
+ cat "$M_PATCHES/clamav/"shutdown_rarload_01035.patch | patch -p1 --verbose &>> "$M_LOGS/clamav.txt"; error
+
+ # Add the ability to dictate the CA bundle file location when running freshclam.
+ cat "$M_PATCHES/clamav/"freshclam_cafile_option_01035.patch | patch -p1 --verbose &>> "$M_LOGS/clamav.txt"; error
+
+ # Output the version number and not the git commit hash.
+ cat "$M_PATCHES/clamav/"version_0984.patch | patch -p1 --verbose &>> "$M_LOGS/clamav.txt"; error
# Applied to most recent version.
else
# Add the shutdown and clean up functions and fix the rar library dynamic loading logic.
- cat "$M_PATCHES/clamav/"shutdown_rarload_01042.patch | patch -p1 --fuzz=100 --verbose &>> "$M_LOGS/clamav.txt"; error
+ cat "$M_PATCHES/clamav/"shutdown_rarload_01042.patch | patch -p1 --verbose &>> "$M_LOGS/clamav.txt"; error
# Add the ability to dictate the CA bundle file location when running freshclam.
cat "$M_PATCHES/clamav/"freshclam_cafile_option_01042.patch | patch -p1 --verbose &>> "$M_LOGS/clamav.txt"; error
diff --git a/lib/archives/clamav-0.102.3.tar.gz b/lib/archives/clamav-0.103.5.tar.gz
index 6d2ac8e6..23bb92bb 100644
--- a/lib/archives/clamav-0.102.3.tar.gz
+++ b/lib/archives/clamav-0.103.5.tar.gz
Binary files differ
diff --git a/lib/check/magma.open.symbols.c b/lib/check/magma.open.symbols.c
index 1af4656f..3ed3398b 100644
--- a/lib/check/magma.open.symbols.c
+++ b/lib/check/magma.open.symbols.c
@@ -25,19 +25,19 @@ int (*BZ2_bzBuffToBuffDecompress_d)(char *dest, unsigned int *destLen, char *sou
int (*BZ2_bzBuffToBuffCompress_d)(char *dest, unsigned int *destLen, char *source, unsigned int sourceLen, int blockSize100k, int verbosity, int workFactor) = NULL;
void (*cl_shutdown_d)(void) = NULL;
const char * (*cl_retver_d)(void) = NULL;
-int (*cl_init_d)(unsigned int initoptions) = NULL;
+cl_error_t (*cl_init_d)(unsigned int initoptions) = NULL;
const char * (*cl_strerror_d)(int clerror) = NULL;
struct cl_engine * (*cl_engine_new_d)(void) = NULL;
-int (*cl_statfree_d)(struct cl_stat *dbstat) = NULL;
-int (*cl_engine_free_d)(struct cl_engine *engine) = NULL;
-int (*cl_engine_compile_d)(struct cl_engine *engine) = NULL;
+cl_error_t (*cl_statfree_d)(struct cl_stat *dbstat) = NULL;
+cl_error_t (*cl_engine_free_d)(struct cl_engine *engine) = NULL;
+cl_error_t (*cl_engine_compile_d)(struct cl_engine *engine) = NULL;
int (*cl_statchkdir_d)(const struct cl_stat *dbstat) = NULL;
-int (*cl_statinidir_d)(const char *dirname, struct cl_stat *dbstat) = NULL;
-int (*cl_countsigs_d)(const char *path, unsigned int countoptions, unsigned int *sigs) = NULL;
-int (*cl_engine_set_num_d)(struct cl_engine *engine, enum cl_engine_field field, long long num) = NULL;
-int (*cl_engine_set_str_d)(struct cl_engine *engine, enum cl_engine_field field, const char *str) = NULL;
-int (*cl_load_d)(const char *path, struct cl_engine *engine, unsigned int *signo, unsigned int dboptions) = NULL;
-int (*cl_scandesc_d)(int desc, const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options *scanoptions) = NULL;
+cl_error_t (*cl_statinidir_d)(const char *dirname, struct cl_stat *dbstat) = NULL;
+cl_error_t (*cl_countsigs_d)(const char *path, unsigned int countoptions, unsigned int *sigs) = NULL;
+cl_error_t (*cl_engine_set_num_d)(struct cl_engine *engine, enum cl_engine_field field, long long num) = NULL;
+cl_error_t (*cl_engine_set_str_d)(struct cl_engine *engine, enum cl_engine_field field, const char *str) = NULL;
+cl_error_t (*cl_load_d)(const char *path, struct cl_engine *engine, unsigned int *signo, unsigned int dboptions) = NULL;
+cl_error_t (*cl_scandesc_d)(int desc, const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options *scanoptions) = NULL;
const char * (*dspam_version_d)(void) = NULL;
int (*dspam_detach_d)(DSPAM_CTX *CTX) = NULL;
void (*dspam_destroy_d)(DSPAM_CTX * CTX) = NULL;
diff --git a/lib/check/magma.open.symbols.h b/lib/check/magma.open.symbols.h
index 8db5dcf0..e3fd51e7 100644
--- a/lib/check/magma.open.symbols.h
+++ b/lib/check/magma.open.symbols.h
@@ -138,19 +138,19 @@ extern int (*BZ2_bzBuffToBuffCompress_d)(char *dest, unsigned int *destLen, char
//! CLAMAV
extern void (*cl_shutdown_d)(void);
extern const char * (*cl_retver_d)(void);
-extern int (*cl_init_d)(unsigned int initoptions);
+extern cl_error_t (*cl_init_d)(unsigned int initoptions);
extern const char * (*cl_strerror_d)(int clerror);
extern struct cl_engine * (*cl_engine_new_d)(void);
-extern int (*cl_statfree_d)(struct cl_stat *dbstat);
-extern int (*cl_engine_free_d)(struct cl_engine *engine);
-extern int (*cl_engine_compile_d)(struct cl_engine *engine);
+extern cl_error_t (*cl_statfree_d)(struct cl_stat *dbstat);
+extern cl_error_t (*cl_engine_free_d)(struct cl_engine *engine);
+extern cl_error_t (*cl_engine_compile_d)(struct cl_engine *engine);
extern int (*cl_statchkdir_d)(const struct cl_stat *dbstat);
-extern int (*cl_statinidir_d)(const char *dirname, struct cl_stat *dbstat);
-extern int (*cl_countsigs_d)(const char *path, unsigned int countoptions, unsigned int *sigs);
-extern int (*cl_engine_set_num_d)(struct cl_engine *engine, enum cl_engine_field field, long long num);
-extern int (*cl_engine_set_str_d)(struct cl_engine *engine, enum cl_engine_field field, const char *str);
-extern int (*cl_load_d)(const char *path, struct cl_engine *engine, unsigned int *signo, unsigned int dboptions);
-extern int (*cl_scandesc_d)(int desc, const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options *scanoptions);
+extern cl_error_t (*cl_statinidir_d)(const char *dirname, struct cl_stat *dbstat);
+extern cl_error_t (*cl_countsigs_d)(const char *path, unsigned int countoptions, unsigned int *sigs);
+extern cl_error_t (*cl_engine_set_num_d)(struct cl_engine *engine, enum cl_engine_field field, long long num);
+extern cl_error_t (*cl_engine_set_str_d)(struct cl_engine *engine, enum cl_engine_field field, const char *str);
+extern cl_error_t (*cl_load_d)(const char *path, struct cl_engine *engine, unsigned int *signo, unsigned int dboptions);
+extern cl_error_t (*cl_scandesc_d)(int desc, const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options *scanoptions);
//! DSPAM
extern const char * (*dspam_version_d)(void);
diff --git a/lib/patches/clamav/freshclam_cafile_option_01035.patch b/lib/patches/clamav/freshclam_cafile_option_01035.patch
new file mode 100644
index 00000000..c61c1673
--- /dev/null
+++ b/lib/patches/clamav/freshclam_cafile_option_01035.patch
@@ -0,0 +1,107 @@
+diff --git a/freshclam/freshclam.c b/freshclam/freshclam.c
+index 1f97d51..a9c33d3 100644
+--- a/freshclam/freshclam.c
++++ b/freshclam/freshclam.c
+@@ -173,6 +173,7 @@ static void help(void)
+ printf("\n");
+ printf(" --config-file=FILE Read configuration from FILE.\n");
+ printf(" --log=FILE -l FILE Log into FILE\n");
++ printf(" --ca=FILE Override the certificate bundle FILE location\n");
+ printf(" --daemon -d Run in daemon mode\n");
+ printf(" --pid=FILE -p FILE Save daemon's pid in FILE\n");
+ #ifndef _WIN32
+@@ -875,6 +876,7 @@ static fc_error_t initialize(struct optstruct *opts)
+ fcConfig.localIP = (optget(opts, "LocalIPAddress"))->strarg;
+
+ /* Select a path for the temp directory: databaseDirectory/tmp */
++ fcConfig.caFile = optget(opts, "CAFile")->strarg;
+ tempDirectory = cli_gentemp_with_prefix(fcConfig.databaseDirectory, "tmp");
+ fcConfig.tempDirectory = tempDirectory;
+
+diff --git a/libfreshclam/libfreshclam.c b/libfreshclam/libfreshclam.c
+index 6258626..fde1ab7 100644
+--- a/libfreshclam/libfreshclam.c
++++ b/libfreshclam/libfreshclam.c
+@@ -213,6 +213,9 @@ fc_error_t fc_initialize(fc_config *fcConfig)
+ if (NULL != fcConfig->proxyPassword) {
+ g_proxyPassword = cli_strdup(fcConfig->proxyPassword);
+ }
++ if (NULL != fcConfig->caFile) {
++ g_caFile = cli_strdup(fcConfig->caFile);
++ }
+
+ #ifdef _WIN32
+ if ((fcConfig->databaseDirectory[strlen(fcConfig->databaseDirectory) - 1] != '/') &&
+@@ -288,6 +291,10 @@ void fc_cleanup(void)
+ free(g_userAgent);
+ g_userAgent = NULL;
+ }
++ if (NULL != g_caFile) {
++ free(g_caFile);
++ g_caFile = NULL;
++ }
+ if (NULL != g_proxyServer) {
+ free(g_proxyServer);
+ g_proxyServer = NULL;
+diff --git a/libfreshclam/libfreshclam.h b/libfreshclam/libfreshclam.h
+index c7da23d..0780f2c 100644
+--- a/libfreshclam/libfreshclam.h
++++ b/libfreshclam/libfreshclam.h
+@@ -50,6 +50,7 @@ typedef struct fc_config_ {
+ uint32_t connectTimeout; /**< CURLOPT_CONNECTTIMEOUT, Timeout for the. connection phase (seconds). */
+ uint32_t requestTimeout; /**< CURLOPT_TIMEOUT, Timeout for libcurl transfer operation (seconds). */
+ uint32_t bCompressLocalDatabase; /**< If set, will apply gz compression to CLD databases. */
++ const char *caFile; /**< (optional) CA file to use for certificate verification, if desired. */
+ const char *logFile; /**< (optional) Filepath to use for log output, if desired. */
+ const char *logFacility; /**< (optional) System logging facility (I.e. "syslog"), if desired. */
+ const char *localIP; /**< (optional) client IP for multihomed systems. */
+diff --git a/libfreshclam/libfreshclam_internal.c b/libfreshclam/libfreshclam_internal.c
+index f6128e6..e92d266 100644
+--- a/libfreshclam/libfreshclam_internal.c
++++ b/libfreshclam/libfreshclam_internal.c
+@@ -107,6 +107,7 @@ uint16_t g_proxyPort = 0;
+ char *g_proxyUsername = NULL;
+ char *g_proxyPassword = NULL;
+
++char *g_caFile = NULL;
+ char *g_tempDirectory = NULL;
+ char *g_databaseDirectory = NULL;
+
+@@ -709,6 +710,12 @@ static fc_error_t create_curl_handle(
+ }
+ }
+
++ if (g_caFile) {
++ if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_CAINFO, g_caFile)) {
++ logg("!create_curl_handle: Failed to set CURLOPT_CAINFO (%s)!\n", g_caFile);
++ }
++ }
++
+ #if defined(C_DARWIN) || defined(_WIN32)
+ if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function)) {
+ logg("*create_curl_handle: Failed to set SSL CTX function. Your libcurl may use an SSL backend that does not support CURLOPT_SSL_CTX_FUNCTION.\n");
+diff --git a/libfreshclam/libfreshclam_internal.h b/libfreshclam/libfreshclam_internal.h
+index 890d7e5..401d0d4 100644
+--- a/libfreshclam/libfreshclam_internal.h
++++ b/libfreshclam/libfreshclam_internal.h
+@@ -54,6 +54,7 @@ extern uint16_t g_proxyPort;
+ extern char *g_proxyUsername;
+ extern char *g_proxyPassword;
+
++extern char *g_caFile;
+ extern char *g_tempDirectory;
+ extern char *g_databaseDirectory;
+
+diff --git a/shared/optparser.c b/shared/optparser.c
+index 3d540b9..63b8d66 100644
+--- a/shared/optparser.c
++++ b/shared/optparser.c
+@@ -264,6 +264,8 @@ const struct clam_option __clam_options[] = {
+
+ {"DatabaseDirectory", "datadir", 0, CLOPT_TYPE_STRING, NULL, -1, CONST_DATADIR, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_SIGTOOL, "This option allows you to change the default database directory.\nIf you enable it, please make sure it points to the same directory in\nboth clamd and freshclam.", "/var/lib/clamav"},
+
++ {"CAFile", "ca", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM, "This option allows you to override the location of the CA bundle file used by freshclam.\nIf you enable it, please make sure it points to a valid certifcate bundle file.\n", ""},
++
+ {"OfficialDatabaseOnly", "official-db-only", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Only load the official signatures published by the ClamAV project.", "no"},
+
+ {"YaraRules", "yara-rules", 0, CLOPT_TYPE_STRING, NULL, 0, NULL, 0, OPT_CLAMSCAN, "By default, yara rules will be loaded. This option allows you to exclude yara rules when scanning and also to scan only using yara rules. Valid options are yes|no|only", "yes"},
diff --git a/lib/patches/clamav/shutdown_rarload_01035.patch b/lib/patches/clamav/shutdown_rarload_01035.patch
new file mode 100644
index 00000000..8f33fa10
--- /dev/null
+++ b/lib/patches/clamav/shutdown_rarload_01035.patch
@@ -0,0 +1,256 @@
+diff --git a/libclamav/clamav.h b/libclamav/clamav.h
+index 4e34d63..c947482 100644
+--- a/libclamav/clamav.h
++++ b/libclamav/clamav.h
+@@ -264,6 +264,7 @@ void cl_cleanup_crypto(void);
+ * @return cl_error_t CL_SUCCESS if everything initalized correctly.
+ */
+ extern cl_error_t cl_init(unsigned int initoptions);
++extern void cl_shutdown(void);
+
+ /**
+ * @brief Allocate a new scanning engine and initialize default settings.
+diff --git a/libclamav/mbox.c b/libclamav/mbox.c
+index 19feb67..414acf0 100644
+--- a/libclamav/mbox.c
++++ b/libclamav/mbox.c
+@@ -3090,6 +3090,30 @@ initialiseTables(table_t **rfc821Table, table_t **subtypeTable)
+ }
+
+ /*
++ * Cleanup the various lookup tables
++ */
++void
++cli_mbox_shutdown(void)
++{
++
++#ifdef CL_THREAD_SAFE
++ pthread_mutex_lock(&tables_mutex);
++#endif
++ if(rfc821) {
++ tableDestroy(rfc821);
++ rfc821 = NULL;
++ }
++ if(subtype) {
++ tableDestroy(subtype);
++ subtype = NULL;
++ }
++#ifdef CL_THREAD_SAFE
++ pthread_mutex_unlock(&tables_mutex);
++#endif
++
++}
++
++/*
+ * If there's a HTML text version use that, otherwise
+ * use the first text part, otherwise just use the
+ * first one around. HTML text is most likely to include
+diff --git a/libclamav/mbox.h b/libclamav/mbox.h
+index 63ee0c4..fb767f5 100644
+--- a/libclamav/mbox.h
++++ b/libclamav/mbox.h
+@@ -75,4 +75,6 @@ typedef enum {
+ size_t strstrip(char *s); /* remove trailing white space */
+ int cli_mbox(const char *dir, cli_ctx *ctx);
+
++void cli_mbox_shutdown(void);
++
+ #endif /* __MBOX_H */
+diff --git a/libclamav/message.c b/libclamav/message.c
+index 75c86ec..cc2fb7b 100644
+--- a/libclamav/message.c
++++ b/libclamav/message.c
+@@ -137,6 +137,32 @@ static const unsigned char base64Table[256] = {
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};
+
++static table_t *mime_table = NULL;
++
++#ifdef CL_THREAD_SAFE
++ static pthread_mutex_t mime_mutex = PTHREAD_MUTEX_INITIALIZER;
++#endif
++
++/*
++ * Cleanup the various lookup tables
++ */
++void
++cli_mime_shutdown(void)
++{
++
++#ifdef CL_THREAD_SAFE
++ pthread_mutex_lock(&mime_mutex);
++#endif
++ if(mime_table) {
++ tableDestroy(mime_table);
++ mime_table = NULL;
++ }
++#ifdef CL_THREAD_SAFE
++ pthread_mutex_unlock(&mime_mutex);
++#endif
++
++}
++
+ message *
+ messageCreate(void)
+ {
+@@ -211,12 +237,8 @@ void messageReset(message *m)
+ */
+ int messageSetMimeType(message *mess, const char *type)
+ {
+-#ifdef CL_THREAD_SAFE
+- static pthread_mutex_t mime_mutex = PTHREAD_MUTEX_INITIALIZER;
+-#endif
+ const struct mime_map *m;
+ int typeval;
+- static table_t *mime_table;
+
+ if (mess == NULL) {
+ cli_dbgmsg("messageSetMimeType: NULL message pointer\n");
+diff --git a/libclamav/message.h b/libclamav/message.h
+index 62f6b85..a0ec5cd 100644
+--- a/libclamav/message.h
++++ b/libclamav/message.h
+@@ -93,4 +93,6 @@ int messageSavePartial(message *m, const char *dir, const char *id, unsigned par
+ json_object *messageGetJObj(message *m);
+ #endif
+
++void cli_mime_shutdown(void);
++
+ #endif /*_MESSAGE_H*/
+diff --git a/libclamav/others.c b/libclamav/others.c
+index 7a0e92f..f021ffc 100644
+--- a/libclamav/others.c
++++ b/libclamav/others.c
+@@ -288,7 +288,9 @@ static void *get_module_function(void *handle, const char *name)
+ {
+ void *procAddress = NULL;
+ procAddress = dlsym(handle, name);
+- if (NULL == procAddress) {
++
++ // Ignore missing symbols when the handle is NULL. This only means the symbol wasn't statically linked or otherwise loaded already.
++ if (NULL == procAddress && handle != NULL) {
+ const char *err = dlerror();
+ if (NULL == err) {
+ cli_warnmsg("Failed to get function \"%s\": Unknown error.\n", name);
+@@ -296,6 +298,10 @@ static void *get_module_function(void *handle, const char *name)
+ cli_warnmsg("Failed to get function \"%s\": %s\n", name, err);
+ }
+ }
++ // If the symbol wasn't found, and the handle is NULL, this will call dlerror(), which will reset the error queue.
++ else if (NULL == procAddress && handle == NULL) {
++ dlerror();
++ }
+ return procAddress;
+ }
+ #endif // !_WIN32
+@@ -317,20 +323,25 @@ static void rarload(void)
+
+ if (have_rar) return;
+
+- rhandle = load_module("libclamunrar_iface", "unrar");
+- if (NULL == rhandle)
+- return;
+-
+- if ((NULL == (cli_unrar_open = (cl_unrar_error_t(*)(const char *, void **, char **, uint32_t *, uint8_t))get_module_function(rhandle, "libclamunrar_iface_LTX_unrar_open"))) ||
+- (NULL == (cli_unrar_peek_file_header = (cl_unrar_error_t(*)(void *, unrar_metadata_t *))get_module_function(rhandle, "libclamunrar_iface_LTX_unrar_peek_file_header"))) ||
+- (NULL == (cli_unrar_extract_file = (cl_unrar_error_t(*)(void *, const char *, char *))get_module_function(rhandle, "libclamunrar_iface_LTX_unrar_extract_file"))) ||
+- (NULL == (cli_unrar_skip_file = (cl_unrar_error_t(*)(void *))get_module_function(rhandle, "libclamunrar_iface_LTX_unrar_skip_file"))) ||
+- (NULL == (cli_unrar_close = (void (*)(void *))get_module_function(rhandle, "libclamunrar_iface_LTX_unrar_close")))) {
+-
+- cli_warnmsg("Failed to load function from UnRAR module\n");
+- cli_warnmsg("Version mismatch?\n");
+- cli_warnmsg("UnRAR support unavailable\n");
+- return;
++ if ((NULL == (cli_unrar_open = (cl_unrar_error_t(*)(const char *, void **, char **, uint32_t *, uint8_t))get_module_function(NULL, "libclamunrar_iface_LTX_unrar_open"))) ||
++ (NULL == (cli_unrar_peek_file_header = (cl_unrar_error_t(*)(void *, unrar_metadata_t *))get_module_function(NULL, "libclamunrar_iface_LTX_unrar_peek_file_header"))) ||
++ (NULL == (cli_unrar_extract_file = (cl_unrar_error_t(*)(void *, const char *, char *))get_module_function(NULL, "libclamunrar_iface_LTX_unrar_extract_file"))) ||
++ (NULL == (cli_unrar_skip_file = (cl_unrar_error_t(*)(void *))get_module_function(NULL, "libclamunrar_iface_LTX_unrar_skip_file"))) ||
++ (NULL == (cli_unrar_close = (void (*)(void *))get_module_function(NULL, "libclamunrar_iface_LTX_unrar_close")))) {
++
++ rhandle = load_module("libclamunrar_iface", "unrar");
++ if (NULL == rhandle) return;
++
++ if ((NULL == (cli_unrar_open = (cl_unrar_error_t(*)(const char *, void **, char **, uint32_t *, uint8_t))get_module_function(rhandle, "libclamunrar_iface_LTX_unrar_open"))) ||
++ (NULL == (cli_unrar_peek_file_header = (cl_unrar_error_t(*)(void *, unrar_metadata_t *))get_module_function(rhandle, "libclamunrar_iface_LTX_unrar_peek_file_header"))) ||
++ (NULL == (cli_unrar_extract_file = (cl_unrar_error_t(*)(void *, const char *, char *))get_module_function(rhandle, "libclamunrar_iface_LTX_unrar_extract_file"))) ||
++ (NULL == (cli_unrar_skip_file = (cl_unrar_error_t(*)(void *))get_module_function(rhandle, "libclamunrar_iface_LTX_unrar_skip_file"))) ||
++ (NULL == (cli_unrar_close = (void (*)(void *))get_module_function(rhandle, "libclamunrar_iface_LTX_unrar_close")))) {
++ cli_warnmsg("Failed to load function from UnRAR module\n");
++ cli_warnmsg("Version mismatch?\n");
++ cli_warnmsg("UnRAR support unavailable\n");
++ return;
++ }
+ }
+ have_rar = 1;
+ }
+@@ -460,6 +471,14 @@ cl_error_t cl_init(unsigned int initoptions)
+ return CL_SUCCESS;
+ }
+
++void cl_shutdown(void) {
++ cli_mbox_shutdown();
++ cli_mime_shutdown();
++ if (lt_dlinitialized() && lt_dlexit()) {
++ cli_errmsg("lt_dlexit: Library exit error, probably because of an invalid reference counter");
++ }
++}
++
+ struct cl_engine *cl_engine_new(void)
+ {
+ struct cl_engine *new;
+diff --git a/libltdl/ltdl.c b/libltdl/ltdl.c
+index 6013f2a..6dc57ea 100644
+--- a/libltdl/ltdl.c
++++ b/libltdl/ltdl.c
+@@ -91,7 +91,7 @@ static const char sys_dlsearch_path[] = LT_DLSEARCH_PATH;
+
+
+
+-
++
+ /* --- DYNAMIC MODULE LOADING --- */
+
+
+@@ -262,6 +262,12 @@ lt_dlinit (void)
+ }
+
+ int
++lt_dlinitialized (void)
++{
++ return initialized;
++}
++
++int
+ lt_dlexit (void)
+ {
+ /* shut down libltdl */
+diff --git a/libltdl/ltdl.h b/libltdl/ltdl.h
+index f811399..ee9b03a 100644
+--- a/libltdl/ltdl.h
++++ b/libltdl/ltdl.h
+@@ -43,7 +43,7 @@ LT_BEGIN_C_DECLS
+ /* LT_STRLEN can be used safely on NULL pointers. */
+ #define LT_STRLEN(s) (((s) && (s)[0]) ? strlen (s) : 0)
+
+-
++
+ /* --- DYNAMIC MODULE LOADING API --- */
+
+
+@@ -52,6 +52,7 @@ typedef struct lt__handle *lt_dlhandle; /* A loaded module. */
+ /* Initialisation and finalisation functions for libltdl. */
+ LT_SCOPE int lt_dlinit (void);
+ LT_SCOPE int lt_dlexit (void);
++LT_SCOPE int lt_dlinitialized (void);
+
+ /* Module search path manipulation. */
+ LT_SCOPE int lt_dladdsearchdir (const char *search_dir);
+@@ -110,7 +111,7 @@ extern LT_DLSYM_CONST lt_dlsymlist lt__PROGRAM__LTX_preloaded_symbols[];
+
+
+
+-
++
+ /* --- MODULE INFORMATION --- */
+
+
diff --git a/lib/patches/clamav/shutdown_rarload_01042.patch b/lib/patches/clamav/shutdown_rarload_01042.patch
index 373869ef..2ec7fdbf 100644
--- a/lib/patches/clamav/shutdown_rarload_01042.patch
+++ b/lib/patches/clamav/shutdown_rarload_01042.patch
@@ -1,15 +1,15 @@
diff --git a/libclamav/clamav.h b/libclamav/clamav.h
-index d4be07e..c49c484 100644
+index d4be07e..70e9c72 100644
--- a/libclamav/clamav.h
+++ b/libclamav/clamav.h
-@@ -261,6 +261,7 @@ void cl_cleanup_crypto(void);
- /**
- * @brief Initialize the ClamAV library.
- *
-+extern void cl_shutdown(void);
- * @param initoptions Unused.
+@@ -265,6 +265,7 @@ void cl_cleanup_crypto(void);
* @return cl_error_t CL_SUCCESS if everything initalized correctly.
*/
+ extern cl_error_t cl_init(unsigned int initoptions);
++extern void cl_shutdown(void);
+
+ /**
+ * @brief Allocate a new scanning engine and initialize default settings.
diff --git a/libclamav/mbox.c b/libclamav/mbox.c
index 1f1e1c3..ac97d18 100644
--- a/libclamav/mbox.c
@@ -118,23 +118,45 @@ index 62f6b85..a0ec5cd 100644
+
#endif /*_MESSAGE_H*/
diff --git a/libclamav/others.c b/libclamav/others.c
-index 4c31381..20a0fdf 100644
+index 4c31381..f3a9c3b 100644
--- a/libclamav/others.c
+++ b/libclamav/others.c
-@@ -302,20 +302,26 @@ static void rarload(void)
+@@ -268,7 +268,9 @@ static void *get_module_function(void *handle, const char *name)
+ {
+ void *procAddress = NULL;
+ procAddress = dlsym(handle, name);
+- if (NULL == procAddress) {
++
++ // Ignore missing symbols when the handle is NULL. This only means the symbol wasn't statically linked or otherwise loaded already.
++ if (NULL == procAddress && handle != NULL) {
+ const char *err = dlerror();
+ if (NULL == err) {
+ cli_warnmsg("Failed to get function \"%s\": Unknown error.\n", name);
+@@ -276,6 +278,10 @@ static void *get_module_function(void *handle, const char *name)
+ cli_warnmsg("Failed to get function \"%s\": %s\n", name, err);
+ }
+ }
++ // If the symbol wasn't found, and the handle is NULL, this will call dlerror(), which will reset the error queue.
++ else if (NULL == procAddress && handle == NULL) {
++ dlerror();
++ }
+ return procAddress;
+ }
+ #endif // !_WIN32
+@@ -302,20 +308,26 @@ static void rarload(void)
cli_unrar_skip_file = unrar_skip_file;
cli_unrar_close = unrar_close;
#else
- rhandle = load_module("libclamunrar_iface", "unrar");
- if (NULL == rhandle)
- return;
--
+
- if ((NULL == (cli_unrar_open = (cl_unrar_error_t(*)(const char *, void **, char **, uint32_t *, uint8_t))get_module_function(rhandle, "libclamunrar_iface_LTX_unrar_open"))) ||
- (NULL == (cli_unrar_peek_file_header = (cl_unrar_error_t(*)(void *, unrar_metadata_t *))get_module_function(rhandle, "libclamunrar_iface_LTX_unrar_peek_file_header"))) ||
- (NULL == (cli_unrar_extract_file = (cl_unrar_error_t(*)(void *, const char *, char *))get_module_function(rhandle, "libclamunrar_iface_LTX_unrar_extract_file"))) ||
- (NULL == (cli_unrar_skip_file = (cl_unrar_error_t(*)(void *))get_module_function(rhandle, "libclamunrar_iface_LTX_unrar_skip_file"))) ||
- (NULL == (cli_unrar_close = (void (*)(void *))get_module_function(rhandle, "libclamunrar_iface_LTX_unrar_close")))) {
-
+-
- cli_warnmsg("Failed to load function from UnRAR module\n");
- cli_warnmsg("Version mismatch?\n");
- cli_warnmsg("UnRAR support unavailable\n");
@@ -161,15 +183,19 @@ index 4c31381..20a0fdf 100644
}
#endif
-@@ -440,6 +446,14 @@ cl_error_t cl_init(unsigned int initoptions)
+@@ -440,6 +452,18 @@ cl_error_t cl_init(unsigned int initoptions)
return CL_SUCCESS;
}
+void cl_shutdown(void) {
+ cli_mbox_shutdown();
+ cli_mime_shutdown();
++ // Uncomment this fix once we patch libltdl to let us check the initialized counter. Until then use the ugly warning below as a reminder.
++ // if (lt_dlinitialized() && lt_dlexit()) {
++ // cli_errmsg("lt_dlexit: Library exit error, probably because of an invalid reference counter");
++ // }
+ if (lt_dlexit()) {
-+ cli_errmsg("lt_dlexit: Library exit error, probably because of an invalid reference counter");
++ cli_errmsg("lt_dlexit: Library exit error, probably because of an invalid reference counter [LIBLTDL NO LONGER BUNDLED / OTHERWISE WE'D USE 0.103.5 PATCH TO CHECK INITALIZED]");
+ }
+}
+
diff --git a/lib/patches/clamav/version_0984.patch b/lib/patches/clamav/version_0984.patch
index d11c11bf..d89c82fe 100644
--- a/lib/patches/clamav/version_0984.patch
+++ b/lib/patches/clamav/version_0984.patch
@@ -3,4 +3,3 @@ diff -r 946577531cae libclamav/version.h.static
+++ b/libclamav/version.h.static Fri Oct 10 05:45:20 2014 -0500
@@ -0,0 +1,1 @@
+#define REPO_VERSION VERSION
-
diff --git a/sandbox/etc/freshclam.conf b/sandbox/etc/freshclam.conf
index d49bfa98..7875bd41 100644
--- a/sandbox/etc/freshclam.conf
+++ b/sandbox/etc/freshclam.conf
@@ -3,7 +3,6 @@
# lib/sources/clamav/freshclam/.libs/freshclam --user $USER --datadir=res/virus --config-file=res/config/freshclam.conf
Bytecode yes
-SafeBrowsing yes
CompressLocalDatabase no
DatabaseMirror database.clamav.net
diff --git a/src/providers/symbols.c b/src/providers/symbols.c
index 46a32f7c..0e791e36 100644
--- a/src/providers/symbols.c
+++ b/src/providers/symbols.c
@@ -37,19 +37,19 @@ int (*BZ2_bzBuffToBuffCompress_d)(char *dest, unsigned int *destLen, char *sourc
int (*lt_dlexit_d)(void) = NULL;
void (*cl_shutdown_d)(void) = NULL;
const char * (*cl_retver_d)(void) = NULL;
-int (*cl_init_d)(unsigned int initoptions) = NULL;
+cl_error_t (*cl_init_d)(unsigned int initoptions) = NULL;
const char * (*cl_strerror_d)(int clerror) = NULL;
struct cl_engine * (*cl_engine_new_d)(void) = NULL;
-int (*cl_statfree_d)(struct cl_stat *dbstat) = NULL;
-int (*cl_engine_free_d)(struct cl_engine *engine) = NULL;
-int (*cl_engine_compile_d)(struct cl_engine *engine) = NULL;
+cl_error_t (*cl_statfree_d)(struct cl_stat *dbstat) = NULL;
+cl_error_t (*cl_engine_free_d)(struct cl_engine *engine) = NULL;
+cl_error_t (*cl_engine_compile_d)(struct cl_engine *engine) = NULL;
int (*cl_statchkdir_d)(const struct cl_stat *dbstat) = NULL;
-int (*cl_statinidir_d)(const char *dirname, struct cl_stat *dbstat) = NULL;
-int (*cl_countsigs_d)(const char *path, unsigned int countoptions, unsigned int *sigs) = NULL;
-int (*cl_engine_set_num_d)(struct cl_engine *engine, enum cl_engine_field field, long long num) = NULL;
-int (*cl_engine_set_str_d)(struct cl_engine *engine, enum cl_engine_field field, const char *str) = NULL;
-int (*cl_load_d)(const char *path, struct cl_engine *engine, unsigned int *signo, unsigned int dboptions) = NULL;
-int (*cl_scandesc_d)(int desc, const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options *scanoptions) = NULL;
+cl_error_t (*cl_statinidir_d)(const char *dirname, struct cl_stat *dbstat) = NULL;
+cl_error_t (*cl_countsigs_d)(const char *path, unsigned int countoptions, unsigned int *sigs) = NULL;
+cl_error_t (*cl_engine_set_num_d)(struct cl_engine *engine, enum cl_engine_field field, long long num) = NULL;
+cl_error_t (*cl_engine_set_str_d)(struct cl_engine *engine, enum cl_engine_field field, const char *str) = NULL;
+cl_error_t (*cl_load_d)(const char *path, struct cl_engine *engine, unsigned int *signo, unsigned int dboptions) = NULL;
+cl_error_t (*cl_scandesc_d)(int desc, const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options *scanoptions) = NULL;
//! DSPAM
const char * (*dspam_version_d)(void) = NULL;
diff --git a/src/providers/symbols.h b/src/providers/symbols.h
index e9265d43..812f782b 100644
--- a/src/providers/symbols.h
+++ b/src/providers/symbols.h
@@ -139,19 +139,19 @@ extern int (*BZ2_bzBuffToBuffCompress_d)(char *dest, unsigned int *destLen, char
extern int (*lt_dlexit_d)(void);
extern void (*cl_shutdown_d)(void);
extern const char * (*cl_retver_d)(void);
-extern int (*cl_init_d)(unsigned int initoptions);
+extern cl_error_t (*cl_init_d)(unsigned int initoptions);
extern const char * (*cl_strerror_d)(int clerror);
extern struct cl_engine * (*cl_engine_new_d)(void);
-extern int (*cl_statfree_d)(struct cl_stat *dbstat);
-extern int (*cl_engine_free_d)(struct cl_engine *engine);
-extern int (*cl_engine_compile_d)(struct cl_engine *engine);
+extern cl_error_t (*cl_statfree_d)(struct cl_stat *dbstat);
+extern cl_error_t (*cl_engine_free_d)(struct cl_engine *engine);
+extern cl_error_t (*cl_engine_compile_d)(struct cl_engine *engine);
extern int (*cl_statchkdir_d)(const struct cl_stat *dbstat);
-extern int (*cl_statinidir_d)(const char *dirname, struct cl_stat *dbstat);
-extern int (*cl_countsigs_d)(const char *path, unsigned int countoptions, unsigned int *sigs);
-extern int (*cl_engine_set_num_d)(struct cl_engine *engine, enum cl_engine_field field, long long num);
-extern int (*cl_engine_set_str_d)(struct cl_engine *engine, enum cl_engine_field field, const char *str);
-extern int (*cl_load_d)(const char *path, struct cl_engine *engine, unsigned int *signo, unsigned int dboptions);
-extern int (*cl_scandesc_d)(int desc, const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options *scanoptions);
+extern cl_error_t (*cl_statinidir_d)(const char *dirname, struct cl_stat *dbstat);
+extern cl_error_t (*cl_countsigs_d)(const char *path, unsigned int countoptions, unsigned int *sigs);
+extern cl_error_t (*cl_engine_set_num_d)(struct cl_engine *engine, enum cl_engine_field field, long long num);
+extern cl_error_t (*cl_engine_set_str_d)(struct cl_engine *engine, enum cl_engine_field field, const char *str);
+extern cl_error_t (*cl_load_d)(const char *path, struct cl_engine *engine, unsigned int *signo, unsigned int dboptions);
+extern cl_error_t (*cl_scandesc_d)(int desc, const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options *scanoptions);
//! DSPAM
extern const char * (*dspam_version_d)(void);