2003-07-29 15:48:06 +00:00
|
|
|
/*
|
2009-02-13 10:55:45 +00:00
|
|
|
* Copyright (C) 2007-2009 Sourcefire, Inc.
|
|
|
|
*
|
|
|
|
* Authors: Tomasz Kojm
|
2003-07-29 15:48:06 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
2007-03-31 20:31:04 +00:00
|
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
|
|
* published by the Free Software Foundation.
|
2003-07-29 15:48:06 +00:00
|
|
|
*
|
|
|
|
* 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
|
2006-04-09 19:59:28 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
* MA 02110-1301, USA.
|
2003-07-29 15:48:06 +00:00
|
|
|
*/
|
|
|
|
|
2006-09-13 22:06:13 +00:00
|
|
|
#if HAVE_CONFIG_H
|
|
|
|
#include "clamav-config.h"
|
|
|
|
#endif
|
|
|
|
|
2003-07-29 15:48:06 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2004-02-20 15:49:29 +00:00
|
|
|
#include <string.h>
|
2006-09-12 20:55:09 +00:00
|
|
|
#ifdef HAVE_UNISTD_H
|
2003-07-29 15:48:06 +00:00
|
|
|
#include <unistd.h>
|
2009-09-30 00:54:04 +02:00
|
|
|
#endif
|
|
|
|
#ifndef _WIN32
|
2003-07-29 15:48:06 +00:00
|
|
|
#include <sys/time.h>
|
2006-09-12 20:55:09 +00:00
|
|
|
#endif
|
2003-07-29 15:48:06 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2003-11-23 22:42:20 +00:00
|
|
|
#include <fcntl.h>
|
2003-07-29 15:48:06 +00:00
|
|
|
#include <time.h>
|
2009-09-24 16:21:51 +02:00
|
|
|
#ifdef HAVE_PWD_H
|
2003-07-29 15:48:06 +00:00
|
|
|
#include <pwd.h>
|
2009-09-24 16:21:51 +02:00
|
|
|
#endif
|
|
|
|
#ifdef HAVE_GRP_H
|
2003-07-29 15:48:06 +00:00
|
|
|
#include <grp.h>
|
2006-09-12 20:55:09 +00:00
|
|
|
#endif
|
2009-08-06 22:29:13 +02:00
|
|
|
#include <signal.h>
|
2003-07-29 15:48:06 +00:00
|
|
|
|
2004-03-29 00:00:58 +00:00
|
|
|
#if defined(USE_SYSLOG) && !defined(C_AIX)
|
2003-07-29 15:48:06 +00:00
|
|
|
#include <syslog.h>
|
|
|
|
#endif
|
|
|
|
|
2004-02-27 09:45:46 +00:00
|
|
|
#ifdef C_LINUX
|
|
|
|
#include <sys/resource.h>
|
|
|
|
#endif
|
|
|
|
|
2006-09-05 20:45:39 +00:00
|
|
|
#include "target.h"
|
|
|
|
|
|
|
|
#include "libclamav/clamav.h"
|
|
|
|
#include "libclamav/others.h"
|
2007-11-08 15:17:08 +00:00
|
|
|
#include "libclamav/matcher-ac.h"
|
2008-08-01 15:39:00 +00:00
|
|
|
#include "libclamav/readdb.h"
|
2006-09-05 20:45:39 +00:00
|
|
|
|
|
|
|
#include "shared/output.h"
|
2008-12-17 21:42:54 +00:00
|
|
|
#include "shared/optparser.h"
|
2006-09-05 20:45:39 +00:00
|
|
|
#include "shared/misc.h"
|
|
|
|
|
|
|
|
#include "server.h"
|
2003-07-29 15:48:06 +00:00
|
|
|
#include "tcpserver.h"
|
|
|
|
#include "localserver.h"
|
|
|
|
#include "others.h"
|
2004-03-29 00:00:58 +00:00
|
|
|
#include "shared.h"
|
2004-02-06 13:46:08 +00:00
|
|
|
|
2004-03-30 21:11:25 +00:00
|
|
|
short debug_mode = 0, logok = 0;
|
2005-06-07 01:40:08 +00:00
|
|
|
short foreground = 0;
|
|
|
|
|
2007-02-11 00:41:13 +00:00
|
|
|
static void help(void)
|
2006-09-05 20:45:39 +00:00
|
|
|
{
|
|
|
|
printf("\n");
|
2008-08-04 10:38:24 +00:00
|
|
|
printf(" Clam AntiVirus Daemon %s\n", get_version());
|
2009-02-24 16:12:56 +00:00
|
|
|
printf(" By The ClamAV Team: http://www.clamav.net/team\n");
|
|
|
|
printf(" (C) 2007-2009 Sourcefire, Inc.\n\n");
|
2006-09-05 20:45:39 +00:00
|
|
|
|
|
|
|
printf(" --help -h Show this help.\n");
|
|
|
|
printf(" --version -V Show version number.\n");
|
|
|
|
printf(" --debug Enable debug mode.\n");
|
|
|
|
printf(" --config-file=FILE -c FILE Read configuration from FILE.\n\n");
|
|
|
|
}
|
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
static struct optstruct *opts;
|
Must free engine on exit, otherwise valgrind incorrectly reports leaks.
This is a cherry-pick of a similar commit on the bytecode branch.
There this was needed because the JIT stores pointers mangled (stores an integer in low
bits of the pointer), thus valgrind can't see that pointers to that memory
region still exist, and reports it as definetely lost, instead of still
reachable.
However this seems to happen on master too (where there is no JIT), valgrind
cannot see that everything allocating in engine is reachable from the engine
pointer, and reports some of the memory allocated for the engine (the regex
parts) as possible lost, and reports the rest as still reachable. This seems to
only happen with certain kernel versions, timings, etc.
The fix is to always free the engine, even if this is the parent after the fork.
2009-10-02 13:21:33 +03:00
|
|
|
|
|
|
|
/* When running under valgrind and daemonizing, valgrind incorrectly reports
|
|
|
|
* leaks from the engine, because it can't see that all the memory is still
|
|
|
|
* reachable (some pointers are stored mangled in the JIT).
|
|
|
|
* So free the engine on exit from the parent too (during daemonize)
|
|
|
|
*/
|
|
|
|
static struct cl_engine *gengine = NULL;
|
|
|
|
static void free_engine(void)
|
|
|
|
{
|
|
|
|
if (gengine) {
|
|
|
|
cl_engine_free(gengine);
|
|
|
|
gengine = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-15 18:30:18 +00:00
|
|
|
int main(int argc, char **argv)
|
2003-07-29 15:48:06 +00:00
|
|
|
{
|
Must free engine on exit, otherwise valgrind incorrectly reports leaks.
This is a cherry-pick of a similar commit on the bytecode branch.
There this was needed because the JIT stores pointers mangled (stores an integer in low
bits of the pointer), thus valgrind can't see that pointers to that memory
region still exist, and reports it as definetely lost, instead of still
reachable.
However this seems to happen on master too (where there is no JIT), valgrind
cannot see that everything allocating in engine is reachable from the engine
pointer, and reports some of the memory allocated for the engine (the regex
parts) as possible lost, and reports the rest as still reachable. This seems to
only happen with certain kernel versions, timings, etc.
The fix is to always free the engine, even if this is the parent after the fork.
2009-10-02 13:21:33 +03:00
|
|
|
static struct cl_engine *engine = NULL;
|
2008-12-17 21:42:54 +00:00
|
|
|
const struct optstruct *opt;
|
2008-05-30 10:27:24 +00:00
|
|
|
#ifndef C_WINDOWS
|
2007-03-19 20:36:17 +00:00
|
|
|
struct passwd *user = NULL;
|
2009-08-05 18:34:21 +02:00
|
|
|
struct sigaction sa;
|
2008-05-30 10:27:24 +00:00
|
|
|
#endif
|
2003-07-29 15:48:06 +00:00
|
|
|
time_t currtime;
|
|
|
|
const char *dbdir, *cfgfile;
|
2008-12-17 21:42:54 +00:00
|
|
|
char *pua_cats = NULL, *pt;
|
2009-02-12 16:51:09 +00:00
|
|
|
int ret, tcpsock = 0, localsock = 0, i, min_port, max_port;
|
2006-09-05 20:45:39 +00:00
|
|
|
unsigned int sigs = 0;
|
2005-06-22 15:54:28 +00:00
|
|
|
int lsockets[2], nlsockets = 0;
|
2009-07-28 20:36:38 +02:00
|
|
|
unsigned int dboptions = CL_DB_CVDNOTMP;
|
2004-05-11 00:14:14 +00:00
|
|
|
#ifdef C_LINUX
|
|
|
|
struct stat sb;
|
|
|
|
#endif
|
2006-05-15 18:30:18 +00:00
|
|
|
|
2009-09-24 16:08:52 +02:00
|
|
|
#ifndef _WIN32
|
2009-08-05 18:34:21 +02:00
|
|
|
memset(&sa, 0, sizeof(sa));
|
|
|
|
sa.sa_handler = SIG_IGN;
|
|
|
|
sigaction(SIGHUP, &sa, NULL);
|
|
|
|
sigaction(SIGUSR2, &sa, NULL);
|
2006-09-12 20:55:09 +00:00
|
|
|
#endif
|
2006-05-15 18:30:18 +00:00
|
|
|
|
2008-12-30 21:16:02 +00:00
|
|
|
if((opts = optparse(NULL, argc, argv, 1, OPT_CLAMD, 0, NULL)) == NULL) {
|
2008-12-17 21:42:54 +00:00
|
|
|
mprintf("!Can't parse command line options\n");
|
2006-05-15 18:30:18 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2003-07-29 15:48:06 +00:00
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
if(optget(opts, "help")->enabled) {
|
2003-07-29 15:48:06 +00:00
|
|
|
help();
|
2008-12-17 21:42:54 +00:00
|
|
|
optfree(opts);
|
2006-09-05 20:45:39 +00:00
|
|
|
return 0;
|
2003-07-29 15:48:06 +00:00
|
|
|
}
|
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
if(optget(opts, "debug")->enabled) {
|
2004-02-27 09:45:46 +00:00
|
|
|
#if defined(C_LINUX)
|
|
|
|
/* njh@bandsman.co.uk: create a dump if needed */
|
|
|
|
struct rlimit rlim;
|
|
|
|
|
|
|
|
rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
|
|
|
|
if(setrlimit(RLIMIT_CORE, &rlim) < 0)
|
|
|
|
perror("setrlimit");
|
|
|
|
#endif
|
2004-02-17 00:08:25 +00:00
|
|
|
debug_mode = 1;
|
2004-02-27 09:45:46 +00:00
|
|
|
}
|
2004-02-17 00:08:25 +00:00
|
|
|
|
2003-07-29 15:48:06 +00:00
|
|
|
/* parse the config file */
|
2008-12-17 21:42:54 +00:00
|
|
|
cfgfile = optget(opts, "config-file")->strarg;
|
|
|
|
pt = strdup(cfgfile);
|
2008-12-30 21:16:02 +00:00
|
|
|
if((opts = optparse(cfgfile, 0, NULL, 1, OPT_CLAMD, 0, opts)) == NULL) {
|
2008-12-17 21:42:54 +00:00
|
|
|
fprintf(stderr, "ERROR: Can't open/parse the config file %s\n", pt);
|
|
|
|
free(pt);
|
2006-09-05 20:45:39 +00:00
|
|
|
return 1;
|
2003-07-29 15:48:06 +00:00
|
|
|
}
|
2008-12-17 21:42:54 +00:00
|
|
|
free(pt);
|
2008-01-22 10:42:30 +00:00
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
if(optget(opts, "version")->enabled) {
|
|
|
|
print_version(optget(opts, "DatabaseDirectory")->strarg);
|
|
|
|
optfree(opts);
|
2008-01-22 10:42:30 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-10-02 17:45:47 +00:00
|
|
|
umask(0);
|
|
|
|
|
2005-06-07 01:40:08 +00:00
|
|
|
/* drop privileges */
|
2009-09-24 19:10:27 +02:00
|
|
|
#ifndef _WIN32
|
2008-12-17 21:42:54 +00:00
|
|
|
if(geteuid() == 0 && (opt = optget(opts, "User"))->enabled) {
|
|
|
|
if((user = getpwnam(opt->strarg)) == NULL) {
|
|
|
|
fprintf(stderr, "ERROR: Can't get information about user %s.\n", opt->strarg);
|
|
|
|
optfree(opts);
|
2006-09-05 20:45:39 +00:00
|
|
|
return 1;
|
2005-06-07 01:40:08 +00:00
|
|
|
}
|
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
if(optget(opts, "AllowSupplementaryGroups")->enabled) {
|
2005-06-07 01:40:08 +00:00
|
|
|
#ifdef HAVE_INITGROUPS
|
2008-12-17 21:42:54 +00:00
|
|
|
if(initgroups(opt->strarg, user->pw_gid)) {
|
2005-06-07 01:40:08 +00:00
|
|
|
fprintf(stderr, "ERROR: initgroups() failed.\n");
|
2008-12-17 21:42:54 +00:00
|
|
|
optfree(opts);
|
2006-09-05 20:45:39 +00:00
|
|
|
return 1;
|
2005-06-07 01:40:08 +00:00
|
|
|
}
|
|
|
|
#else
|
2008-08-20 09:03:52 +00:00
|
|
|
mprintf("!AllowSupplementaryGroups: initgroups() is not available, please disable AllowSupplementaryGroups in %s\n", cfgfile);
|
2008-12-17 21:42:54 +00:00
|
|
|
optfree(opts);
|
2008-08-20 09:03:52 +00:00
|
|
|
return 1;
|
2005-06-07 01:40:08 +00:00
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
#ifdef HAVE_SETGROUPS
|
|
|
|
if(setgroups(1, &user->pw_gid)) {
|
|
|
|
fprintf(stderr, "ERROR: setgroups() failed.\n");
|
2008-12-17 21:42:54 +00:00
|
|
|
optfree(opts);
|
2006-09-05 20:45:39 +00:00
|
|
|
return 1;
|
2005-06-07 01:40:08 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if(setgid(user->pw_gid)) {
|
|
|
|
fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid);
|
2008-12-17 21:42:54 +00:00
|
|
|
optfree(opts);
|
2006-09-05 20:45:39 +00:00
|
|
|
return 1;
|
2005-06-07 01:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(setuid(user->pw_uid)) {
|
|
|
|
fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid);
|
2008-12-17 21:42:54 +00:00
|
|
|
optfree(opts);
|
2006-09-05 20:45:39 +00:00
|
|
|
return 1;
|
2005-06-07 01:40:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-07-29 15:48:06 +00:00
|
|
|
/* initialize logger */
|
2008-12-17 21:42:54 +00:00
|
|
|
logg_lock = !optget(opts, "LogFileUnlock")->enabled;
|
|
|
|
logg_time = optget(opts, "LogTime")->enabled;
|
|
|
|
logok = optget(opts, "LogClean")->enabled;
|
|
|
|
logg_size = optget(opts, "LogFileMaxSize")->numarg;
|
|
|
|
logg_verbose = mprintf_verbose = optget(opts, "LogVerbose")->enabled;
|
2009-02-17 15:59:26 +00:00
|
|
|
mprintf_send_timeout = optget(opts, "SendBufTimeout")->numarg;
|
2003-07-29 15:48:06 +00:00
|
|
|
|
2009-02-12 21:14:45 +00:00
|
|
|
do { /* logger initialized */
|
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
if((opt = optget(opts, "LogFile"))->enabled) {
|
2008-02-03 19:23:20 +00:00
|
|
|
char timestr[32];
|
2008-12-17 21:42:54 +00:00
|
|
|
logg_file = opt->strarg;
|
2009-09-24 19:07:39 +02:00
|
|
|
if(!cli_is_abspath(logg_file)) {
|
2003-07-29 15:48:06 +00:00
|
|
|
fprintf(stderr, "ERROR: LogFile requires full path.\n");
|
2009-02-12 21:14:45 +00:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2003-07-29 15:48:06 +00:00
|
|
|
}
|
|
|
|
time(&currtime);
|
2008-02-03 19:23:20 +00:00
|
|
|
if(logg("#+++ Started at %s", cli_ctime(&currtime, timestr, sizeof(timestr)))) {
|
2008-11-25 20:07:11 +00:00
|
|
|
fprintf(stderr, "ERROR: Can't initialize the internal logger\n");
|
2009-02-12 21:14:45 +00:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2003-07-29 15:48:06 +00:00
|
|
|
}
|
|
|
|
} else
|
2004-03-29 00:00:58 +00:00
|
|
|
logg_file = NULL;
|
2003-07-29 15:48:06 +00:00
|
|
|
|
2008-11-12 16:19:43 +00:00
|
|
|
if((ret = cl_init(CL_INIT_DEFAULT))) {
|
|
|
|
logg("!Can't initialize libclamav: %s\n", cl_strerror(ret));
|
2009-02-12 21:14:45 +00:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2008-11-12 16:19:43 +00:00
|
|
|
}
|
|
|
|
|
2009-02-17 15:59:36 +00:00
|
|
|
if(optget(opts, "Debug")->enabled) /* enable debug messages in libclamav */ {
|
2008-11-12 16:19:43 +00:00
|
|
|
cl_debug();
|
2009-02-17 15:59:36 +00:00
|
|
|
logg_verbose = 2;
|
|
|
|
}
|
2008-11-12 16:19:43 +00:00
|
|
|
|
2004-03-29 00:00:58 +00:00
|
|
|
#if defined(USE_SYSLOG) && !defined(C_AIX)
|
2008-12-17 21:42:54 +00:00
|
|
|
if(optget(opts, "LogSyslog")->enabled) {
|
2004-05-11 00:14:14 +00:00
|
|
|
int fac = LOG_LOCAL6;
|
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
opt = optget(opts, "LogFacility");
|
|
|
|
if((fac = logg_facility(opt->strarg)) == -1) {
|
|
|
|
logg("!LogFacility: %s: No such facility.\n", opt->strarg);
|
2009-02-12 21:14:45 +00:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2004-05-11 00:14:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
openlog("clamd", LOG_PID, fac);
|
2004-03-29 00:00:58 +00:00
|
|
|
logg_syslog = 1;
|
2004-05-11 00:14:14 +00:00
|
|
|
}
|
2003-07-29 15:48:06 +00:00
|
|
|
#endif
|
|
|
|
|
2004-05-11 00:14:14 +00:00
|
|
|
#ifdef C_LINUX
|
2004-10-20 21:54:08 +00:00
|
|
|
procdev = 0;
|
|
|
|
if(stat("/proc", &sb) != -1 && !sb.st_size)
|
2004-05-11 00:14:14 +00:00
|
|
|
procdev = sb.st_dev;
|
|
|
|
#endif
|
2003-07-29 15:48:06 +00:00
|
|
|
|
|
|
|
/* check socket type */
|
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
if(optget(opts, "TCPSocket")->enabled)
|
2003-07-29 15:48:06 +00:00
|
|
|
tcpsock = 1;
|
2005-06-22 15:54:28 +00:00
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
if(optget(opts, "LocalSocket")->enabled)
|
2005-06-22 15:54:28 +00:00
|
|
|
localsock = 1;
|
|
|
|
|
|
|
|
if(!tcpsock && !localsock) {
|
2006-09-05 20:45:39 +00:00
|
|
|
logg("!Please define server type (local and/or TCP).\n");
|
2009-02-12 21:14:45 +00:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2003-07-29 15:48:06 +00:00
|
|
|
}
|
|
|
|
|
2008-08-04 10:38:24 +00:00
|
|
|
logg("#clamd daemon %s (OS: "TARGET_OS_TYPE", ARCH: "TARGET_ARCH_TYPE", CPU: "TARGET_CPU_TYPE")\n", get_version());
|
2007-02-22 19:08:59 +00:00
|
|
|
|
2009-09-24 16:08:52 +02:00
|
|
|
#ifndef _WIN32
|
2007-03-19 20:36:17 +00:00
|
|
|
if(user)
|
2008-02-15 17:37:53 +00:00
|
|
|
logg("#Running as user %s (UID %u, GID %u)\n", user->pw_name, user->pw_uid, user->pw_gid);
|
2008-05-30 10:27:24 +00:00
|
|
|
#endif
|
2007-03-19 20:36:17 +00:00
|
|
|
|
2007-02-22 19:08:59 +00:00
|
|
|
if(logg_size)
|
2008-02-15 17:37:53 +00:00
|
|
|
logg("#Log file size limited to %d bytes.\n", logg_size);
|
2007-02-22 19:08:59 +00:00
|
|
|
else
|
2008-02-15 17:37:53 +00:00
|
|
|
logg("#Log file size limit disabled.\n");
|
2007-02-22 19:08:59 +00:00
|
|
|
|
2009-02-12 16:51:09 +00:00
|
|
|
min_port = optget(opts, "StreamMinPort")->numarg;
|
|
|
|
max_port = optget(opts, "StreamMaxPort")->numarg;
|
|
|
|
if (min_port < 1024 || min_port > max_port || max_port > 65535) {
|
2009-02-16 21:27:22 +00:00
|
|
|
logg("!Invalid StreamMinPort/StreamMaxPort: %d, %d\n", min_port, max_port);
|
2009-02-12 21:14:45 +00:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2009-02-12 16:51:09 +00:00
|
|
|
}
|
|
|
|
|
2008-11-13 15:55:35 +00:00
|
|
|
if(!(engine = cl_engine_new())) {
|
2008-11-12 16:19:43 +00:00
|
|
|
logg("!Can't initialize antivirus engine\n");
|
2009-02-12 21:14:45 +00:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2008-11-12 16:19:43 +00:00
|
|
|
}
|
|
|
|
|
2004-02-01 01:18:57 +00:00
|
|
|
/* load the database(s) */
|
2008-12-17 21:42:54 +00:00
|
|
|
dbdir = optget(opts, "DatabaseDirectory")->strarg;
|
2008-02-15 17:37:53 +00:00
|
|
|
logg("#Reading databases from %s\n", dbdir);
|
2003-07-29 15:48:06 +00:00
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
if(optget(opts, "DetectPUA")->enabled) {
|
2007-08-13 18:10:35 +00:00
|
|
|
dboptions |= CL_DB_PUA;
|
2008-07-31 16:26:50 +00:00
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
if((opt = optget(opts, "ExcludePUA"))->enabled) {
|
2008-07-31 16:26:50 +00:00
|
|
|
dboptions |= CL_DB_PUA_EXCLUDE;
|
|
|
|
i = 0;
|
|
|
|
logg("#Excluded PUA categories:");
|
2008-12-17 21:42:54 +00:00
|
|
|
while(opt) {
|
|
|
|
if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
|
2008-07-31 16:26:50 +00:00
|
|
|
logg("!Can't allocate memory for pua_cats\n");
|
2008-11-12 16:19:43 +00:00
|
|
|
cl_engine_free(engine);
|
2009-02-12 21:14:45 +00:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2008-07-31 16:26:50 +00:00
|
|
|
}
|
2008-12-17 21:42:54 +00:00
|
|
|
logg("# %s", opt->strarg);
|
|
|
|
sprintf(pua_cats + i, ".%s", opt->strarg);
|
|
|
|
i += strlen(opt->strarg) + 1;
|
2008-07-31 16:26:50 +00:00
|
|
|
pua_cats[i] = 0;
|
2008-12-17 21:42:54 +00:00
|
|
|
opt = opt->nextarg;
|
2008-07-31 16:26:50 +00:00
|
|
|
}
|
2009-02-12 21:14:45 +00:00
|
|
|
if (ret)
|
|
|
|
break;
|
2008-07-31 16:26:50 +00:00
|
|
|
logg("#\n");
|
|
|
|
pua_cats[i] = '.';
|
|
|
|
pua_cats[i + 1] = 0;
|
|
|
|
}
|
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
if((opt = optget(opts, "IncludePUA"))->enabled) {
|
2008-07-31 16:26:50 +00:00
|
|
|
if(pua_cats) {
|
|
|
|
logg("!ExcludePUA and IncludePUA cannot be used at the same time\n");
|
|
|
|
free(pua_cats);
|
2009-02-12 21:14:45 +00:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2008-07-31 16:26:50 +00:00
|
|
|
}
|
|
|
|
dboptions |= CL_DB_PUA_INCLUDE;
|
|
|
|
i = 0;
|
|
|
|
logg("#Included PUA categories:");
|
2008-12-17 21:42:54 +00:00
|
|
|
while(opt) {
|
|
|
|
if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
|
2008-07-31 16:26:50 +00:00
|
|
|
logg("!Can't allocate memory for pua_cats\n");
|
2009-02-12 21:14:45 +00:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2008-07-31 16:26:50 +00:00
|
|
|
}
|
2008-12-17 21:42:54 +00:00
|
|
|
logg("# %s", opt->strarg);
|
|
|
|
sprintf(pua_cats + i, ".%s", opt->strarg);
|
|
|
|
i += strlen(opt->strarg) + 1;
|
2008-07-31 16:26:50 +00:00
|
|
|
pua_cats[i] = 0;
|
2008-12-17 21:42:54 +00:00
|
|
|
opt = opt->nextarg;
|
2008-07-31 16:26:50 +00:00
|
|
|
}
|
2009-02-12 21:14:45 +00:00
|
|
|
if (ret)
|
|
|
|
break;
|
2008-07-31 16:26:50 +00:00
|
|
|
logg("#\n");
|
|
|
|
pua_cats[i] = '.';
|
|
|
|
pua_cats[i + 1] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pua_cats) {
|
2009-03-12 15:21:36 +00:00
|
|
|
if((ret = cl_engine_set_str(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))) {
|
|
|
|
logg("!cli_engine_set_str(CL_ENGINE_PUA_CATEGORIES) failed: %s\n", cl_strerror(ret));
|
2008-07-31 16:26:50 +00:00
|
|
|
free(pua_cats);
|
2009-02-12 21:14:45 +00:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2008-07-31 16:26:50 +00:00
|
|
|
}
|
2008-11-12 16:19:43 +00:00
|
|
|
free(pua_cats);
|
2008-07-31 16:26:50 +00:00
|
|
|
}
|
|
|
|
} else {
|
2008-02-15 17:37:53 +00:00
|
|
|
logg("#Not loading PUA signatures.\n");
|
2008-07-31 16:26:50 +00:00
|
|
|
}
|
2007-08-13 18:10:35 +00:00
|
|
|
|
2008-11-14 22:23:39 +00:00
|
|
|
/* set the temporary dir */
|
2008-12-17 21:42:54 +00:00
|
|
|
if((opt = optget(opts, "TemporaryDirectory"))->enabled) {
|
2009-03-12 15:21:36 +00:00
|
|
|
if((ret = cl_engine_set_str(engine, CL_ENGINE_TMPDIR, opt->strarg))) {
|
|
|
|
logg("!cli_engine_set_str(CL_ENGINE_TMPDIR) failed: %s\n", cl_strerror(ret));
|
2009-02-12 21:14:45 +00:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2008-11-14 22:23:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-12 15:21:36 +00:00
|
|
|
if(optget(opts, "LeaveTemporaryFiles")->enabled)
|
|
|
|
cl_engine_set_num(engine, CL_ENGINE_KEEPTMP, 1);
|
2008-11-14 22:23:39 +00:00
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
if(optget(opts, "PhishingSignatures")->enabled)
|
2006-12-20 01:23:50 +00:00
|
|
|
dboptions |= CL_DB_PHISHING;
|
|
|
|
else
|
2008-02-15 17:37:53 +00:00
|
|
|
logg("#Not loading phishing signatures.\n");
|
2005-11-13 23:38:41 +00:00
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
if(optget(opts,"PhishingScanURLs")->enabled)
|
2007-01-12 17:29:09 +00:00
|
|
|
dboptions |= CL_DB_PHISHING_URLS;
|
|
|
|
else
|
2008-02-15 17:37:53 +00:00
|
|
|
logg("#Disabling URL based phishing detection.\n");
|
2007-01-12 17:29:09 +00:00
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
if(optget(opts,"DevACOnly")->enabled) {
|
2008-02-15 17:37:53 +00:00
|
|
|
logg("#Only using the A-C matcher.\n");
|
2009-03-12 15:21:36 +00:00
|
|
|
cl_engine_set_num(engine, CL_ENGINE_AC_ONLY, 1);
|
2007-11-08 15:17:08 +00:00
|
|
|
}
|
|
|
|
|
2008-12-17 21:42:54 +00:00
|
|
|
if((opt = optget(opts, "DevACDepth"))->enabled) {
|
2009-03-12 15:21:36 +00:00
|
|
|
cl_engine_set_num(engine, CL_ENGINE_AC_MAXDEPTH, opt->numarg);
|
2009-05-05 14:14:40 +00:00
|
|
|
logg("#Max A-C depth set to %u\n", (unsigned int) opt->numarg);
|
2007-11-08 15:17:08 +00:00
|
|
|
}
|
|
|
|
|
2008-11-12 16:19:43 +00:00
|
|
|
if((ret = cl_load(dbdir, engine, &sigs, dboptions))) {
|
2003-08-29 14:27:15 +00:00
|
|
|
logg("!%s\n", cl_strerror(ret));
|
2009-02-12 21:14:45 +00:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2003-07-29 15:48:06 +00:00
|
|
|
}
|
|
|
|
|
2008-02-15 17:37:53 +00:00
|
|
|
logg("#Loaded %u signatures.\n", sigs);
|
2008-11-12 16:19:43 +00:00
|
|
|
if((ret = cl_engine_compile(engine)) != 0) {
|
|
|
|
logg("!Database initialization error: %s\n", cl_strerror(ret));
|
2009-02-12 21:14:45 +00:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2003-12-02 22:48:56 +00:00
|
|
|
}
|
2003-07-29 15:48:06 +00:00
|
|
|
|
2006-09-05 20:45:39 +00:00
|
|
|
if(tcpsock) {
|
2009-02-12 21:14:45 +00:00
|
|
|
if ((lsockets[nlsockets] = tcpserver(opts)) == -1) {
|
|
|
|
ret = 1;
|
|
|
|
break;
|
2006-09-05 20:45:39 +00:00
|
|
|
}
|
|
|
|
nlsockets++;
|
|
|
|
}
|
2009-09-24 16:08:52 +02:00
|
|
|
#ifndef _WIN32
|
2006-09-05 20:45:39 +00:00
|
|
|
if(localsock) {
|
2009-02-12 21:14:45 +00:00
|
|
|
if ((lsockets[nlsockets] = localserver(opts)) == -1) {
|
|
|
|
ret = 1;
|
|
|
|
break;
|
2006-09-05 20:45:39 +00:00
|
|
|
}
|
|
|
|
nlsockets++;
|
|
|
|
}
|
2005-06-22 15:54:28 +00:00
|
|
|
|
2008-02-15 17:37:53 +00:00
|
|
|
/* fork into background */
|
2008-12-17 21:42:54 +00:00
|
|
|
if(!optget(opts, "Foreground")->enabled) {
|
2008-08-01 15:45:10 +00:00
|
|
|
#ifdef C_BSD
|
|
|
|
/* workaround for OpenBSD bug, see https://wwws.clamav.net/bugzilla/show_bug.cgi?id=885 */
|
|
|
|
for(ret=0;ret<nlsockets;ret++) {
|
|
|
|
fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) | O_NONBLOCK);
|
|
|
|
}
|
|
|
|
#endif
|
Must free engine on exit, otherwise valgrind incorrectly reports leaks.
This is a cherry-pick of a similar commit on the bytecode branch.
There this was needed because the JIT stores pointers mangled (stores an integer in low
bits of the pointer), thus valgrind can't see that pointers to that memory
region still exist, and reports it as definetely lost, instead of still
reachable.
However this seems to happen on master too (where there is no JIT), valgrind
cannot see that everything allocating in engine is reachable from the engine
pointer, and reports some of the memory allocated for the engine (the regex
parts) as possible lost, and reports the rest as still reachable. This seems to
only happen with certain kernel versions, timings, etc.
The fix is to always free the engine, even if this is the parent after the fork.
2009-10-02 13:21:33 +03:00
|
|
|
gengine = engine;
|
|
|
|
atexit(free_engine);
|
2008-02-15 17:37:53 +00:00
|
|
|
if(daemonize() == -1) {
|
|
|
|
logg("!daemonize() failed\n");
|
2009-02-12 21:14:45 +00:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2008-02-15 17:37:53 +00:00
|
|
|
}
|
Must free engine on exit, otherwise valgrind incorrectly reports leaks.
This is a cherry-pick of a similar commit on the bytecode branch.
There this was needed because the JIT stores pointers mangled (stores an integer in low
bits of the pointer), thus valgrind can't see that pointers to that memory
region still exist, and reports it as definetely lost, instead of still
reachable.
However this seems to happen on master too (where there is no JIT), valgrind
cannot see that everything allocating in engine is reachable from the engine
pointer, and reports some of the memory allocated for the engine (the regex
parts) as possible lost, and reports the rest as still reachable. This seems to
only happen with certain kernel versions, timings, etc.
The fix is to always free the engine, even if this is the parent after the fork.
2009-10-02 13:21:33 +03:00
|
|
|
gengine = NULL;
|
2008-08-01 15:45:10 +00:00
|
|
|
#ifdef C_BSD
|
|
|
|
for(ret=0;ret<nlsockets;ret++) {
|
|
|
|
fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) & ~O_NONBLOCK);
|
|
|
|
}
|
|
|
|
#endif
|
2008-02-15 17:37:53 +00:00
|
|
|
if(!debug_mode)
|
|
|
|
if(chdir("/") == -1)
|
|
|
|
logg("^Can't change current working directory to root\n");
|
|
|
|
|
|
|
|
} else
|
|
|
|
foreground = 1;
|
2009-09-24 16:08:52 +02:00
|
|
|
#endif
|
2008-02-15 17:37:53 +00:00
|
|
|
|
2009-02-12 16:51:09 +00:00
|
|
|
ret = recvloop_th(lsockets, nlsockets, engine, dboptions, opts);
|
2003-07-29 15:48:06 +00:00
|
|
|
|
2009-02-12 21:14:45 +00:00
|
|
|
} while (0);
|
|
|
|
|
|
|
|
logg("*Closing the main socket%s.\n", (nlsockets > 1) ? "s" : "");
|
|
|
|
|
|
|
|
for (i = 0; i < nlsockets; i++) {
|
2009-02-12 21:14:51 +00:00
|
|
|
closesocket(lsockets[i]);
|
2009-02-12 21:14:45 +00:00
|
|
|
}
|
|
|
|
|
2009-09-24 19:10:27 +02:00
|
|
|
#ifndef _WIN32
|
2009-02-12 21:14:51 +00:00
|
|
|
if(nlsockets && localsock) {
|
|
|
|
opt = optget(opts, "LocalSocket");
|
2009-02-12 21:14:45 +00:00
|
|
|
if(unlink(opt->strarg) == -1)
|
|
|
|
logg("!Can't unlink the socket file %s\n", opt->strarg);
|
|
|
|
else
|
2009-02-12 21:14:51 +00:00
|
|
|
logg("Socket file removed.\n");
|
2009-02-12 21:14:45 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-12-01 19:28:40 +00:00
|
|
|
logg_close();
|
2008-12-17 21:42:54 +00:00
|
|
|
optfree(opts);
|
2003-07-29 15:48:06 +00:00
|
|
|
|
2006-09-05 20:45:39 +00:00
|
|
|
return ret;
|
2003-07-29 15:48:06 +00:00
|
|
|
}
|