2018-12-03 13:17:07 -05:00
|
|
|
/*
|
2019-02-28 13:13:14 -05:00
|
|
|
* Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
|
|
|
|
* Copyright (C) 2007-2013 Sourcefire, Inc.
|
2018-12-03 13:17:07 -05:00
|
|
|
*
|
|
|
|
* Authors: Tomasz Kojm, aCaB, Mickey Sola
|
|
|
|
*
|
|
|
|
* 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>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
#ifndef _WIN32
|
|
|
|
#include <sys/time.h>
|
|
|
|
#endif
|
|
|
|
#include <time.h>
|
|
|
|
#include <signal.h>
|
|
|
|
|
|
|
|
#include "libclamav/clamav.h"
|
2019-02-28 13:13:14 -05:00
|
|
|
#include "libclamav/others.h"
|
2018-12-03 13:17:07 -05:00
|
|
|
#include "shared/output.h"
|
|
|
|
#include "shared/misc.h"
|
|
|
|
#include "shared/optparser.h"
|
|
|
|
#include "shared/actions.h"
|
|
|
|
|
2019-02-28 13:13:14 -05:00
|
|
|
|
|
|
|
#include "clamonacc.h"
|
2019-02-20 18:31:11 -05:00
|
|
|
#include "./client/onaccess_client.h"
|
2019-02-28 13:13:14 -05:00
|
|
|
#include "./fanotif/onaccess_fan.h"
|
|
|
|
#include "./inotif/onaccess_ddd.h"
|
2018-12-03 13:17:07 -05:00
|
|
|
|
|
|
|
|
2019-02-28 13:13:14 -05:00
|
|
|
pthread_t ddd_pid = 0;
|
2018-12-03 13:17:07 -05:00
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
2019-02-28 13:13:14 -05:00
|
|
|
const struct optstruct *opts;
|
2019-04-04 10:43:19 -04:00
|
|
|
const struct optstruct *clamdopts;
|
2019-02-28 13:13:14 -05:00
|
|
|
struct onas_context *ctx;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
/* Initialize context */
|
|
|
|
ctx = onas_init_context();
|
|
|
|
if(ctx == NULL) {
|
2019-03-22 15:29:59 -04:00
|
|
|
logg("!Clamonacc: can't initialize context\n");
|
2019-02-28 13:13:14 -05:00
|
|
|
return 2;
|
|
|
|
}
|
2018-12-03 13:17:07 -05:00
|
|
|
|
2019-02-28 13:13:14 -05:00
|
|
|
/* Parse out all our command line options */
|
2019-04-02 13:47:48 -04:00
|
|
|
opts = optparse(NULL, argc, argv, 1, OPT_CLAMONACC, OPT_CLAMSCAN, NULL);
|
2019-02-28 13:13:14 -05:00
|
|
|
if(opts == NULL) {
|
2019-03-22 15:29:59 -04:00
|
|
|
logg("!Clamonacc: can't parse command line options\n");
|
2019-02-28 13:13:14 -05:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
ctx->opts = opts;
|
2018-12-03 13:17:07 -05:00
|
|
|
|
2019-02-28 13:13:14 -05:00
|
|
|
clamdopts = optparse(optget(opts, "config-file")->strarg, 0, NULL, 1, OPT_CLAMD, 0, NULL);
|
|
|
|
if (clamdopts == NULL) {
|
|
|
|
logg("!Clamonacc: can't parse clamd configuration file %s\n", optget(opts, "config-file")->strarg);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
ctx->clamdopts = clamdopts;
|
|
|
|
|
|
|
|
/* Setup our client */
|
|
|
|
switch(onas_setup_client(&ctx)) {
|
|
|
|
case CL_SUCCESS:
|
2019-03-26 11:34:54 -04:00
|
|
|
if (CL_SUCCESS == onas_check_client_connection(&ctx)) {
|
2019-02-28 13:13:14 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CL_BREAK:
|
|
|
|
ret = 0;
|
2019-04-02 13:47:48 -04:00
|
|
|
logg("*Clamonacc: not setting up client\n");
|
2019-02-28 13:13:14 -05:00
|
|
|
goto clean_up;
|
|
|
|
break;
|
|
|
|
case CL_EARG:
|
|
|
|
default:
|
2019-03-22 15:29:59 -04:00
|
|
|
logg("!Clamonacc: can't setup client\n");
|
2019-02-28 13:13:14 -05:00
|
|
|
ret = 2;
|
|
|
|
goto clean_up;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#if defined(FANOTIFY)
|
|
|
|
/* Setup fanotify */
|
|
|
|
switch(onas_setup_fanotif(&ctx)) {
|
|
|
|
case CL_SUCCESS:
|
|
|
|
break;
|
|
|
|
case CL_BREAK:
|
|
|
|
ret = 0;
|
|
|
|
goto clean_up;
|
|
|
|
break;
|
|
|
|
case CL_EARG:
|
|
|
|
default:
|
|
|
|
mprintf("!Clamonacc: can't setup fanotify\n");
|
|
|
|
ret = 2;
|
|
|
|
goto clean_up;
|
|
|
|
break;
|
|
|
|
}
|
2018-12-03 13:17:07 -05:00
|
|
|
|
2019-02-28 13:13:14 -05:00
|
|
|
if (ctx->ddd_enabled) {
|
|
|
|
/* Setup inotify and kickoff DDD system */
|
|
|
|
switch(onas_enable_inotif_ddd(&ctx)) {
|
|
|
|
case CL_SUCCESS:
|
|
|
|
break;
|
|
|
|
case CL_BREAK:
|
|
|
|
ret = 0;
|
|
|
|
goto clean_up;
|
|
|
|
break;
|
|
|
|
case CL_EARG:
|
|
|
|
default:
|
|
|
|
mprintf("!Clamonacc: can't setup fanotify\n");
|
|
|
|
ret = 2;
|
|
|
|
goto clean_up;
|
|
|
|
break;
|
|
|
|
}
|
2018-12-03 13:17:07 -05:00
|
|
|
}
|
2019-02-28 13:13:14 -05:00
|
|
|
#else
|
|
|
|
mprintf("!Clamonacc: currently, this application only runs on linux systems with fanotify enabled\n");
|
|
|
|
goto clean_up;
|
|
|
|
#endif
|
2018-12-03 13:17:07 -05:00
|
|
|
|
2019-03-28 11:55:23 -04:00
|
|
|
logg("*Clamonacc: beginning event loops\n");
|
2019-02-28 13:13:14 -05:00
|
|
|
/* Kick off event loop(s) */
|
|
|
|
ret = onas_start_eloop(&ctx);
|
2018-12-03 13:17:07 -05:00
|
|
|
|
2019-02-28 13:13:14 -05:00
|
|
|
/* Clean up */
|
|
|
|
clean_up:
|
|
|
|
onas_cleanup(ctx);
|
2018-12-03 13:17:07 -05:00
|
|
|
exit(ret);
|
2019-02-28 13:13:14 -05:00
|
|
|
}
|
2018-12-03 13:17:07 -05:00
|
|
|
|
2019-02-28 13:13:14 -05:00
|
|
|
struct onas_context *onas_init_context(void) {
|
|
|
|
struct onas_context *ctx = (struct onas_context*) cli_malloc(sizeof(struct onas_context));
|
|
|
|
if (NULL == ctx) {
|
|
|
|
return NULL;
|
2018-12-03 13:17:07 -05:00
|
|
|
}
|
|
|
|
|
2019-02-28 13:13:14 -05:00
|
|
|
memset(ctx, 0, sizeof(struct onas_context));
|
|
|
|
return ctx;
|
|
|
|
}
|
2018-12-03 13:17:07 -05:00
|
|
|
|
2019-03-26 11:34:54 -04:00
|
|
|
cl_error_t onas_check_client_connection(struct onas_context **ctx) {
|
2018-12-03 13:17:07 -05:00
|
|
|
|
2019-03-26 11:34:54 -04:00
|
|
|
errno = 0;
|
|
|
|
|
|
|
|
/* 0 local, non-zero remote, errno set on error */
|
|
|
|
(*ctx)->isremote = onas_check_remote(ctx);
|
|
|
|
if (errno == 0) {
|
|
|
|
logg("*Clamonacc: ");
|
|
|
|
(*ctx)->isremote ? logg("*daemon is remote\n") : logg("*daemon is local\n");
|
|
|
|
}
|
|
|
|
return errno ? CL_EACCES : CL_SUCCESS;
|
2019-02-28 13:13:14 -05:00
|
|
|
}
|
2018-12-03 13:17:07 -05:00
|
|
|
|
2019-02-28 13:13:14 -05:00
|
|
|
int onas_start_eloop(struct onas_context **ctx) {
|
|
|
|
int ret = 0;
|
2018-12-03 13:17:07 -05:00
|
|
|
|
2019-02-28 13:13:14 -05:00
|
|
|
if (!ctx || !*ctx) {
|
|
|
|
mprintf("!Clamonacc: unable to start clamonacc. (bad context)\n");
|
|
|
|
return CL_EARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef C_LINUX
|
|
|
|
ret = onas_fan_eloop(ctx);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
2018-12-03 13:17:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void help(void)
|
|
|
|
{
|
|
|
|
mprintf_stdout = 1;
|
|
|
|
|
|
|
|
mprintf("\n");
|
|
|
|
mprintf(" ClamAV: On Access Scanning Application and Client %s\n", get_version());
|
|
|
|
mprintf(" By The ClamAV Team: https://www.clamav.net/about.html#credits\n");
|
2019-02-28 13:13:14 -05:00
|
|
|
mprintf(" (C) 2007-2019 Cisco Systems, Inc.\n");
|
2018-12-03 13:17:07 -05:00
|
|
|
mprintf("\n");
|
|
|
|
mprintf(" clamonacc [options] [file/directory/-]\n");
|
|
|
|
mprintf("\n");
|
|
|
|
mprintf(" --help -h Show this help\n");
|
|
|
|
mprintf(" --version -V Print version number and exit\n");
|
|
|
|
mprintf(" --verbose -v Be verbose\n");
|
|
|
|
mprintf(" --log=FILE -l FILE Save scanning output to FILE\n");
|
2019-02-28 13:13:14 -05:00
|
|
|
mprintf(" --watch-list=FILE -w FILE Watch directories from FILE\n");
|
2018-12-03 13:17:07 -05:00
|
|
|
mprintf(" --exclude-list=FILES -f FILE Exclude directories from FILE\n");
|
|
|
|
mprintf(" --remove Remove infected files. Be careful!\n");
|
|
|
|
mprintf(" --move=DIRECTORY Move infected files into DIRECTORY\n");
|
|
|
|
mprintf(" --copy=DIRECTORY Copy infected files into DIRECTORY\n");
|
|
|
|
mprintf(" --config-file=FILE Read configuration from FILE.\n");
|
|
|
|
mprintf(" --allmatch -z Continue scanning within file after finding a match.\n");
|
|
|
|
mprintf(" --infected -i Only print infected files\n");
|
|
|
|
mprintf(" --fdpass Pass filedescriptor to clamd (useful if clamd is running as a different user)\n");
|
|
|
|
mprintf(" --stream Force streaming files to clamd (for debugging and unit testing)\n");
|
|
|
|
mprintf("\n");
|
|
|
|
|
|
|
|
exit(0);
|
|
|
|
}
|
2019-02-28 13:13:14 -05:00
|
|
|
|
|
|
|
void* onas_cleanup(struct onas_context *ctx) {
|
|
|
|
onas_context_cleanup(ctx);
|
|
|
|
cl_cleanup_crypto();
|
|
|
|
logg_close();
|
|
|
|
}
|
|
|
|
|
|
|
|
void* onas_context_cleanup(struct onas_context *ctx) {
|
|
|
|
close(ctx->fan_fd);
|
|
|
|
optfree((struct optstruct *) ctx->opts);
|
2019-04-04 10:43:19 -04:00
|
|
|
optfree((struct optstruct *) ctx->clamdopts);
|
2019-02-28 13:13:14 -05:00
|
|
|
ctx->opts = NULL;
|
|
|
|
ctx->clamdopts = NULL;
|
|
|
|
free(ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int ds, dms, ret, infected = 0, err = 0;
|
|
|
|
struct timeval t1, t2;
|
|
|
|
time_t starttime;
|
|
|
|
#ifndef _WIN32
|
|
|
|
struct sigaction sigact;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
memset(&sigact, 0, sizeof(struct sigaction));
|
|
|
|
sigact.sa_handler = SIG_IGN;
|
|
|
|
sigemptyset(&sigact.sa_mask);
|
|
|
|
sigaddset(&sigact.sa_mask, SIGPIPE);
|
|
|
|
sigaction(SIGPIPE, &sigact, NULL);
|
|
|
|
|
|
|
|
time(&starttime);
|
|
|
|
ctime() does \n, but I need it once more
|
|
|
|
|
|
|
|
gettimeofday(&t1, NULL);
|
|
|
|
|
|
|
|
ret = client(opts, &infected, &err);
|
|
|
|
}*/
|