0d06ef19 |
/* |
e7f5f537 |
* Copyright (C) 2013-2021 Cisco Systems, Inc. and/or its affiliates. All rights reserved. |
265427ce |
* Copyright (C) 2009-2013 Sourcefire, Inc. |
52cddcbc |
* |
0d06ef19 |
* Author: Tomasz Kojm <tkojm@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include <stdio.h>
#include <string.h> |
b3acc382 |
#ifdef HAVE_UNISTD_H |
0d06ef19 |
#include <unistd.h> |
b3acc382 |
#endif |
5bdf0b2a |
#include <time.h> |
9b2f14fa |
#ifdef HAVE_UNAME_SYSCALL
#include <sys/utsname.h>
#endif
#include <zlib.h> |
4dccd075 |
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h> |
0d06ef19 |
|
d7979d4f |
#include "clamav-config.h" |
9b2f14fa |
#include "target.h" |
9e20cdf6 |
// libclamav
#include "clamav.h"
#include "str.h"
#include "others.h"
#include "readdb.h"
#include "bytecode.h"
#include "bytecode_detect.h" |
b02190b4 |
#include "fpu.h" |
1d8a56d4 |
|
9e20cdf6 |
// shared
#include "optparser.h"
#include "misc.h"
|
e46b546c |
#ifndef _WIN32
extern const struct clam_option *clam_options;
#else
__declspec(dllimport) extern const struct clam_option *clam_options;
#endif
|
0d06ef19 |
static struct _cfgfile {
const char *name;
int tool;
} cfgfile[] = { |
72fd33c8 |
{"clamd.conf", OPT_CLAMD},
{"freshclam.conf", OPT_FRESHCLAM},
{"clamav-milter.conf", OPT_MILTER},
{NULL, 0}}; |
0d06ef19 |
static void printopts(struct optstruct *opts, int nondef)
{ |
72fd33c8 |
const struct optstruct *opt;
while (opts) {
if (!opts->name) {
opts = opts->next;
continue;
}
if (clam_options[opts->idx].owner & OPT_DEPRECATED) {
if (opts->active)
printf("*** %s is DEPRECATED ***\n", opts->name);
opts = opts->next;
continue;
}
if (nondef && (opts->numarg == clam_options[opts->idx].numarg) && ((opts->strarg == clam_options[opts->idx].strarg) || (opts->strarg && clam_options[opts->idx].strarg && !strcmp(opts->strarg, clam_options[opts->idx].strarg)))) {
opts = opts->next;
continue;
}
if (!opts->enabled)
printf("%s disabled\n", opts->name);
else
switch (clam_options[opts->idx].argtype) {
case CLOPT_TYPE_STRING:
printf("%s = \"%s\"", opts->name, opts->strarg);
opt = opts;
while ((opt = opt->nextarg))
printf(", \"%s\"", opt->strarg);
printf("\n");
break;
case CLOPT_TYPE_NUMBER:
case CLOPT_TYPE_SIZE:
printf("%s = \"%lld\"", opts->name, opts->numarg);
opt = opts;
while ((opt = opt->nextarg))
printf(", \"%lld\"", opt->numarg);
printf("\n");
break;
case CLOPT_TYPE_BOOL:
printf("%s = \"yes\"\n", opts->name);
break;
default:
printf("!!! %s: UNKNOWN INTERNAL TYPE !!!\n", opts->name);
}
opts = opts->next; |
0d06ef19 |
}
}
|
1d8a56d4 |
static int printconf(const char *name)
{ |
72fd33c8 |
int i, j, tool = 0, tokens_count;
char buffer[1025];
const char *tokens[128];
const struct clam_option *cpt;
for (i = 0; cfgfile[i].name; i++) {
if (!strcmp(name, cfgfile[i].name)) {
tool = cfgfile[i].tool;
break;
} |
1d8a56d4 |
} |
72fd33c8 |
if (!tool) {
printf("ERROR: Unknown config file\nAvailable options:");
for (i = 0; cfgfile[i].name; i++)
printf(" %s", cfgfile[i].name);
printf("\n");
return 1; |
1d8a56d4 |
}
|
72fd33c8 |
printf("##\n## %s - automatically generated by clamconf " VERSION "\n##\n", name); |
1d8a56d4 |
printf("\n# Comment out or remove the line below.\nExample\n");
|
72fd33c8 |
for (i = 0; clam_options[i].owner; i++) {
cpt = &clam_options[i];
if (cpt->name && (cpt->owner & tool) && !(cpt->owner & OPT_DEPRECATED) && !(cpt->flags & 4)) {
strncpy(buffer, cpt->description, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = 0;
tokens_count = cli_strtokenize(buffer, '\n', 128, tokens);
printf("\n");
for (j = 0; j < tokens_count; j++)
printf("# %s\n", tokens[j]);
switch (cpt->argtype) {
case CLOPT_TYPE_STRING:
if (cpt->strarg)
printf("# Default: %s\n", cpt->strarg);
else
printf("# Default: disabled\n");
break;
case CLOPT_TYPE_NUMBER:
if (cpt->numarg != -1)
printf("# Default: %lld\n", cpt->numarg);
else
printf("# Default: disabled\n");
break;
case CLOPT_TYPE_SIZE:
printf("# You may use 'M' or 'm' for megabytes (1M = 1m = 1048576 bytes)\n# and 'K' or 'k' for kilobytes (1K = 1k = 1024 bytes). To specify the size\n# in bytes just don't use modifiers.\n");
if (cpt->numarg != -1)
printf("# Default: %lld\n", cpt->numarg);
else
printf("# Default: disabled\n");
break;
case CLOPT_TYPE_BOOL:
if (cpt->numarg != -1)
printf("# Default: %s\n", cpt->numarg ? "yes" : "no");
else
printf("# Default: disabled\n");
break;
default:
printf("!!! %s: UNKNOWN INTERNAL TYPE !!!\n", cpt->name);
}
if (cpt->suggested && strchr(cpt->suggested, '\n')) {
strncpy(buffer, cpt->suggested, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = 0;
tokens_count = cli_strtokenize(buffer, '\n', 128, tokens);
for (j = 0; j < tokens_count; j++)
printf("#%s %s\n", cpt->name, tokens[j]);
} else {
printf("#%s %s\n", cpt->name, cpt->suggested ? cpt->suggested : "ARG");
}
} |
1d8a56d4 |
}
return 0;
}
|
0d06ef19 |
static void help(void)
{
printf("\n"); |
e098cdc5 |
printf(" Clam AntiVirus: Configuration Tool %s\n", get_version()); |
964a1e73 |
printf(" By The ClamAV Team: https://www.clamav.net/about.html#credits\n"); |
e7f5f537 |
printf(" (C) 2021 Cisco Systems, Inc.\n"); |
e098cdc5 |
printf("\n");
printf(" --help -h Show this help\n"); |
1d8a56d4 |
printf(" --version -V Show version\n");
printf(" --config-dir=DIR -c DIR Read configuration files from DIR\n");
printf(" --non-default -n Only display non-default settings\n");
printf(" --generate-config=NAME -g NAME Generate example config file\n"); |
0d06ef19 |
printf("\n");
return;
}
|
ed6cd43e |
static void print_platform(struct cli_environment *env) |
9b2f14fa |
{ |
69184d40 |
printf("\nPlatform information\n--------------------\n"); |
ed6cd43e |
printf("uname: %s %s %s %s\n", |
72fd33c8 |
env->sysname, env->release, env->version, env->machine); |
ed6cd43e |
|
72fd33c8 |
printf("OS: " TARGET_OS_TYPE ", ARCH: " TARGET_ARCH_TYPE ", CPU: " TARGET_CPU_TYPE "\n"); |
9b2f14fa |
#ifdef C_LINUX
if (!access("/usr/bin/lsb_release", X_OK)) { |
72fd33c8 |
fputs("Full OS version: ", stdout);
fflush(stdout);
if (system("/usr/bin/lsb_release -d -s") == -1) {
perror("failed to determine");
} |
9b2f14fa |
}
#else
/* e.g. Solaris */
if (!access("/etc/release", R_OK)) { |
022677ab |
char buf[1024];
FILE *f = fopen("/etc/release", "r");
if (f) {
fgets(buf, sizeof(buf), f);
printf("Full OS version: %s", buf);
fclose(f);
} |
9b2f14fa |
}
#endif
|
e4fedabe |
if (strcmp(ZLIB_VERSION, zlibVersion())) |
72fd33c8 |
printf("WARNING: zlib version mismatch: %s (%s)\n", ZLIB_VERSION, zlibVersion()); |
9b2f14fa |
#ifdef ZLIB_VERNUM |
69184d40 |
printf("zlib version: %s (%s), compile flags: %02lx\n", |
72fd33c8 |
ZLIB_VERSION, zlibVersion(), zlibCompileFlags()); |
9b2f14fa |
#else
/* old zlib w/o zlibCompileFlags() */
printf("zlib version: %s (%s)\n", |
72fd33c8 |
ZLIB_VERSION, zlibVersion()); |
9b2f14fa |
#endif |
9cc0b8c9 |
|
ed6cd43e |
if (env->triple[0]) |
72fd33c8 |
printf("Triple: %s\n", env->triple); |
88d54dcb |
if (env->cpu[0]) |
72fd33c8 |
printf("CPU: %s, %s\n", env->cpu, env->big_endian ? "Big-endian" : "Little-endian"); |
ed6cd43e |
printf("platform id: 0x%08x%08x%08x\n", |
72fd33c8 |
env->platform_id_a,
env->platform_id_b,
env->platform_id_c); |
9b2f14fa |
}
|
ed6cd43e |
static void print_build(struct cli_environment *env) |
9b2f14fa |
{ |
ed6cd43e |
const char *name;
const char *version = NULL; |
9b2f14fa |
printf("\nBuild information\n-----------------\n");
/* Try to print information about some commonly used compilers */ |
69650bea |
#ifdef __GNUC__ |
72fd33c8 |
version = __VERSION__; |
69650bea |
#endif |
ed6cd43e |
switch (env->compiler) { |
72fd33c8 |
case compiler_gnuc:
name = "GNU C";
break;
case compiler_clang:
name = "Clang";
break;
case compiler_llvm:
name = "LLVM-GCC";
break;
case compiler_intel:
name = "Intel Compiler";
break;
case compiler_msc:
name = "Microsoft Visual C++";
break;
case compiler_sun:
name = "Sun studio";
break;
default:
name = NULL; |
ed6cd43e |
}
if (name) |
72fd33c8 |
printf("%s: %s%s(%u.%u.%u)\n", name,
version ? version : "",
version ? " " : "",
env->c_version >> 16,
(env->c_version >> 8) & 0xff,
(env->c_version) & 0xff); |
2a7f1cda |
cli_printcxxver(); |
331cce0a |
#if defined(BUILD_CPPFLAGS) && defined(BUILD_CFLAGS) && defined(BUILD_CXXFLAGS) && defined(BUILD_LDFLAGS) && defined(BUILD_CONFIGURE_FLAGS) |
9b2f14fa |
printf("CPPFLAGS: %s\nCFLAGS: %s\nCXXFLAGS: %s\nLDFLAGS: %s\nConfigure: %s\n", |
72fd33c8 |
BUILD_CPPFLAGS, BUILD_CFLAGS, BUILD_CXXFLAGS, BUILD_LDFLAGS,
BUILD_CONFIGURE_FLAGS); |
331cce0a |
#endif |
ed6cd43e |
printf("sizeof(void*) = %d\n", env->sizeof_ptr);
printf("Engine flevel: %d, dconf: %d\n", |
72fd33c8 |
env->functionality_level,
env->dconf_level); |
9b2f14fa |
}
|
4dccd075 |
static void print_dbs(const char *dir)
{ |
72fd33c8 |
DIR *dd;
struct dirent *dent;
char *dbfile;
unsigned int flevel = cl_retflevel(), cnt, sigs = 0;
struct cl_cvd *cvd; |
4dccd075 |
|
72fd33c8 |
if ((dd = opendir(dir)) == NULL) { |
4dccd075 |
printf("print_dbs: Can't open directory %s\n", dir);
return;
}
|
72fd33c8 |
while ((dent = readdir(dd))) {
if (dent->d_ino) {
if (CLI_DBEXT(dent->d_name)) {
dbfile = (char *)malloc(strlen(dent->d_name) + strlen(dir) + 2);
if (!dbfile) {
printf("print_dbs: Can't allocate memory for dbfile\n");
closedir(dd);
return;
}
sprintf(dbfile, "%s" PATHSEP "%s", dir, dent->d_name);
if (cli_strbcasestr(dbfile, ".cvd") || cli_strbcasestr(dbfile, ".cld")) {
cvd = cl_cvdhead(dbfile);
if (!cvd) {
printf("%s: Can't get information about the database\n", dbfile);
} else {
const time_t t = cvd->stime;
printf("%s: version %u, sigs: %u, built on %s", dent->d_name, cvd->version, cvd->sigs, ctime(&t));
sigs += cvd->sigs;
if (cvd->fl > flevel)
printf("%s: WARNING: This database requires f-level %u (current f-level: %u)\n", dent->d_name, cvd->fl, flevel);
cl_cvdfree(cvd);
}
} else if (cli_strbcasestr(dbfile, ".cbc")) {
printf("[3rd Party] %s: bytecode\n", dent->d_name);
sigs++;
} else {
cnt = countlines(dbfile);
printf("[3rd Party] %s: %u sig%c\n", dent->d_name, cnt, cnt > 1 ? 's' : ' ');
sigs += cnt;
}
free(dbfile);
}
} |
4dccd075 |
}
closedir(dd);
printf("Total number of signatures: %u\n", sigs);
}
|
0d06ef19 |
int main(int argc, char **argv)
{ |
72fd33c8 |
const char *dir;
char path[512], dbdir[512], clamd_dbdir[512], *pt;
struct optstruct *opts, *toolopts;
const struct optstruct *opt;
unsigned int i, j;
struct cli_environment env; |
0d06ef19 |
opts = optparse(NULL, argc, argv, 1, OPT_CLAMCONF, 0, NULL); |
72fd33c8 |
if (!opts) {
printf("ERROR: Can't parse command line options\n");
return 1; |
0d06ef19 |
}
|
72fd33c8 |
if (optget(opts, "help")->enabled) {
help();
optfree(opts);
return 0; |
0d06ef19 |
}
|
72fd33c8 |
if (optget(opts, "version")->enabled) {
printf("Clam AntiVirus Configuration Tool %s\n", get_version());
optfree(opts);
return 0; |
a128eb80 |
}
|
72fd33c8 |
if ((opt = optget(opts, "generate-config"))->enabled) {
printconf(opt->strarg);
optfree(opts);
return 0; |
1d8a56d4 |
}
|
72fd33c8 |
dbdir[0] = 0; |
53814f19 |
clamd_dbdir[0] = 0; |
72fd33c8 |
dir = optget(opts, "config-dir")->strarg; |
0d06ef19 |
printf("Checking configuration files in %s\n", dir); |
72fd33c8 |
for (i = 0; cfgfile[i].name; i++) {
snprintf(path, sizeof(path), "%s" PATHSEP "%s", dir, cfgfile[i].name);
path[511] = 0;
if (access(path, R_OK)) {
printf("\n%s not found\n", cfgfile[i].name);
continue;
}
printf("\nConfig file: %s\n", cfgfile[i].name);
for (j = 0; j < strlen(cfgfile[i].name) + 13; j++)
printf("-");
printf("\n");
toolopts = optparse(path, 0, NULL, 1, cfgfile[i].tool | OPT_DEPRECATED, 0, NULL);
if (!toolopts)
continue;
printopts(toolopts, optget(opts, "non-default")->enabled);
if (cfgfile[i].tool == OPT_FRESHCLAM) {
opt = optget(toolopts, "DatabaseDirectory");
strncpy(dbdir, opt->strarg, sizeof(dbdir));
dbdir[sizeof(dbdir) - 1] = 0;
} else if (cfgfile[i].tool == OPT_CLAMD) {
opt = optget(toolopts, "DatabaseDirectory");
strncpy(clamd_dbdir, opt->strarg, sizeof(clamd_dbdir));
clamd_dbdir[sizeof(clamd_dbdir) - 1] = 0;
}
optfree(toolopts); |
0d06ef19 |
}
optfree(opts); |
5bdf0b2a |
printf("\nSoftware settings\n-----------------\n");
printf("Version: %s\n", cl_retver()); |
72fd33c8 |
if (strcmp(cl_retver(), get_version()))
printf("WARNING: Version mismatch: libclamav=%s, clamconf=%s\n", cl_retver(), get_version()); |
5bdf0b2a |
cl_init(CL_INIT_DEFAULT);
printf("Optional features supported: ");
#ifdef USE_MPOOL |
72fd33c8 |
printf("MEMPOOL "); |
5bdf0b2a |
#endif
#ifdef SUPPORT_IPv6 |
72fd33c8 |
printf("IPv6 "); |
5bdf0b2a |
#endif
#ifdef CLAMUKO |
72fd33c8 |
printf("CLAMUKO "); |
5bdf0b2a |
#endif
#ifdef C_BIGSTACK |
72fd33c8 |
printf("BIGSTACK "); |
5bdf0b2a |
#endif
#ifdef FRESHCLAM_DNS_FIX |
72fd33c8 |
printf("FRESHCLAM_DNS_FIX "); |
5bdf0b2a |
#endif |
48bb121c |
#ifndef _WIN32 |
72fd33c8 |
if (get_fpu_endian() != FPU_ENDIAN_UNKNOWN) |
48bb121c |
#endif |
72fd33c8 |
printf("AUTOIT_EA06 "); |
5bdf0b2a |
#ifdef HAVE_BZLIB_H |
72fd33c8 |
printf("BZIP2 "); |
5bdf0b2a |
#endif |
c648e6b4 |
|
9cc0b8c9 |
#ifdef HAVE_LIBXML2 |
72fd33c8 |
printf("LIBXML2 "); |
9cc0b8c9 |
#endif |
17d741d8 |
#ifdef HAVE_PCRE |
41d46330 |
#if USING_PCRE2 |
72fd33c8 |
printf("PCRE2 "); |
41d46330 |
#else |
72fd33c8 |
printf("PCRE "); |
17d741d8 |
#endif |
41d46330 |
#endif |
ee064318 |
#ifdef HAVE_ICONV |
72fd33c8 |
printf("ICONV "); |
ee064318 |
#endif |
9cc0b8c9 |
#ifdef HAVE_JSON |
72fd33c8 |
printf("JSON "); |
9cc0b8c9 |
#endif |
72fd33c8 |
if (have_rar)
printf("RAR "); |
2487a4a3 |
if (have_clamjit) |
72fd33c8 |
printf("JIT"); |
5bdf0b2a |
printf("\n");
|
72fd33c8 |
if (!strlen(dbdir)) {
pt = freshdbdir();
if (pt) {
strncpy(dbdir, pt, sizeof(dbdir));
free(pt);
} else {
strncpy(dbdir, DATADIR, sizeof(dbdir));
}
dbdir[sizeof(dbdir) - 1] = 0; |
5bdf0b2a |
} |
4dccd075 |
printf("\nDatabase information\n--------------------\n"); |
5bdf0b2a |
printf("Database directory: %s\n", dbdir); |
72fd33c8 |
if (strcmp(dbdir, clamd_dbdir))
printf("WARNING: freshclam.conf and clamd.conf point to different database directories\n"); |
4dccd075 |
print_dbs(dbdir);
|
ed6cd43e |
cli_detect_environment(&env);
print_platform(&env);
print_build(&env); |
cef54eaf |
|
0d06ef19 |
return 0;
} |