clang-format'd using new .clang-format rules.

This commit is contained in:
Micah Snyder 2018-12-03 12:40:13 -05:00
parent 38fe8b69a0
commit 72fd33c8b2
335 changed files with 73102 additions and 74645 deletions

View file

@ -52,14 +52,15 @@
struct smfiDesc descr;
struct optstruct *opts;
static void milter_exit(int sig) {
static void milter_exit(int sig)
{
const struct optstruct *opt;
logg("*clamav-milter: milter_exit, signal %d\n", sig);
#ifndef _WIN32
if((opt = optget(opts, "MilterSocket"))) {
if(unlink(opt->strarg) == -1)
if ((opt = optget(opts, "MilterSocket"))) {
if (unlink(opt->strarg) == -1)
logg("!Can't unlink the socket file %s\n", opt->strarg);
else
logg("Socket file removed.\n");
@ -76,7 +77,8 @@ static void milter_exit(int sig) {
whitelist_free();
}
int main(int argc, char **argv) {
int main(int argc, char **argv)
{
char *my_socket, *pt;
const struct optstruct *opt;
time_t currtime;
@ -104,345 +106,345 @@ int main(int argc, char **argv) {
cl_initialize_crypto();
memset(&descr, 0, sizeof(struct smfiDesc));
descr.xxfi_name = "ClamAV"; /* filter name */
descr.xxfi_version = SMFI_VERSION; /* milter version */
descr.xxfi_flags = SMFIF_QUARANTINE; /* flags */
descr.xxfi_connect = clamfi_connect; /* connection info filter */
descr.xxfi_envfrom = clamfi_envfrom; /* envelope sender filter */
descr.xxfi_envrcpt = clamfi_envrcpt; /* envelope recipient filter */
descr.xxfi_header = clamfi_header; /* header filter */
descr.xxfi_body = clamfi_body; /* body block */
descr.xxfi_eom = clamfi_eom; /* end of message */
descr.xxfi_abort = clamfi_abort; /* message aborted */
descr.xxfi_name = "ClamAV"; /* filter name */
descr.xxfi_version = SMFI_VERSION; /* milter version */
descr.xxfi_flags = SMFIF_QUARANTINE; /* flags */
descr.xxfi_connect = clamfi_connect; /* connection info filter */
descr.xxfi_envfrom = clamfi_envfrom; /* envelope sender filter */
descr.xxfi_envrcpt = clamfi_envrcpt; /* envelope recipient filter */
descr.xxfi_header = clamfi_header; /* header filter */
descr.xxfi_body = clamfi_body; /* body block */
descr.xxfi_eom = clamfi_eom; /* end of message */
descr.xxfi_abort = clamfi_abort; /* message aborted */
opts = optparse(NULL, argc, argv, 1, OPT_MILTER, 0, NULL);
if (!opts) {
mprintf("!Can't parse command line options\n");
return 1;
mprintf("!Can't parse command line options\n");
return 1;
}
if(optget(opts, "help")->enabled) {
printf("\n");
printf(" Clam AntiVirus: Milter Mail Scanner %s\n", get_version());
printf(" By The ClamAV Team: https://www.clamav.net/about.html#credits\n");
printf(" (C) 2009-2018 Cisco Systems, Inc.\n");
printf("\n");
printf(" %s [-c <config-file>]\n\n", argv[0]);
printf("\n");
printf(" --help -h Show this help\n");
printf(" --version -V Show version\n");
printf(" --config-file <file> -c Read configuration from file\n");
printf("\n");
optfree(opts);
return 0;
if (optget(opts, "help")->enabled) {
printf("\n");
printf(" Clam AntiVirus: Milter Mail Scanner %s\n", get_version());
printf(" By The ClamAV Team: https://www.clamav.net/about.html#credits\n");
printf(" (C) 2009-2018 Cisco Systems, Inc.\n");
printf("\n");
printf(" %s [-c <config-file>]\n\n", argv[0]);
printf("\n");
printf(" --help -h Show this help\n");
printf(" --version -V Show version\n");
printf(" --config-file <file> -c Read configuration from file\n");
printf("\n");
optfree(opts);
return 0;
}
if(opts->filename) {
int x;
for(x = 0; opts->filename[x]; x++)
mprintf("^Ignoring option %s\n", opts->filename[x]);
if (opts->filename) {
int x;
for (x = 0; opts->filename[x]; x++)
mprintf("^Ignoring option %s\n", opts->filename[x]);
}
if(optget(opts, "version")->enabled) {
printf("clamav-milter %s\n", get_version());
optfree(opts);
return 0;
if (optget(opts, "version")->enabled) {
printf("clamav-milter %s\n", get_version());
optfree(opts);
return 0;
}
pt = strdup(optget(opts, "config-file")->strarg);
if (pt == NULL) {
printf("Unable to allocate memory for config file\n");
return 1;
printf("Unable to allocate memory for config file\n");
return 1;
}
if((opts = optparse(pt, 0, NULL, 1, OPT_MILTER, 0, opts)) == NULL) {
printf("%s: cannot parse config file %s\n", argv[0], pt);
free(pt);
return 1;
if ((opts = optparse(pt, 0, NULL, 1, OPT_MILTER, 0, opts)) == NULL) {
printf("%s: cannot parse config file %s\n", argv[0], pt);
free(pt);
return 1;
}
free(pt);
if((opt = optget(opts, "Chroot"))->enabled) {
if(chdir(opt->strarg) != 0) {
logg("!Cannot change directory to %s\n", opt->strarg);
return 1;
}
if(chroot(opt->strarg) != 0) {
logg("!chroot to %s failed. Are you root?\n", opt->strarg);
return 1;
}
if ((opt = optget(opts, "Chroot"))->enabled) {
if (chdir(opt->strarg) != 0) {
logg("!Cannot change directory to %s\n", opt->strarg);
return 1;
}
if (chroot(opt->strarg) != 0) {
logg("!chroot to %s failed. Are you root?\n", opt->strarg);
return 1;
}
}
pt = optget(opts, "AddHeader")->strarg;
if (strcasecmp(pt, "No")) {
char myname[255];
char myname[255];
if (((opt = optget(opts, "ReportHostname"))->enabled &&
strncpy(myname, opt->strarg, sizeof(myname))) ||
!gethostname(myname, sizeof(myname))) {
if (((opt = optget(opts, "ReportHostname"))->enabled &&
strncpy(myname, opt->strarg, sizeof(myname))) ||
!gethostname(myname, sizeof(myname))) {
myname[sizeof(myname)-1] = '\0';
snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s at %s",
get_version(), myname);
} else {
snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s",
get_version());
}
xvirushdr[sizeof(xvirushdr)-1] = '\0';
myname[sizeof(myname) - 1] = '\0';
snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s at %s",
get_version(), myname);
} else {
snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s",
get_version());
}
xvirushdr[sizeof(xvirushdr) - 1] = '\0';
descr.xxfi_flags |= SMFIF_ADDHDRS;
descr.xxfi_flags |= SMFIF_ADDHDRS;
if (strcasecmp(pt, "Add")) { /* Replace or Yes */
descr.xxfi_flags |= SMFIF_CHGHDRS;
addxvirus = 1;
} else { /* Add */
addxvirus = 2;
}
if (strcasecmp(pt, "Add")) { /* Replace or Yes */
descr.xxfi_flags |= SMFIF_CHGHDRS;
addxvirus = 1;
} else { /* Add */
addxvirus = 2;
}
}
if(!(my_socket = optget(opts, "MilterSocket")->strarg)) {
logg("!Please configure the MilterSocket directive\n");
logg_close();
optfree(opts);
return 1;
if (!(my_socket = optget(opts, "MilterSocket")->strarg)) {
logg("!Please configure the MilterSocket directive\n");
logg_close();
optfree(opts);
return 1;
}
if(smfi_setconn(my_socket) == MI_FAILURE) {
logg("!smfi_setconn failed\n");
logg_close();
optfree(opts);
return 1;
if (smfi_setconn(my_socket) == MI_FAILURE) {
logg("!smfi_setconn failed\n");
logg_close();
optfree(opts);
return 1;
}
if(smfi_register(descr) == MI_FAILURE) {
logg("!smfi_register failed\n");
logg_close();
optfree(opts);
return 1;
if (smfi_register(descr) == MI_FAILURE) {
logg("!smfi_register failed\n");
logg_close();
optfree(opts);
return 1;
}
opt = optget(opts, "FixStaleSocket");
opt = optget(opts, "FixStaleSocket");
umsk = umask(0777); /* socket is created with 000 to avoid races */
if(smfi_opensocket(opt->enabled) == MI_FAILURE) {
logg("!Failed to create socket %s\n", my_socket);
logg_close();
optfree(opts);
return 1;
if (smfi_opensocket(opt->enabled) == MI_FAILURE) {
logg("!Failed to create socket %s\n", my_socket);
logg_close();
optfree(opts);
return 1;
}
umask(umsk); /* restore umask */
if(strncmp(my_socket, "inet:", 5) && strncmp(my_socket, "inet6:", 6)) {
/* set group ownership and perms on the local socket */
char *sock_name = my_socket;
mode_t sock_mode;
if(!strncmp(my_socket, "unix:", 5))
sock_name += 5;
if(!strncmp(my_socket, "local:", 6))
sock_name += 6;
if(*my_socket == ':')
sock_name ++;
if (strncmp(my_socket, "inet:", 5) && strncmp(my_socket, "inet6:", 6)) {
/* set group ownership and perms on the local socket */
char *sock_name = my_socket;
mode_t sock_mode;
if (!strncmp(my_socket, "unix:", 5))
sock_name += 5;
if (!strncmp(my_socket, "local:", 6))
sock_name += 6;
if (*my_socket == ':')
sock_name++;
if(optget(opts, "MilterSocketGroup")->enabled) {
char *gname = optget(opts, "MilterSocketGroup")->strarg, *end;
gid_t sock_gid = strtol(gname, &end, 10);
if(*end) {
struct group *pgrp = getgrnam(gname);
if(!pgrp) {
logg("!Unknown group %s\n", gname);
logg_close();
optfree(opts);
return 1;
}
sock_gid = pgrp->gr_gid;
}
if(chown(sock_name, -1, sock_gid)) {
logg("!Failed to change socket ownership to group %s\n", gname);
logg_close();
optfree(opts);
return 1;
}
}
if (optget(opts, "MilterSocketGroup")->enabled) {
char *gname = optget(opts, "MilterSocketGroup")->strarg, *end;
gid_t sock_gid = strtol(gname, &end, 10);
if (*end) {
struct group *pgrp = getgrnam(gname);
if (!pgrp) {
logg("!Unknown group %s\n", gname);
logg_close();
optfree(opts);
return 1;
}
sock_gid = pgrp->gr_gid;
}
if (chown(sock_name, -1, sock_gid)) {
logg("!Failed to change socket ownership to group %s\n", gname);
logg_close();
optfree(opts);
return 1;
}
}
if ((opt = optget(opts, "User"))->enabled) {
struct passwd *user;
if ((user = getpwnam(opt->strarg)) == NULL) {
logg("ERROR: Can't get information about user %s.\n",
opt->strarg);
logg_close();
optfree(opts);
return 1;
}
if ((opt = optget(opts, "User"))->enabled) {
struct passwd *user;
if ((user = getpwnam(opt->strarg)) == NULL) {
logg("ERROR: Can't get information about user %s.\n",
opt->strarg);
logg_close();
optfree(opts);
return 1;
}
if(chown(sock_name, user->pw_uid, -1)) {
logg("!Failed to change socket ownership to user %s\n", user->pw_name);
optfree(opts);
logg_close();
return 1;
}
}
if (chown(sock_name, user->pw_uid, -1)) {
logg("!Failed to change socket ownership to user %s\n", user->pw_name);
optfree(opts);
logg_close();
return 1;
}
}
if(optget(opts, "MilterSocketMode")->enabled) {
char *end;
sock_mode = strtol(optget(opts, "MilterSocketMode")->strarg, &end, 8);
if(*end) {
logg("!Invalid MilterSocketMode %s\n", optget(opts, "MilterSocketMode")->strarg);
logg_close();
optfree(opts);
return 1;
}
} else
sock_mode = 0777 & ~umsk;
if (optget(opts, "MilterSocketMode")->enabled) {
char *end;
sock_mode = strtol(optget(opts, "MilterSocketMode")->strarg, &end, 8);
if (*end) {
logg("!Invalid MilterSocketMode %s\n", optget(opts, "MilterSocketMode")->strarg);
logg_close();
optfree(opts);
return 1;
}
} else
sock_mode = 0777 & ~umsk;
if(chmod(sock_name, sock_mode & 0666)) {
logg("!Cannot set milter socket permission to %s\n", optget(opts, "MilterSocketMode")->strarg);
logg_close();
optfree(opts);
return 1;
}
if (chmod(sock_name, sock_mode & 0666)) {
logg("!Cannot set milter socket permission to %s\n", optget(opts, "MilterSocketMode")->strarg);
logg_close();
optfree(opts);
return 1;
}
}
if(geteuid() == 0 && (opt = optget(opts, "User"))->enabled) {
if (geteuid() == 0 && (opt = optget(opts, "User"))->enabled) {
struct passwd *user = NULL;
if((user = getpwnam(opt->strarg)) == NULL) {
fprintf(stderr, "ERROR: Can't get information about user %s.\n", opt->strarg);
optfree(opts);
return 1;
}
if ((user = getpwnam(opt->strarg)) == NULL) {
fprintf(stderr, "ERROR: Can't get information about user %s.\n", opt->strarg);
optfree(opts);
return 1;
}
#ifdef HAVE_INITGROUPS
if(initgroups(opt->strarg, user->pw_gid)) {
fprintf(stderr, "ERROR: initgroups() failed.\n");
optfree(opts);
return 1;
}
if (initgroups(opt->strarg, user->pw_gid)) {
fprintf(stderr, "ERROR: initgroups() failed.\n");
optfree(opts);
return 1;
}
#elif HAVE_SETGROUPS
if(setgroups(1, &user->pw_gid)) {
fprintf(stderr, "ERROR: setgroups() failed.\n");
optfree(opts);
return 1;
}
if (setgroups(1, &user->pw_gid)) {
fprintf(stderr, "ERROR: setgroups() failed.\n");
optfree(opts);
return 1;
}
#endif
if(setgid(user->pw_gid)) {
fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid);
optfree(opts);
return 1;
}
if (setgid(user->pw_gid)) {
fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int)user->pw_gid);
optfree(opts);
return 1;
}
if(setuid(user->pw_uid)) {
fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid);
optfree(opts);
return 1;
}
if (setuid(user->pw_uid)) {
fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int)user->pw_uid);
optfree(opts);
return 1;
}
}
logg_lock = !optget(opts, "LogFileUnlock")->enabled;
logg_time = optget(opts, "LogTime")->enabled;
logg_size = optget(opts, "LogFileMaxSize")->numarg;
logg_lock = !optget(opts, "LogFileUnlock")->enabled;
logg_time = optget(opts, "LogTime")->enabled;
logg_size = optget(opts, "LogFileMaxSize")->numarg;
logg_verbose = mprintf_verbose = optget(opts, "LogVerbose")->enabled;
if (logg_size)
logg_rotate = optget(opts, "LogRotate")->enabled;
if((opt = optget(opts, "LogFile"))->enabled) {
logg_file = opt->strarg;
if(!cli_is_abspath(logg_file)) {
fprintf(stderr, "ERROR: LogFile requires full path.\n");
logg_close();
optfree(opts);
return 1;
}
if ((opt = optget(opts, "LogFile"))->enabled) {
logg_file = opt->strarg;
if (!cli_is_abspath(logg_file)) {
fprintf(stderr, "ERROR: LogFile requires full path.\n");
logg_close();
optfree(opts);
return 1;
}
} else
logg_file = NULL;
logg_file = NULL;
#if defined(USE_SYSLOG) && !defined(C_AIX)
if(optget(opts, "LogSyslog")->enabled) {
int fac;
if (optget(opts, "LogSyslog")->enabled) {
int fac;
opt = optget(opts, "LogFacility");
if((fac = logg_facility(opt->strarg)) == -1) {
logg("!LogFacility: %s: No such facility.\n", opt->strarg);
logg_close();
optfree(opts);
return 1;
}
opt = optget(opts, "LogFacility");
if ((fac = logg_facility(opt->strarg)) == -1) {
logg("!LogFacility: %s: No such facility.\n", opt->strarg);
logg_close();
optfree(opts);
return 1;
}
openlog("clamav-milter", LOG_PID, fac);
logg_syslog = 1;
openlog("clamav-milter", LOG_PID, fac);
logg_syslog = 1;
}
#endif
time(&currtime);
if(logg("#+++ Started at %s", ctime(&currtime))) {
fprintf(stderr, "ERROR: Can't initialize the internal logger\n");
logg_close();
optfree(opts);
return 1;
if (logg("#+++ Started at %s", ctime(&currtime))) {
fprintf(stderr, "ERROR: Can't initialize the internal logger\n");
logg_close();
optfree(opts);
return 1;
}
if((opt = optget(opts, "TemporaryDirectory"))->enabled)
tempdir = opt->strarg;
if ((opt = optget(opts, "TemporaryDirectory"))->enabled)
tempdir = opt->strarg;
if(localnets_init(opts) || init_actions(opts)) {
logg_close();
optfree(opts);
return 1;
if (localnets_init(opts) || init_actions(opts)) {
logg_close();
optfree(opts);
return 1;
}
if((opt = optget(opts, "Whitelist"))->enabled && whitelist_init(opt->strarg)) {
localnets_free();
logg_close();
optfree(opts);
return 1;
if ((opt = optget(opts, "Whitelist"))->enabled && whitelist_init(opt->strarg)) {
localnets_free();
logg_close();
optfree(opts);
return 1;
}
if((opt = optget(opts, "SkipAuthenticated"))->enabled && smtpauth_init(opt->strarg)) {
localnets_free();
whitelist_free();
logg_close();
optfree(opts);
return 1;
if ((opt = optget(opts, "SkipAuthenticated"))->enabled && smtpauth_init(opt->strarg)) {
localnets_free();
whitelist_free();
logg_close();
optfree(opts);
return 1;
}
multircpt = optget(opts, "SupportMultipleRecipients")->enabled;
if(!optget(opts, "Foreground")->enabled) {
if(daemonize() == -1) {
logg("!daemonize() failed\n");
localnets_free();
whitelist_free();
cpool_free();
logg_close();
optfree(opts);
return 1;
}
if(chdir("/") == -1)
logg("^Can't change current working directory to root\n");
if (!optget(opts, "Foreground")->enabled) {
if (daemonize() == -1) {
logg("!daemonize() failed\n");
localnets_free();
whitelist_free();
cpool_free();
logg_close();
optfree(opts);
return 1;
}
if (chdir("/") == -1)
logg("^Can't change current working directory to root\n");
}
maxfilesize = optget(opts, "MaxFileSize")->numarg;
if(!maxfilesize) {
logg("^Invalid MaxFileSize, using default (%d)\n", CLI_DEFAULT_MAXFILESIZE);
maxfilesize = CLI_DEFAULT_MAXFILESIZE;
if (!maxfilesize) {
logg("^Invalid MaxFileSize, using default (%d)\n", CLI_DEFAULT_MAXFILESIZE);
maxfilesize = CLI_DEFAULT_MAXFILESIZE;
}
readtimeout = optget(opts, "ReadTimeout")->numarg;
cpool_init(opts);
if (!cp) {
logg("!Failed to init the socket pool\n");
localnets_free();
whitelist_free();
logg_close();
optfree(opts);
return 1;
logg("!Failed to init the socket pool\n");
localnets_free();
whitelist_free();
logg_close();
optfree(opts);
return 1;
}
if((opt = optget(opts, "PidFile"))->enabled) {
FILE *fd;
mode_t old_umask = umask(0002);
if ((opt = optget(opts, "PidFile"))->enabled) {
FILE *fd;
mode_t old_umask = umask(0002);
if((fd = fopen(opt->strarg, "w")) == NULL) {
logg("!Can't save PID in file %s\n", opt->strarg);
} else {
if (fprintf(fd, "%u\n", (unsigned int)getpid())<0) {
logg("!Can't save PID in file %s\n", opt->strarg);
}
fclose(fd);
}
umask(old_umask);
if ((fd = fopen(opt->strarg, "w")) == NULL) {
logg("!Can't save PID in file %s\n", opt->strarg);
} else {
if (fprintf(fd, "%u\n", (unsigned int)getpid()) < 0) {
logg("!Can't save PID in file %s\n", opt->strarg);
}
fclose(fd);
}
umask(old_umask);
}
return smfi_main();

File diff suppressed because it is too large Load diff

View file

@ -30,7 +30,6 @@ extern int addxvirus;
extern char xvirushdr[255];
extern int multircpt;
sfsistat clamfi_body(SMFICTX *ctx, unsigned char *bodyp, size_t len);
sfsistat clamfi_abort(SMFICTX *ctx);
sfsistat clamfi_eom(SMFICTX *ctx);

View file

@ -43,50 +43,62 @@
#include "connpool.h"
#include "netcode.h"
#define SETGAI(k, v) {(k)->gai = (void *)(v);} while(0)
#define FREESRV(k) { if((k).gai) freeaddrinfo((k).gai); else if((k).server) free((k).server); } while(0)
#define SETGAI(k, v) \
{ \
(k)->gai = (void *)(v); \
} \
while (0)
#define FREESRV(k) \
{ \
if ((k).gai) \
freeaddrinfo((k).gai); \
else if ((k).server) \
free((k).server); \
} \
while (0)
#if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
#define _UNUSED_ __attribute__ ((__unused__))
#define _UNUSED_ __attribute__((__unused__))
#else
#define _UNUSED_
#endif
struct CPOOL *cp = NULL;
struct CPOOL *cp = NULL;
static pthread_cond_t mon_cond = PTHREAD_COND_INITIALIZER;
static int quitting = 1;
static int quitting = 1;
static pthread_t probe_th;
static int cpool_addunix(char *path) {
static int cpool_addunix(char *path)
{
struct sockaddr_un *srv;
struct CP_ENTRY *cpe = &cp->pool[cp->entries-1];
struct CP_ENTRY *cpe = &cp->pool[cp->entries - 1];
if(!cli_is_abspath(path)) {
logg("!Unix clamd socket must be an absolute path\n");
return 1;
if (!cli_is_abspath(path)) {
logg("!Unix clamd socket must be an absolute path\n");
return 1;
}
if(!(srv = (struct sockaddr_un *)malloc(sizeof(*srv)))) {
logg("!Out of memory allocating unix socket space\n");
return 1;
if (!(srv = (struct sockaddr_un *)malloc(sizeof(*srv)))) {
logg("!Out of memory allocating unix socket space\n");
return 1;
}
srv->sun_family = AF_UNIX;
strncpy(srv->sun_path, path, sizeof(srv->sun_path));
srv->sun_path[sizeof(srv->sun_path)-1]='\0';
cpe->type = 0;
cpe->dead = 1;
cpe->local = 1;
cpe->last_poll = 0;
cpe->server = (struct sockaddr *)srv;
cpe->socklen = sizeof(*srv);
srv->sun_path[sizeof(srv->sun_path) - 1] = '\0';
cpe->type = 0;
cpe->dead = 1;
cpe->local = 1;
cpe->last_poll = 0;
cpe->server = (struct sockaddr *)srv;
cpe->socklen = sizeof(*srv);
SETGAI(cpe, NULL);
if(!cp->local_cpe) cp->local_cpe = cpe;
if (!cp->local_cpe) cp->local_cpe = cpe;
logg("*Local socket unix:%s added to the pool (slot %d)\n", srv->sun_path, cp->entries);
return 0;
}
static int islocal(struct sockaddr *sa, socklen_t addrlen) {
static int islocal(struct sockaddr *sa, socklen_t addrlen)
{
int s = socket(sa->sa_family, SOCK_STREAM, 0);
int ret;
if (s < 0) return 0;
@ -95,197 +107,197 @@ static int islocal(struct sockaddr *sa, socklen_t addrlen) {
return ret;
}
static int cpool_addtcp(char *addr, char *port) {
static int cpool_addtcp(char *addr, char *port)
{
struct addrinfo hints, *res, *res2;
struct CP_ENTRY *cpe = (struct CP_ENTRY *)&cp->pool[cp->entries-1];
struct CP_ENTRY *cpe = (struct CP_ENTRY *)&cp->pool[cp->entries - 1];
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if(getaddrinfo(addr, port ? port : "3310", &hints, &res)) {
logg("^Can't resolve hostname %s\n", addr ? addr : "");
return 1;
if (getaddrinfo(addr, port ? port : "3310", &hints, &res)) {
logg("^Can't resolve hostname %s\n", addr ? addr : "");
return 1;
}
cpe->type = 1;
cpe->dead = 1;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_UNSPEC;
if(!getaddrinfo(addr, NULL, &hints, &res2)) {
cpe->local = islocal(res2->ai_addr, res2->ai_addrlen);
freeaddrinfo(res2);
} else cpe->local = 0;
hints.ai_family = AF_UNSPEC;
if (!getaddrinfo(addr, NULL, &hints, &res2)) {
cpe->local = islocal(res2->ai_addr, res2->ai_addrlen);
freeaddrinfo(res2);
} else
cpe->local = 0;
cpe->last_poll = 0;
cpe->server = res->ai_addr;
cpe->socklen = res->ai_addrlen;
cpe->server = res->ai_addr;
cpe->socklen = res->ai_addrlen;
SETGAI(cpe, res);
logg("*%s socket tcp:%s:%s added to the pool (slot %d)\n", cpe->local ? "Local" : "Remote", addr ? addr : "localhost", port ? port : "3310", cp->entries);
return 0;
}
static int addslot(void) {
static int addslot(void)
{
struct CP_ENTRY *cpe;
if(!(cpe = realloc(cp->pool, (cp->entries + 1) * sizeof(struct CP_ENTRY)))) {
logg("!Out of memory while initializing the connection pool\n");
cpool_free();
return 1;
if (!(cpe = realloc(cp->pool, (cp->entries + 1) * sizeof(struct CP_ENTRY)))) {
logg("!Out of memory while initializing the connection pool\n");
cpool_free();
return 1;
}
if(cp->local_cpe)
cp->local_cpe = (struct CP_ENTRY *)((char *)cp->local_cpe + ((char *)cpe - (char *)cp->pool));
if (cp->local_cpe)
cp->local_cpe = (struct CP_ENTRY *)((char *)cp->local_cpe + ((char *)cpe - (char *)cp->pool));
memset(&cpe[cp->entries], 0, sizeof(*cpe));
cp->pool = cpe;
cp->entries++;
return 0;
}
/* Probe strategy:
- wake up every minute
- probe alive if last check > 15 min
- probe dead if (last check > 2 min || no clamd available)
*/
static void cpool_probe(void) {
unsigned int i, dead=0;
static void cpool_probe(void)
{
unsigned int i, dead = 0;
struct CP_ENTRY *cpe = cp->pool;
time_t now = time(NULL);
time_t now = time(NULL);
for(i=1; i<=cp->entries; i++) {
if((cpe->dead && (cpe->last_poll < now - 120 || !cp->alive)) || cpe->last_poll < now - 15*60*60) {
cpe->last_poll = time(NULL);
nc_ping_entry(cpe);
logg("*Probe for slot %u returned: %s\n", i, cpe->dead ? "failed" : "success");
}
dead += cpe->dead;
cpe++;
for (i = 1; i <= cp->entries; i++) {
if ((cpe->dead && (cpe->last_poll < now - 120 || !cp->alive)) || cpe->last_poll < now - 15 * 60 * 60) {
cpe->last_poll = time(NULL);
nc_ping_entry(cpe);
logg("*Probe for slot %u returned: %s\n", i, cpe->dead ? "failed" : "success");
}
dead += cpe->dead;
cpe++;
}
cp->alive = cp->entries - dead;
if(!cp->alive)
logg("^No clamd server appears to be available\n");
if (!cp->alive)
logg("^No clamd server appears to be available\n");
}
static void *cpool_mon(_UNUSED_ void *v) {
static void *cpool_mon(_UNUSED_ void *v)
{
pthread_mutex_t conv;
pthread_mutex_init(&conv, NULL);
pthread_mutex_lock(&conv);
while(!quitting) {
struct timespec t;
while (!quitting) {
struct timespec t;
cpool_probe();
t.tv_sec = time(NULL) + 60;
t.tv_nsec = 0;
pthread_cond_timedwait(&mon_cond, &conv, &t);
cpool_probe();
t.tv_sec = time(NULL) + 60;
t.tv_nsec = 0;
pthread_cond_timedwait(&mon_cond, &conv, &t);
}
pthread_mutex_unlock(&conv);
pthread_mutex_destroy(&conv);
return NULL;
}
void cpool_init(struct optstruct *opts) {
void cpool_init(struct optstruct *opts)
{
const struct optstruct *opt;
int failed = 0;
if(!(cp=calloc(sizeof(*cp), 1))) {
logg("!Out of memory while initializing the connection pool");
return;
if (!(cp = calloc(sizeof(*cp), 1))) {
logg("!Out of memory while initializing the connection pool");
return;
}
cp->local_cpe = NULL;
if((opt = optget(opts, "ClamdSocket"))->enabled) {
while(opt) {
char *socktype = opt->strarg;
if ((opt = optget(opts, "ClamdSocket"))->enabled) {
while (opt) {
char *socktype = opt->strarg;
if(addslot()) return;
if(!strncasecmp(socktype, "unix:", 5)) {
failed = cpool_addunix(socktype+5);
} else if(!strncasecmp(socktype, "tcp:", 4)) {
char *port = strrchr(socktype+4, ':');
if(port) {
*port='\0';
port++;
}
failed = cpool_addtcp(socktype+4, port);
} else {
logg("!Failed to parse ClamdSocket directive '%s'\n", socktype);
failed = 1;
}
if(failed) break;
opt = opt->nextarg;
}
if(failed) {
cpool_free();
return;
}
if (addslot()) return;
if (!strncasecmp(socktype, "unix:", 5)) {
failed = cpool_addunix(socktype + 5);
} else if (!strncasecmp(socktype, "tcp:", 4)) {
char *port = strrchr(socktype + 4, ':');
if (port) {
*port = '\0';
port++;
}
failed = cpool_addtcp(socktype + 4, port);
} else {
logg("!Failed to parse ClamdSocket directive '%s'\n", socktype);
failed = 1;
}
if (failed) break;
opt = opt->nextarg;
}
if (failed) {
cpool_free();
return;
}
}
if(!cp->entries) {
logg("!No ClamdSocket specified\n");
cpool_free();
return;
if (!cp->entries) {
logg("!No ClamdSocket specified\n");
cpool_free();
return;
}
quitting = 0;
pthread_create(&probe_th, NULL, cpool_mon, NULL);
srand(time(NULL));
}
void cpool_free(void) {
void cpool_free(void)
{
unsigned int i;
if(!quitting) {
logg("*Killing the monitor and stopping\n");
quitting = 1;
pthread_cond_signal(&mon_cond);
pthread_join(probe_th, NULL);
if (!quitting) {
logg("*Killing the monitor and stopping\n");
quitting = 1;
pthread_cond_signal(&mon_cond);
pthread_join(probe_th, NULL);
}
if(cp) {
if(cp->pool) {
for(i=0; i<cp->entries; i++)
FREESRV(cp->pool[i]);
free(cp->pool);
}
free(cp);
cp = NULL;
if (cp) {
if (cp->pool) {
for (i = 0; i < cp->entries; i++)
FREESRV(cp->pool[i]);
free(cp->pool);
}
free(cp);
cp = NULL;
}
}
struct CP_ENTRY *cpool_get_rand(int *s) {
struct CP_ENTRY *cpool_get_rand(int *s)
{
unsigned int start, i;
struct CP_ENTRY *cpe;
if(cp->alive) {
start = rand() % cp->entries;
for(i=0; i<cp->entries; i++) {
cpe = &cp->pool[(i+start) % cp->entries];
if(cpe->dead) continue;
if(cpe->local && cp->local_cpe && !cp->local_cpe->dead)
cpe = cp->local_cpe;
if((*s = nc_connect_entry(cpe)) == -1) {
cpe->dead = 1;
continue;
}
return cpe;
}
if (cp->alive) {
start = rand() % cp->entries;
for (i = 0; i < cp->entries; i++) {
cpe = &cp->pool[(i + start) % cp->entries];
if (cpe->dead) continue;
if (cpe->local && cp->local_cpe && !cp->local_cpe->dead)
cpe = cp->local_cpe;
if ((*s = nc_connect_entry(cpe)) == -1) {
cpe->dead = 1;
continue;
}
return cpe;
}
}
pthread_cond_signal(&mon_cond);
return NULL;
}
/*
* Local Variables:
* mode: c

View file

@ -51,7 +51,7 @@
#include "libclamav/others.h"
#include "netcode.h"
#define strerror_print(msg) logg(msg": %s\n", cli_strerror(errno, er, sizeof(er)))
#define strerror_print(msg) logg(msg ": %s\n", cli_strerror(errno, er, sizeof(er)))
enum {
NON_SMTP,
@ -68,359 +68,362 @@ struct LOCALNET {
};
struct LOCALNET *lnet = NULL;
char *tempdir = NULL;
char *tempdir = NULL;
/* for connect and send */
#define TIMEOUT 30
/* for recv */
long readtimeout;
static int nc_socket(struct CP_ENTRY *cpe) {
static int nc_socket(struct CP_ENTRY *cpe)
{
int flags, s = socket(cpe->server->sa_family, SOCK_STREAM, 0);
char er[256];
if (s == -1) {
strerror_print("!Failed to create socket");
return -1;
strerror_print("!Failed to create socket");
return -1;
}
flags = fcntl(s, F_GETFL, 0);
if (flags == -1) {
strerror_print("!fcntl_get failed");
close(s);
return -1;
strerror_print("!fcntl_get failed");
close(s);
return -1;
}
flags |= O_NONBLOCK;
if (fcntl(s, F_SETFL, flags) == -1) {
strerror_print("!fcntl_set failed");
close(s);
return -1;
strerror_print("!fcntl_set failed");
close(s);
return -1;
}
return s;
}
static int nc_connect(int s, struct CP_ENTRY *cpe) {
static int nc_connect(int s, struct CP_ENTRY *cpe)
{
time_t timeout = time(NULL) + TIMEOUT;
int res = connect(s, cpe->server, cpe->socklen);
int res = connect(s, cpe->server, cpe->socklen);
struct timeval tv;
char er[256];
if (!res) return 0;
if (errno != EINPROGRESS) {
strerror_print("*connect failed");
close(s);
return -1;
strerror_print("*connect failed");
close(s);
return -1;
}
tv.tv_sec = TIMEOUT;
tv.tv_sec = TIMEOUT;
tv.tv_usec = 0;
while(1) {
fd_set fds;
int s_err;
socklen_t s_len = sizeof(s_err);
while (1) {
fd_set fds;
int s_err;
socklen_t s_len = sizeof(s_err);
FD_ZERO(&fds);
FD_SET(s, &fds);
res = select(s+1, NULL, &fds, NULL, &tv);
if(res < 1) {
time_t now;
FD_ZERO(&fds);
FD_SET(s, &fds);
res = select(s + 1, NULL, &fds, NULL, &tv);
if (res < 1) {
time_t now;
if (res == -1 && errno == EINTR && ((now = time(NULL)) < timeout)) {
tv.tv_sec = timeout - now;
tv.tv_usec = 0;
continue;
}
logg("*Failed to establish a connection to clamd\n");
close(s);
return -1;
}
if(getsockopt(s, SOL_SOCKET, SO_ERROR, &s_err, (socklen_t *)&s_len) || s_err) {
logg("*Failed to establish a connection to clamd\n");
close(s);
return -1;
}
return 0;
if (res == -1 && errno == EINTR && ((now = time(NULL)) < timeout)) {
tv.tv_sec = timeout - now;
tv.tv_usec = 0;
continue;
}
logg("*Failed to establish a connection to clamd\n");
close(s);
return -1;
}
if (getsockopt(s, SOL_SOCKET, SO_ERROR, &s_err, (socklen_t *)&s_len) || s_err) {
logg("*Failed to establish a connection to clamd\n");
close(s);
return -1;
}
return 0;
}
}
int nc_send(int s, const void *buff, size_t len) {
int nc_send(int s, const void *buff, size_t len)
{
char *buf = (char *)buff;
while(len) {
int res = send(s, buf, len, 0);
time_t timeout = time(NULL) + TIMEOUT;
struct timeval tv;
char er[256];
while (len) {
int res = send(s, buf, len, 0);
time_t timeout = time(NULL) + TIMEOUT;
struct timeval tv;
char er[256];
if(!res) {
logg("!Connection closed while sending data\n");
close(s);
return 1;
}
if(res!=-1) {
len-=res;
buf+=res;
continue;
}
if(errno != EAGAIN && errno != EWOULDBLOCK) {
strerror_print("!send failed");
close(s);
return 1;
}
if (!res) {
logg("!Connection closed while sending data\n");
close(s);
return 1;
}
if (res != -1) {
len -= res;
buf += res;
continue;
}
if (errno != EAGAIN && errno != EWOULDBLOCK) {
strerror_print("!send failed");
close(s);
return 1;
}
tv.tv_sec = TIMEOUT;
tv.tv_usec = 0;
while(1) {
fd_set fds;
tv.tv_sec = TIMEOUT;
tv.tv_usec = 0;
while (1) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(s, &fds);
res = select(s+1, NULL, &fds, NULL, &tv);
if(res < 1) {
time_t now;
FD_ZERO(&fds);
FD_SET(s, &fds);
res = select(s + 1, NULL, &fds, NULL, &tv);
if (res < 1) {
time_t now;
if (res == -1 && errno == EINTR && ((now = time(NULL)) < timeout)) {
tv.tv_sec = timeout - now;
tv.tv_usec = 0;
continue;
}
logg("!Failed to stream to clamd\n");
close(s);
return 1;
}
break;
}
if (res == -1 && errno == EINTR && ((now = time(NULL)) < timeout)) {
tv.tv_sec = timeout - now;
tv.tv_usec = 0;
continue;
}
logg("!Failed to stream to clamd\n");
close(s);
return 1;
}
break;
}
}
return 0;
}
int nc_sendmsg(int s, int fd) {
int nc_sendmsg(int s, int fd)
{
struct iovec iov[1];
struct msghdr msg;
struct cmsghdr *cmsg;
int ret;
unsigned char fdbuf[CMSG_SPACE(sizeof(int))];
char dummy[]="";
char dummy[] = "";
iov[0].iov_base = dummy;
iov[0].iov_len = 1;
iov[0].iov_len = 1;
memset(&msg, 0, sizeof(msg));
msg.msg_control = fdbuf;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_controllen = CMSG_LEN(sizeof(int));
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
msg.msg_control = fdbuf;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_controllen = CMSG_LEN(sizeof(int));
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = fd;
/* FIXME: nonblock code needed (?) */
if((ret = sendmsg(s, &msg, 0)) == -1) {
char er[256];
strerror_print("!clamfi_eom: FD send failed");
close(s);
if ((ret = sendmsg(s, &msg, 0)) == -1) {
char er[256];
strerror_print("!clamfi_eom: FD send failed");
close(s);
}
return ret;
}
char *nc_recv(int s) {
char buf[128], *ret=NULL;
char *nc_recv(int s)
{
char buf[128], *ret = NULL;
time_t now, timeout = time(NULL) + readtimeout;
struct timeval tv;
fd_set fds;
int res;
unsigned int len = 0;
while(1) {
now = time(NULL);
if(now >= timeout) {
logg("!Timed out while reading clamd reply\n");
close(s);
return NULL;
}
tv.tv_sec = timeout - now;
tv.tv_usec = 0;
while (1) {
now = time(NULL);
if (now >= timeout) {
logg("!Timed out while reading clamd reply\n");
close(s);
return NULL;
}
tv.tv_sec = timeout - now;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(s, &fds);
FD_ZERO(&fds);
FD_SET(s, &fds);
res = select(s+1, &fds, NULL, NULL, readtimeout ? &tv : NULL);
if(res<1) {
if (res != -1 || errno != EINTR)
timeout = 0;
continue;
}
res = select(s + 1, &fds, NULL, NULL, readtimeout ? &tv : NULL);
if (res < 1) {
if (res != -1 || errno != EINTR)
timeout = 0;
continue;
}
res = recv(s, &buf[len], sizeof(buf) - len, 0);
if(!res) {
logg("!Connection closed while reading from socket\n");
close(s);
return NULL;
}
if(res==-1) {
char er[256];
if (errno == EAGAIN)
continue;
strerror_print("!recv failed after successful select");
close(s);
return NULL;
}
len += res;
if(len && buf[len-1] == '\n') break;
if(len >= sizeof(buf)) {
logg("!Overlong reply from clamd\n");
close(s);
return NULL;
}
res = recv(s, &buf[len], sizeof(buf) - len, 0);
if (!res) {
logg("!Connection closed while reading from socket\n");
close(s);
return NULL;
}
if (res == -1) {
char er[256];
if (errno == EAGAIN)
continue;
strerror_print("!recv failed after successful select");
close(s);
return NULL;
}
len += res;
if (len && buf[len - 1] == '\n') break;
if (len >= sizeof(buf)) {
logg("!Overlong reply from clamd\n");
close(s);
return NULL;
}
}
if(!(ret = (char *)malloc(len+1))) {
logg("!malloc(%d) failed\n", len+1);
close(s);
return NULL;
if (!(ret = (char *)malloc(len + 1))) {
logg("!malloc(%d) failed\n", len + 1);
close(s);
return NULL;
}
memcpy(ret, buf, len);
ret[len]='\0';
ret[len] = '\0';
return ret;
}
int nc_connect_entry(struct CP_ENTRY *cpe) {
int nc_connect_entry(struct CP_ENTRY *cpe)
{
int s = nc_socket(cpe);
if(s==-1) return -1;
if (s == -1) return -1;
return nc_connect(s, cpe) ? -1 : s;
}
void nc_ping_entry(struct CP_ENTRY *cpe) {
void nc_ping_entry(struct CP_ENTRY *cpe)
{
int s = nc_connect_entry(cpe);
char *reply;
if(s>=0) {
if(!nc_send(s, "nPING\n", 6) && (reply = nc_recv(s))) {
cpe->dead = strcmp(reply, "PONG\n")!=0;
free(reply);
close(s);
return;
}
close(s);
if (s >= 0) {
if (!nc_send(s, "nPING\n", 6) && (reply = nc_recv(s))) {
cpe->dead = strcmp(reply, "PONG\n") != 0;
free(reply);
close(s);
return;
}
close(s);
}
cpe->dead = 1;
}
int nc_connect_rand(int *main, int *alt, int *local) {
int nc_connect_rand(int *main, int *alt, int *local)
{
struct CP_ENTRY *cpe = cpool_get_rand(main);
if(!cpe) return 1;
if (!cpe) return 1;
*local = (cpe->server->sa_family == AF_UNIX);
if(*local) {
char *unlinkme;
if(cli_gentempfd(tempdir, &unlinkme, alt) != CL_SUCCESS) {
logg("!Failed to create temporary file\n");
close(*main);
return 1;
}
unlink(unlinkme);
free(unlinkme);
if(nc_send(*main, "nFILDES\n", 8)) {
logg("!FD scan request failed\n");
close(*alt);
close(*main);
return 1;
}
if (*local) {
char *unlinkme;
if (cli_gentempfd(tempdir, &unlinkme, alt) != CL_SUCCESS) {
logg("!Failed to create temporary file\n");
close(*main);
return 1;
}
unlink(unlinkme);
free(unlinkme);
if (nc_send(*main, "nFILDES\n", 8)) {
logg("!FD scan request failed\n");
close(*alt);
close(*main);
return 1;
}
} else {
if(nc_send(*main, "nINSTREAM\n", 10)) {
logg("!Failed to communicate with clamd\n");
close(*main);
return 1;
}
if (nc_send(*main, "nINSTREAM\n", 10)) {
logg("!Failed to communicate with clamd\n");
close(*main);
return 1;
}
}
return 0;
}
static int resolve(char *name, uint32_t *family, uint32_t *host) {
static int resolve(char *name, uint32_t *family, uint32_t *host)
{
struct addrinfo hints, *res;
if(!name) {
/* l->basehost[0] = l->basehost[1] = l->basehost[2] = l->basehost[3] = 0; DONT BOTHER*/
*family = NON_SMTP;
return 0;
if (!name) {
/* l->basehost[0] = l->basehost[1] = l->basehost[2] = l->basehost[3] = 0; DONT BOTHER*/
*family = NON_SMTP;
return 0;
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if(getaddrinfo(name, NULL, &hints, &res)) {
logg("!Can't resolve LocalNet hostname %s\n", name);
return 1;
if (getaddrinfo(name, NULL, &hints, &res)) {
logg("!Can't resolve LocalNet hostname %s\n", name);
return 1;
}
if(res->ai_addrlen == sizeof(struct sockaddr_in) && res->ai_addr->sa_family == AF_INET) {
struct sockaddr_in *sa = (struct sockaddr_in *)res->ai_addr;
if (res->ai_addrlen == sizeof(struct sockaddr_in) && res->ai_addr->sa_family == AF_INET) {
struct sockaddr_in *sa = (struct sockaddr_in *)res->ai_addr;
*family = INET_HOST;
host[0] = htonl(sa->sin_addr.s_addr);
/* host[1] = host[2] = host[3] = 0; DONT BOTHER*/
} else if(res->ai_addrlen == sizeof(struct sockaddr_in6) && res->ai_addr->sa_family == AF_INET6) {
struct sockaddr_in6 *sa = (struct sockaddr_in6 *)res->ai_addr;
unsigned int i, j;
uint32_t u = 0;
*family = INET_HOST;
host[0] = htonl(sa->sin_addr.s_addr);
/* host[1] = host[2] = host[3] = 0; DONT BOTHER*/
} else if (res->ai_addrlen == sizeof(struct sockaddr_in6) && res->ai_addr->sa_family == AF_INET6) {
struct sockaddr_in6 *sa = (struct sockaddr_in6 *)res->ai_addr;
unsigned int i, j;
uint32_t u = 0;
*family = INET6_HOST;
for(i=0, j=0; i<16; i++) {
u += (sa->sin6_addr.s6_addr[i] << (8*j));
if(++j == 4) {
host[i>>2] = u;
j = u = 0;
}
}
*family = INET6_HOST;
for (i = 0, j = 0; i < 16; i++) {
u += (sa->sin6_addr.s6_addr[i] << (8 * j));
if (++j == 4) {
host[i >> 2] = u;
j = u = 0;
}
}
} else {
logg("!Unsupported address type for LocalNet %s\n", name);
freeaddrinfo(res);
return 1;
logg("!Unsupported address type for LocalNet %s\n", name);
freeaddrinfo(res);
return 1;
}
freeaddrinfo(res);
return 0;
}
static struct LOCALNET *localnet(char *name, char *mask) {
static struct LOCALNET *localnet(char *name, char *mask)
{
struct LOCALNET *l = (struct LOCALNET *)malloc(sizeof(*l));
uint32_t nmask;
unsigned int i;
if(!l) {
logg("!Out of memory while resolving LocalNet\n");
return NULL;
if (!l) {
logg("!Out of memory while resolving LocalNet\n");
return NULL;
}
if(resolve(name, &l->family, l->basehost)) {
free(l);
return NULL;
if (resolve(name, &l->family, l->basehost)) {
free(l);
return NULL;
}
if(l->family == NON_SMTP) {
l->mask[0] = l->mask[1] = l->mask[2] = l->mask[3] = 0x0;
return l;
if (l->family == NON_SMTP) {
l->mask[0] = l->mask[1] = l->mask[2] = l->mask[3] = 0x0;
return l;
}
if(!mask || !*mask) nmask = 32 + 96*(l->family == INET6_HOST);
else nmask = atoi(mask);
if (!mask || !*mask)
nmask = 32 + 96 * (l->family == INET6_HOST);
else
nmask = atoi(mask);
if((l->family == INET6_HOST && nmask > 128) || (l->family == INET_HOST && nmask > 32)) {
logg("!Bad netmask '/%s' for LocalNet %s\n", mask, name);
free(l);
return NULL;
if ((l->family == INET6_HOST && nmask > 128) || (l->family == INET_HOST && nmask > 32)) {
logg("!Bad netmask '/%s' for LocalNet %s\n", mask, name);
free(l);
return NULL;
}
l->mask[0] = l->mask[1] = l->mask[2] = l->mask[3] = 0;
for(i=0; i<nmask; i++)
l->mask[i>>5] |= 1<<(31-(i & 31));
for (i = 0; i < nmask; i++)
l->mask[i >> 5] |= 1 << (31 - (i & 31));
l->basehost[0] &= l->mask[0];
l->basehost[1] &= l->mask[1];
@ -430,95 +433,95 @@ static struct LOCALNET *localnet(char *name, char *mask) {
return l;
}
static int islocalnet(uint32_t family, uint32_t *host)
{
struct LOCALNET *l = lnet;
static int islocalnet(uint32_t family, uint32_t *host) {
struct LOCALNET* l = lnet;
if(!l) return 0;
while(l) {
if(
(l->family == family) &&
(l->basehost[0] == (host[0] & l->mask[0])) && (l->basehost[1] == (host[1] & l->mask[1])) &&
(l->basehost[2] == (host[2] & l->mask[2])) && (l->basehost[3] == (host[3] & l->mask[3]))
) return 1;
l=l->next;
if (!l) return 0;
while (l) {
if (
(l->family == family) &&
(l->basehost[0] == (host[0] & l->mask[0])) && (l->basehost[1] == (host[1] & l->mask[1])) &&
(l->basehost[2] == (host[2] & l->mask[2])) && (l->basehost[3] == (host[3] & l->mask[3]))) return 1;
l = l->next;
}
return 0;
}
int islocalnet_name(char *name) {
int islocalnet_name(char *name)
{
uint32_t host[4], family;
if(!lnet) return 0;
if(resolve(name, &family, host)) {
logg("*Cannot resolv %s\n", name);
return 0;
if (!lnet) return 0;
if (resolve(name, &family, host)) {
logg("*Cannot resolv %s\n", name);
return 0;
}
return islocalnet(family, host);
}
int islocalnet_sock(struct sockaddr *sa) {
int islocalnet_sock(struct sockaddr *sa)
{
uint32_t host[4], family;
if(!lnet) return 0;
if (!lnet) return 0;
if(sa->sa_family == AF_INET) {
struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
if (sa->sa_family == AF_INET) {
struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
family = INET_HOST;
host[0] = htonl(sa4->sin_addr.s_addr);
} else if(sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
unsigned int i, j;
uint32_t u = 0;
family = INET_HOST;
host[0] = htonl(sa4->sin_addr.s_addr);
} else if (sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
unsigned int i, j;
uint32_t u = 0;
family = INET6_HOST;
for(i=0, j=0; i<16; i++) {
u += (sa6->sin6_addr.s6_addr[i] << (8*j));
if(++j == 4) {
host[i>>2] = u;
j = u = 0;
}
}
} else return 0;
family = INET6_HOST;
for (i = 0, j = 0; i < 16; i++) {
u += (sa6->sin6_addr.s6_addr[i] << (8 * j));
if (++j == 4) {
host[i >> 2] = u;
j = u = 0;
}
}
} else
return 0;
return islocalnet(family, host);
}
void localnets_free(void)
{
while (lnet) {
struct LOCALNET *l = lnet->next;
void localnets_free(void) {
while(lnet) {
struct LOCALNET *l = lnet->next;
free(lnet);
lnet = l;
free(lnet);
lnet = l;
}
}
int localnets_init(struct optstruct *opts) {
int localnets_init(struct optstruct *opts)
{
const struct optstruct *opt;
if((opt = optget(opts, "LocalNet"))->enabled) {
while(opt) {
char *lnetname = opt->strarg;
struct LOCALNET *l;
char *mask = strrchr(lnetname, *PATHSEP);
if ((opt = optget(opts, "LocalNet"))->enabled) {
while (opt) {
char *lnetname = opt->strarg;
struct LOCALNET *l;
char *mask = strrchr(lnetname, *PATHSEP);
if(mask) {
*mask='\0';
mask++;
}
if(!strcasecmp(lnetname, "local")) lnetname = NULL;
if((l = localnet(lnetname, mask)) == NULL) {
localnets_free();
return 1;
}
l->next = lnet;
lnet = l;
opt = opt->nextarg;
}
if (mask) {
*mask = '\0';
mask++;
}
if (!strcasecmp(lnetname, "local")) lnetname = NULL;
if ((l = localnet(lnetname, mask)) == NULL) {
localnets_free();
return 1;
}
l->next = lnet;
lnet = l;
opt = opt->nextarg;
}
}
return 0;
}

View file

@ -37,181 +37,184 @@ struct WHLST {
};
struct WHLST *wfrom = NULL;
struct WHLST *wto = NULL;
struct WHLST *wto = NULL;
int skipauth = 0;
regex_t authreg;
void whitelist_free(void) {
void whitelist_free(void)
{
struct WHLST *w;
while(wfrom) {
w = wfrom->next;
cli_regfree(&wfrom->preg);
free(wfrom);
wfrom = w;
while (wfrom) {
w = wfrom->next;
cli_regfree(&wfrom->preg);
free(wfrom);
wfrom = w;
}
while(wto) {
w = wto->next;
cli_regfree(&wto->preg);
free(wto);
wto = w;
while (wto) {
w = wto->next;
cli_regfree(&wto->preg);
free(wto);
wto = w;
}
}
int whitelist_init(const char *fname) {
int whitelist_init(const char *fname)
{
char buf[2048];
FILE *f;
struct WHLST *w;
if(!(f = fopen(fname, "r"))) {
logg("!Cannot open whitelist file '%s'\n", fname);
return 1;
if (!(f = fopen(fname, "r"))) {
logg("!Cannot open whitelist file '%s'\n", fname);
return 1;
}
while(fgets(buf, sizeof(buf), f) != NULL) {
struct WHLST **addto = &wto;
char *ptr = buf;
int len;
while (fgets(buf, sizeof(buf), f) != NULL) {
struct WHLST **addto = &wto;
char *ptr = buf;
int len;
if(*buf == '#' || *buf == ':' || *buf == '!')
continue;
if (*buf == '#' || *buf == ':' || *buf == '!')
continue;
if(!strncasecmp("From:", buf, 5)) {
ptr+=5;
addto = &wfrom;
} else if (!strncasecmp("To:", buf, 3))
ptr+=3;
if (!strncasecmp("From:", buf, 5)) {
ptr += 5;
addto = &wfrom;
} else if (!strncasecmp("To:", buf, 3))
ptr += 3;
len = strlen(ptr) - 1;
for(;len>=0; len--) {
if(ptr[len] != '\n' && ptr[len] != '\r') break;
ptr[len] = '\0';
}
if(!len) continue;
if (!(w = (struct WHLST *)malloc(sizeof(*w)))) {
logg("!Out of memory loading whitelist file\n");
whitelist_free();
fclose(f);
return 1;
}
w->next = (*addto);
(*addto) = w;
if (cli_regcomp(&w->preg, ptr, REG_ICASE|REG_NOSUB)) {
logg("!Failed to compile regex '%s' in whitelist file\n", ptr);
whitelist_free();
fclose(f);
return 1;
}
len = strlen(ptr) - 1;
for (; len >= 0; len--) {
if (ptr[len] != '\n' && ptr[len] != '\r') break;
ptr[len] = '\0';
}
if (!len) continue;
if (!(w = (struct WHLST *)malloc(sizeof(*w)))) {
logg("!Out of memory loading whitelist file\n");
whitelist_free();
fclose(f);
return 1;
}
w->next = (*addto);
(*addto) = w;
if (cli_regcomp(&w->preg, ptr, REG_ICASE | REG_NOSUB)) {
logg("!Failed to compile regex '%s' in whitelist file\n", ptr);
whitelist_free();
fclose(f);
return 1;
}
}
fclose(f);
return 0;
}
int whitelisted(const char *addr, int from) {
int whitelisted(const char *addr, int from)
{
struct WHLST *w;
if(from) w = wfrom;
else w = wto;
if (from)
w = wfrom;
else
w = wto;
while(w) {
if(!cli_regexec(&w->preg, addr, 0, NULL, 0))
return 1;
w = w->next;
while (w) {
if (!cli_regexec(&w->preg, addr, 0, NULL, 0))
return 1;
w = w->next;
}
return 0;
}
int smtpauth_init(const char *r) {
int smtpauth_init(const char *r)
{
char *regex = NULL;
if(!strncmp(r, "file:", 5)) {
char buf[2048];
FILE *f = fopen(r+5, "r");
int rxsize = 0, rxavail = 0, rxused=0;
if (!strncmp(r, "file:", 5)) {
char buf[2048];
FILE *f = fopen(r + 5, "r");
int rxsize = 0, rxavail = 0, rxused = 0;
if(!f) {
logg("!Cannot open whitelist file '%s'\n", r+5);
return 1;
}
while(fgets(buf, sizeof(buf), f) != NULL) {
int len;
char *ptr;
if (!f) {
logg("!Cannot open whitelist file '%s'\n", r + 5);
return 1;
}
while (fgets(buf, sizeof(buf), f) != NULL) {
int len;
char *ptr;
if(*buf == '#' || *buf == ':' || *buf == '!')
continue;
len = strlen(buf) - 1;
for(;len>=0; len--) {
if(buf[len] != '\n' && buf[len] != '\r') break;
buf[len] = '\0';
}
if(len<=0) continue;
if(len*3+1 > rxavail) {
ptr = regex;
regex = realloc(regex, rxsize + 2048);
if(!regex) {
logg("!Cannot allocate memory for SkipAuthenticated file\n");
fclose(f);
return 1;
}
rxavail = 2048;
rxsize += 2048;
if(!ptr) {
regex[0] = '^';
regex[1] = '(';
rxavail -= 2;
rxused = 2;
}
}
ptr = buf;
while(*ptr) {
if((*ptr>='A' && *ptr<='Z') || (*ptr>='a' && *ptr<='z') || (*ptr>='0' && *ptr<='9') || *ptr=='@') {
regex[rxused] = *ptr;
rxused++;
rxavail--;
} else {
regex[rxused] = '[';
regex[rxused+1] = *ptr;
regex[rxused+2] = ']';
rxused += 3;
rxavail -= 3;
}
ptr++;
}
regex[rxused++] = '|';
rxavail--;
}
if(rxavail < 4 && !(regex = realloc(regex, rxsize + 4))) {
logg("!Cannot allocate memory for SkipAuthenticated file\n");
fclose(f);
return 1;
}
regex[rxused-1] = ')';
regex[rxused] = '$';
regex[rxused+1] = '\0';
r = regex;
fclose(f);
if (*buf == '#' || *buf == ':' || *buf == '!')
continue;
len = strlen(buf) - 1;
for (; len >= 0; len--) {
if (buf[len] != '\n' && buf[len] != '\r') break;
buf[len] = '\0';
}
if (len <= 0) continue;
if (len * 3 + 1 > rxavail) {
ptr = regex;
regex = realloc(regex, rxsize + 2048);
if (!regex) {
logg("!Cannot allocate memory for SkipAuthenticated file\n");
fclose(f);
return 1;
}
rxavail = 2048;
rxsize += 2048;
if (!ptr) {
regex[0] = '^';
regex[1] = '(';
rxavail -= 2;
rxused = 2;
}
}
ptr = buf;
while (*ptr) {
if ((*ptr >= 'A' && *ptr <= 'Z') || (*ptr >= 'a' && *ptr <= 'z') || (*ptr >= '0' && *ptr <= '9') || *ptr == '@') {
regex[rxused] = *ptr;
rxused++;
rxavail--;
} else {
regex[rxused] = '[';
regex[rxused + 1] = *ptr;
regex[rxused + 2] = ']';
rxused += 3;
rxavail -= 3;
}
ptr++;
}
regex[rxused++] = '|';
rxavail--;
}
if (rxavail < 4 && !(regex = realloc(regex, rxsize + 4))) {
logg("!Cannot allocate memory for SkipAuthenticated file\n");
fclose(f);
return 1;
}
regex[rxused - 1] = ')';
regex[rxused] = '$';
regex[rxused + 1] = '\0';
r = regex;
fclose(f);
}
if(cli_regcomp(&authreg, r, REG_ICASE|REG_NOSUB|REG_EXTENDED)) {
logg("!Failed to compile regex '%s' for SkipAuthenticated\n", r);
if(regex) free(regex);
return 1;
if (cli_regcomp(&authreg, r, REG_ICASE | REG_NOSUB | REG_EXTENDED)) {
logg("!Failed to compile regex '%s' for SkipAuthenticated\n", r);
if (regex) free(regex);
return 1;
}
if(regex) free(regex);
if (regex) free(regex);
skipauth = 1;
return 0;
}
int smtpauthed(const char *login) {
if(skipauth && !cli_regexec(&authreg, login, 0, NULL, 0))
return 1;
int smtpauthed(const char *login)
{
if (skipauth && !cli_regexec(&authreg, login, 0, NULL, 0))
return 1;
return 0;
}
/*
* Local Variables:
* mode: c

View file

@ -85,37 +85,37 @@ static void tracehook(struct cli_bc_ctx *ctx, unsigned event)
{
dbg_state.directory = ctx->directory;
if (*ctx->file == '?')
return;
return;
switch (event) {
case trace_func:
fprintf(stderr, "[trace] %s:%u:%u -> %s:%u:%u Entered function %s\n",
dbg_state.file, dbg_state.line, dbg_state.col,
ctx->file, ctx->line, ctx->col, ctx->scope);
dbg_state.scope = ctx->scope;
break;
case trace_param:
fprintf(stderr, "[trace] function parameter:\n");
return;
case trace_scope:
fprintf(stderr, "[trace] %s:%u:%u -> %s:%u:%u\n",
dbg_state.file, dbg_state.line, dbg_state.col,
ctx->file, ctx->line, ctx->col);
dbg_state.scope = ctx->scope;
break;
case trace_line:
case trace_col:
if (dbg_state.showline)
cli_bytecode_debug_printsrc(ctx);
else
fprintf(stderr, "[trace] %s:%u:%u\n",
dbg_state.file, dbg_state.line, dbg_state.col);
break;
default:
break;
case trace_func:
fprintf(stderr, "[trace] %s:%u:%u -> %s:%u:%u Entered function %s\n",
dbg_state.file, dbg_state.line, dbg_state.col,
ctx->file, ctx->line, ctx->col, ctx->scope);
dbg_state.scope = ctx->scope;
break;
case trace_param:
fprintf(stderr, "[trace] function parameter:\n");
return;
case trace_scope:
fprintf(stderr, "[trace] %s:%u:%u -> %s:%u:%u\n",
dbg_state.file, dbg_state.line, dbg_state.col,
ctx->file, ctx->line, ctx->col);
dbg_state.scope = ctx->scope;
break;
case trace_line:
case trace_col:
if (dbg_state.showline)
cli_bytecode_debug_printsrc(ctx);
else
fprintf(stderr, "[trace] %s:%u:%u\n",
dbg_state.file, dbg_state.line, dbg_state.col);
break;
default:
break;
}
dbg_state.file = ctx->file;
dbg_state.line = ctx->line;
dbg_state.col = ctx->col;
dbg_state.col = ctx->col;
}
static void tracehook_op(struct cli_bc_ctx *ctx, const char *op)
@ -139,44 +139,44 @@ static void tracehook_ptr(struct cli_bc_ctx *ctx, const void *ptr)
static uint8_t debug_flag = 0;
static void print_src(const char *file)
{
char buf[4096];
int nread, i, found = 0, lcnt = 0;
FILE *f = fopen(file, "r");
if (!f) {
fprintf(stderr,"Unable to reopen %s\n", file);
return;
}
do {
nread = fread(buf, 1, sizeof(buf), f);
for (i=0;i<nread-1;i++) {
if (buf[i] == '\n') {
lcnt++;
}
/* skip over the logical trigger */
if (lcnt >= 2 && buf[i] == '\n' && buf[i+1] == 'S') {
found = 1;
i+=2;
break;
}
char buf[4096];
int nread, i, found = 0, lcnt = 0;
FILE *f = fopen(file, "r");
if (!f) {
fprintf(stderr, "Unable to reopen %s\n", file);
return;
}
} while (!found && (nread == sizeof(buf)));
if (debug_flag)
printf("[clambc] Source code:");
do {
for (;i+1<nread;i++) {
if (buf[i] == 'S' || buf[i] == '\n') {
putc('\n', stdout);
continue;
}
putc(((buf[i]&0xf) | ((buf[i+1]&0xf)<<4)), stdout);
i++;
}
if (i == nread-1 && nread != 1)
fseek(f, -1, SEEK_CUR);
i=0;
nread = fread(buf, 1, sizeof(buf), f);
} while (nread > 0);
fclose(f);
do {
nread = fread(buf, 1, sizeof(buf), f);
for (i = 0; i < nread - 1; i++) {
if (buf[i] == '\n') {
lcnt++;
}
/* skip over the logical trigger */
if (lcnt >= 2 && buf[i] == '\n' && buf[i + 1] == 'S') {
found = 1;
i += 2;
break;
}
}
} while (!found && (nread == sizeof(buf)));
if (debug_flag)
printf("[clambc] Source code:");
do {
for (; i + 1 < nread; i++) {
if (buf[i] == 'S' || buf[i] == '\n') {
putc('\n', stdout);
continue;
}
putc(((buf[i] & 0xf) | ((buf[i + 1] & 0xf) << 4)), stdout);
i++;
}
if (i == nread - 1 && nread != 1)
fseek(f, -1, SEEK_CUR);
i = 0;
nread = fread(buf, 1, sizeof(buf), f);
} while (nread > 0);
fclose(f);
}
static uint32_t deadbeefcounts[64] = {
0xdeadbeef,
@ -249,102 +249,102 @@ int main(int argc, char *argv[])
FILE *f;
struct cli_bc *bc;
struct cli_bc_ctx *ctx;
int rc, dbgargc, bc_stats=0;
int rc, dbgargc, bc_stats = 0;
struct optstruct *opts;
const struct optstruct *opt;
unsigned funcid=0, i;
unsigned funcid = 0, i;
struct cli_all_bc bcs;
int fd = -1;
unsigned tracelevel;
if(check_flevel())
exit(1);
if (check_flevel())
exit(1);
opts = optparse(NULL, argc, argv, 1, OPT_CLAMBC, 0, NULL);
if (!opts) {
fprintf(stderr, "ERROR: Can't parse command line options\n");
exit(1);
fprintf(stderr, "ERROR: Can't parse command line options\n");
exit(1);
}
if(optget(opts, "version")->enabled) {
printf("Clam AntiVirus Bytecode Testing Tool %s\n", get_version());
cl_init(CL_INIT_DEFAULT);
cli_bytecode_printversion();
optfree(opts);
exit(0);
if (optget(opts, "version")->enabled) {
printf("Clam AntiVirus Bytecode Testing Tool %s\n", get_version());
cl_init(CL_INIT_DEFAULT);
cli_bytecode_printversion();
optfree(opts);
exit(0);
}
if(optget(opts, "help")->enabled || !opts->filename) {
optfree(opts);
help();
exit(0);
if (optget(opts, "help")->enabled || !opts->filename) {
optfree(opts);
help();
exit(0);
}
f = fopen(opts->filename[0], "r");
if (!f) {
fprintf(stderr, "Unable to load %s\n", argv[1]);
optfree(opts);
exit(2);
fprintf(stderr, "Unable to load %s\n", argv[1]);
optfree(opts);
exit(2);
}
bc = malloc(sizeof(*bc));
if (!bc) {
fprintf(stderr, "Out of memory\n");
optfree(opts);
exit(3);
fprintf(stderr, "Out of memory\n");
optfree(opts);
exit(3);
}
if (optget(opts,"debug")->enabled) {
cl_debug();
debug_flag=1;
if (optget(opts, "debug")->enabled) {
cl_debug();
debug_flag = 1;
}
rc = cl_init(CL_INIT_DEFAULT);
if (rc != CL_SUCCESS) {
fprintf(stderr,"Unable to init libclamav: %s\n", cl_strerror(rc));
optfree(opts);
exit(4);
fprintf(stderr, "Unable to init libclamav: %s\n", cl_strerror(rc));
optfree(opts);
exit(4);
}
dbgargc=1;
dbgargc = 1;
while (opts->filename[dbgargc]) dbgargc++;
if (dbgargc > 1)
cli_bytecode_debug(dbgargc, opts->filename);
cli_bytecode_debug(dbgargc, opts->filename);
if (optget(opts, "force-interpreter")->enabled) {
bcs.engine = NULL;
bcs.engine = NULL;
} else {
rc = cli_bytecode_init(&bcs);
if (rc != CL_SUCCESS) {
fprintf(stderr,"Unable to init bytecode engine: %s\n", cl_strerror(rc));
optfree(opts);
exit(4);
}
rc = cli_bytecode_init(&bcs);
if (rc != CL_SUCCESS) {
fprintf(stderr, "Unable to init bytecode engine: %s\n", cl_strerror(rc));
optfree(opts);
exit(4);
}
}
bcs.all_bcs = bc;
bcs.count = 1;
bcs.count = 1;
if((opt = optget(opts, "statistics"))->enabled) {
while(opt) {
if (!strcasecmp(opt->strarg, "bytecode"))
bc_stats=1;
opt = opt->nextarg;
if ((opt = optget(opts, "statistics"))->enabled) {
while (opt) {
if (!strcasecmp(opt->strarg, "bytecode"))
bc_stats = 1;
opt = opt->nextarg;
}
}
rc = cli_bytecode_load(bc, f, NULL, optget(opts, "trust-bytecode")->enabled, bc_stats);
if (rc != CL_SUCCESS) {
fprintf(stderr,"Unable to load bytecode: %s\n", cl_strerror(rc));
optfree(opts);
exit(4);
fprintf(stderr, "Unable to load bytecode: %s\n", cl_strerror(rc));
optfree(opts);
exit(4);
}
fclose(f);
if (bc->state == bc_skip) {
fprintf(stderr,"bytecode load skipped\n");
exit(0);
fprintf(stderr, "bytecode load skipped\n");
exit(0);
}
if (debug_flag)
printf("[clambc] Bytecode loaded\n");
printf("[clambc] Bytecode loaded\n");
if (optget(opts, "info")->enabled) {
cli_bytecode_describe(bc);
cli_bytecode_describe(bc);
} else if (optget(opts, "printsrc")->enabled) {
print_src(opts->filename[0]);
} else if (optget(opts, "printbcir")->enabled) {
@ -352,119 +352,119 @@ int main(int argc, char *argv[])
cli_bytevalue_describe(bc, 0);
cli_bytefunc_describe(bc, 0);
} else {
cli_ctx cctx;
struct cl_engine *engine = cl_engine_new();
fmap_t *map = NULL;
memset(&cctx, 0, sizeof(cctx));
if (!engine) {
fprintf(stderr,"Unable to create engine\n");
optfree(opts);
exit(3);
}
rc = cl_engine_compile(engine);
if (rc) {
fprintf(stderr,"Unable to compile engine: %s\n", cl_strerror(rc));
optfree(opts);
exit(4);
}
rc = cli_bytecode_prepare2(engine, &bcs, BYTECODE_ENGINE_MASK);
if (rc != CL_SUCCESS) {
fprintf(stderr,"Unable to prepare bytecode: %s\n", cl_strerror(rc));
optfree(opts);
exit(4);
}
if (debug_flag)
printf("[clambc] Bytecode prepared\n");
cli_ctx cctx;
struct cl_engine *engine = cl_engine_new();
fmap_t *map = NULL;
memset(&cctx, 0, sizeof(cctx));
if (!engine) {
fprintf(stderr, "Unable to create engine\n");
optfree(opts);
exit(3);
}
rc = cl_engine_compile(engine);
if (rc) {
fprintf(stderr, "Unable to compile engine: %s\n", cl_strerror(rc));
optfree(opts);
exit(4);
}
rc = cli_bytecode_prepare2(engine, &bcs, BYTECODE_ENGINE_MASK);
if (rc != CL_SUCCESS) {
fprintf(stderr, "Unable to prepare bytecode: %s\n", cl_strerror(rc));
optfree(opts);
exit(4);
}
if (debug_flag)
printf("[clambc] Bytecode prepared\n");
ctx = cli_bytecode_context_alloc();
if (!ctx) {
fprintf(stderr,"Out of memory\n");
exit(3);
}
ctx->ctx = &cctx;
cctx.engine = engine;
cctx.fmap = cli_calloc(sizeof(fmap_t*), engine->maxreclevel+2);
if (!cctx.fmap) {
fprintf(stderr,"Out of memory\n");
exit(3);
}
memset(&dbg_state, 0, sizeof(dbg_state));
dbg_state.file = "<libclamav>";
dbg_state.line = 0;
dbg_state.col = 0;
dbg_state.showline = !optget(opts, "no-trace-showsource")->enabled;
tracelevel = optget(opts, "trace")->numarg;
cli_bytecode_context_set_trace(ctx, tracelevel,
tracehook,
tracehook_op,
tracehook_val,
tracehook_ptr);
ctx = cli_bytecode_context_alloc();
if (!ctx) {
fprintf(stderr, "Out of memory\n");
exit(3);
}
ctx->ctx = &cctx;
cctx.engine = engine;
cctx.fmap = cli_calloc(sizeof(fmap_t *), engine->maxreclevel + 2);
if (!cctx.fmap) {
fprintf(stderr, "Out of memory\n");
exit(3);
}
memset(&dbg_state, 0, sizeof(dbg_state));
dbg_state.file = "<libclamav>";
dbg_state.line = 0;
dbg_state.col = 0;
dbg_state.showline = !optget(opts, "no-trace-showsource")->enabled;
tracelevel = optget(opts, "trace")->numarg;
cli_bytecode_context_set_trace(ctx, tracelevel,
tracehook,
tracehook_op,
tracehook_val,
tracehook_ptr);
if (opts->filename[1]) {
funcid = atoi(opts->filename[1]);
}
cli_bytecode_context_setfuncid(ctx, bc, funcid);
if (debug_flag)
printf("[clambc] Running bytecode function :%u\n", funcid);
if (opts->filename[1]) {
funcid = atoi(opts->filename[1]);
}
cli_bytecode_context_setfuncid(ctx, bc, funcid);
if (debug_flag)
printf("[clambc] Running bytecode function :%u\n", funcid);
if (opts->filename[1]) {
i=2;
while (opts->filename[i]) {
rc = cli_bytecode_context_setparam_int(ctx, i-2, atoi(opts->filename[i]));
if (rc != CL_SUCCESS) {
fprintf(stderr,"Unable to set param %u: %s\n", i-2, cl_strerror(rc));
}
i++;
}
}
if (opts->filename[1]) {
i = 2;
while (opts->filename[i]) {
rc = cli_bytecode_context_setparam_int(ctx, i - 2, atoi(opts->filename[i]));
if (rc != CL_SUCCESS) {
fprintf(stderr, "Unable to set param %u: %s\n", i - 2, cl_strerror(rc));
}
i++;
}
}
if ((opt = optget(opts,"input"))->enabled) {
fd = open(opt->strarg, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "Unable to open input file %s: %s\n", opt->strarg, strerror(errno));
optfree(opts);
exit(5);
}
map = fmap(fd, 0, 0);
if (!map) {
fprintf(stderr, "Unable to map input file %s\n", opt->strarg);
exit(5);
}
rc = cli_bytecode_context_setfile(ctx, map);
if (rc != CL_SUCCESS) {
fprintf(stderr, "Unable to set file %s: %s\n", opt->strarg, cl_strerror(rc));
optfree(opts);
exit(5);
}
}
/* for testing */
ctx->hooks.match_counts = deadbeefcounts;
ctx->hooks.match_offsets = deadbeefcounts;
rc = cli_bytecode_run(&bcs, bc, ctx);
if (rc != CL_SUCCESS) {
fprintf(stderr,"Unable to run bytecode: %s\n", cl_strerror(rc));
} else {
uint64_t v;
if (debug_flag)
printf("[clambc] Bytecode run finished\n");
v = cli_bytecode_context_getresult_int(ctx);
if (debug_flag)
printf("[clambc] Bytecode returned: 0x%llx\n", (long long)v);
}
cli_bytecode_context_destroy(ctx);
if (map)
funmap(map);
cl_engine_free(engine);
free(cctx.fmap);
if ((opt = optget(opts, "input"))->enabled) {
fd = open(opt->strarg, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "Unable to open input file %s: %s\n", opt->strarg, strerror(errno));
optfree(opts);
exit(5);
}
map = fmap(fd, 0, 0);
if (!map) {
fprintf(stderr, "Unable to map input file %s\n", opt->strarg);
exit(5);
}
rc = cli_bytecode_context_setfile(ctx, map);
if (rc != CL_SUCCESS) {
fprintf(stderr, "Unable to set file %s: %s\n", opt->strarg, cl_strerror(rc));
optfree(opts);
exit(5);
}
}
/* for testing */
ctx->hooks.match_counts = deadbeefcounts;
ctx->hooks.match_offsets = deadbeefcounts;
rc = cli_bytecode_run(&bcs, bc, ctx);
if (rc != CL_SUCCESS) {
fprintf(stderr, "Unable to run bytecode: %s\n", cl_strerror(rc));
} else {
uint64_t v;
if (debug_flag)
printf("[clambc] Bytecode run finished\n");
v = cli_bytecode_context_getresult_int(ctx);
if (debug_flag)
printf("[clambc] Bytecode returned: 0x%llx\n", (long long)v);
}
cli_bytecode_context_destroy(ctx);
if (map)
funmap(map);
cl_engine_free(engine);
free(cctx.fmap);
}
cli_bytecode_destroy(bc);
cli_bytecode_done(&bcs);
free(bc);
optfree(opts);
if (fd != -1)
close(fd);
close(fd);
if (debug_flag)
printf("[clambc] Exiting\n");
printf("[clambc] Exiting\n");
cl_cleanup_crypto();
return 0;
}

View file

@ -59,140 +59,140 @@ static struct _cfgfile {
const char *name;
int tool;
} cfgfile[] = {
{ "clamd.conf", OPT_CLAMD },
{ "freshclam.conf", OPT_FRESHCLAM },
{ "clamav-milter.conf", OPT_MILTER },
{ NULL, 0 }
};
{"clamd.conf", OPT_CLAMD},
{"freshclam.conf", OPT_FRESHCLAM},
{"clamav-milter.conf", OPT_MILTER},
{NULL, 0}};
static void printopts(struct optstruct *opts, int nondef)
{
const struct optstruct *opt;
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;
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_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;
case CLOPT_TYPE_BOOL:
printf("%s = \"yes\"\n", opts->name);
break;
default:
printf("!!! %s: UNKNOWN INTERNAL TYPE !!!\n", opts->name);
}
opts = opts->next;
default:
printf("!!! %s: UNKNOWN INTERNAL TYPE !!!\n", opts->name);
}
opts = opts->next;
}
}
static int printconf(const char *name)
{
int i, j, tool = 0, tokens_count;
char buffer[1025];
const char *tokens[128];
const struct clam_option *cpt;
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;
}
for (i = 0; cfgfile[i].name; i++) {
if (!strcmp(name, cfgfile[i].name)) {
tool = cfgfile[i].tool;
break;
}
}
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;
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;
}
printf("##\n## %s - automatically generated by clamconf "VERSION"\n##\n", name);
printf("##\n## %s - automatically generated by clamconf " VERSION "\n##\n", name);
printf("\n# Comment out or remove the line below.\nExample\n");
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]);
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;
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_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_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;
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);
}
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");
}
}
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");
}
}
}
return 0;
@ -218,17 +218,17 @@ static void print_platform(struct cli_environment *env)
{
printf("\nPlatform information\n--------------------\n");
printf("uname: %s %s %s %s\n",
env->sysname, env->release, env->version, env->machine);
env->sysname, env->release, env->version, env->machine);
printf("OS: "TARGET_OS_TYPE", ARCH: "TARGET_ARCH_TYPE", CPU: "TARGET_CPU_TYPE"\n");
printf("OS: " TARGET_OS_TYPE ", ARCH: " TARGET_ARCH_TYPE ", CPU: " TARGET_CPU_TYPE "\n");
#ifdef C_LINUX
if (!access("/usr/bin/lsb_release", X_OK)) {
fputs("Full OS version: ", stdout);
fflush(stdout);
if (system("/usr/bin/lsb_release -d -s") == -1) {
perror("failed to determine");
}
fputs("Full OS version: ", stdout);
fflush(stdout);
if (system("/usr/bin/lsb_release -d -s") == -1) {
perror("failed to determine");
}
}
#else
/* e.g. Solaris */
@ -245,24 +245,24 @@ static void print_platform(struct cli_environment *env)
#endif
if (strcmp(ZLIB_VERSION, zlibVersion()))
printf("WARNING: zlib version mismatch: %s (%s)\n", ZLIB_VERSION, zlibVersion());
printf("WARNING: zlib version mismatch: %s (%s)\n", ZLIB_VERSION, zlibVersion());
#ifdef ZLIB_VERNUM
printf("zlib version: %s (%s), compile flags: %02lx\n",
ZLIB_VERSION, zlibVersion(), zlibCompileFlags());
ZLIB_VERSION, zlibVersion(), zlibCompileFlags());
#else
/* old zlib w/o zlibCompileFlags() */
printf("zlib version: %s (%s)\n",
ZLIB_VERSION, zlibVersion());
ZLIB_VERSION, zlibVersion());
#endif
if (env->triple[0])
printf("Triple: %s\n", env->triple);
printf("Triple: %s\n", env->triple);
if (env->cpu[0])
printf("CPU: %s, %s\n", env->cpu, env->big_endian ? "Big-endian" : "Little-endian");
printf("CPU: %s, %s\n", env->cpu, env->big_endian ? "Big-endian" : "Little-endian");
printf("platform id: 0x%08x%08x%08x\n",
env->platform_id_a,
env->platform_id_b,
env->platform_id_c);
env->platform_id_a,
env->platform_id_b,
env->platform_id_c);
}
static void print_build(struct cli_environment *env)
@ -272,95 +272,95 @@ static void print_build(struct cli_environment *env)
printf("\nBuild information\n-----------------\n");
/* Try to print information about some commonly used compilers */
#ifdef __GNUC__
version = __VERSION__;
version = __VERSION__;
#endif
switch (env->compiler) {
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;
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;
}
if (name)
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);
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);
cli_printcxxver();
#if defined(BUILD_CPPFLAGS) && defined(BUILD_CFLAGS) && defined(BUILD_CXXFLAGS) && defined(BUILD_LDFLAGS) && defined(BUILD_CONFIGURE_FLAGS)
printf("CPPFLAGS: %s\nCFLAGS: %s\nCXXFLAGS: %s\nLDFLAGS: %s\nConfigure: %s\n",
BUILD_CPPFLAGS, BUILD_CFLAGS, BUILD_CXXFLAGS, BUILD_LDFLAGS,
BUILD_CONFIGURE_FLAGS);
BUILD_CPPFLAGS, BUILD_CFLAGS, BUILD_CXXFLAGS, BUILD_LDFLAGS,
BUILD_CONFIGURE_FLAGS);
#endif
printf("sizeof(void*) = %d\n", env->sizeof_ptr);
printf("Engine flevel: %d, dconf: %d\n",
env->functionality_level,
env->dconf_level);
env->functionality_level,
env->dconf_level);
}
static void print_dbs(const char *dir)
{
DIR *dd;
struct dirent *dent;
char *dbfile;
unsigned int flevel = cl_retflevel(), cnt, sigs = 0;
struct cl_cvd *cvd;
DIR *dd;
struct dirent *dent;
char *dbfile;
unsigned int flevel = cl_retflevel(), cnt, sigs = 0;
struct cl_cvd *cvd;
if((dd = opendir(dir)) == NULL) {
if ((dd = opendir(dir)) == NULL) {
printf("print_dbs: Can't open directory %s\n", dir);
return;
}
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);
}
}
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);
}
}
}
closedir(dd);
printf("Total number of signatures: %u\n", sigs);
@ -368,135 +368,135 @@ static void print_dbs(const char *dir)
int main(int argc, char **argv)
{
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;
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;
opts = optparse(NULL, argc, argv, 1, OPT_CLAMCONF, 0, NULL);
if(!opts) {
printf("ERROR: Can't parse command line options\n");
return 1;
if (!opts) {
printf("ERROR: Can't parse command line options\n");
return 1;
}
if(optget(opts, "help")->enabled) {
help();
optfree(opts);
return 0;
if (optget(opts, "help")->enabled) {
help();
optfree(opts);
return 0;
}
if(optget(opts, "version")->enabled) {
printf("Clam AntiVirus Configuration Tool %s\n", get_version());
optfree(opts);
return 0;
if (optget(opts, "version")->enabled) {
printf("Clam AntiVirus Configuration Tool %s\n", get_version());
optfree(opts);
return 0;
}
if((opt = optget(opts, "generate-config"))->enabled) {
printconf(opt->strarg);
optfree(opts);
return 0;
if ((opt = optget(opts, "generate-config"))->enabled) {
printconf(opt->strarg);
optfree(opts);
return 0;
}
dbdir[0] = 0;
dbdir[0] = 0;
clamd_dbdir[0] = 0;
dir = optget(opts, "config-dir")->strarg;
dir = optget(opts, "config-dir")->strarg;
printf("Checking configuration files in %s\n", dir);
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);
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);
}
optfree(opts);
printf("\nSoftware settings\n-----------------\n");
printf("Version: %s\n", cl_retver());
if(strcmp(cl_retver(), get_version()))
printf("WARNING: Version mismatch: libclamav=%s, clamconf=%s\n", cl_retver(), get_version());
if (strcmp(cl_retver(), get_version()))
printf("WARNING: Version mismatch: libclamav=%s, clamconf=%s\n", cl_retver(), get_version());
cl_init(CL_INIT_DEFAULT);
printf("Optional features supported: ");
#ifdef USE_MPOOL
printf("MEMPOOL ");
printf("MEMPOOL ");
#endif
#ifdef SUPPORT_IPv6
printf("IPv6 ");
printf("IPv6 ");
#endif
#ifdef CLAMUKO
printf("CLAMUKO ");
printf("CLAMUKO ");
#endif
#ifdef C_BIGSTACK
printf("BIGSTACK ");
printf("BIGSTACK ");
#endif
#ifdef FRESHCLAM_DNS_FIX
printf("FRESHCLAM_DNS_FIX ");
printf("FRESHCLAM_DNS_FIX ");
#endif
#ifndef _WIN32
if (get_fpu_endian() != FPU_ENDIAN_UNKNOWN)
if (get_fpu_endian() != FPU_ENDIAN_UNKNOWN)
#endif
printf("AUTOIT_EA06 ");
printf("AUTOIT_EA06 ");
#ifdef HAVE_BZLIB_H
printf("BZIP2 ");
printf("BZIP2 ");
#endif
#ifdef HAVE_LIBXML2
printf("LIBXML2 ");
printf("LIBXML2 ");
#endif
#ifdef HAVE_PCRE
#if USING_PCRE2
printf("PCRE2 ");
printf("PCRE2 ");
#else
printf("PCRE ");
printf("PCRE ");
#endif
#endif
#ifdef HAVE_ICONV
printf("ICONV ");
printf("ICONV ");
#endif
#ifdef HAVE_JSON
printf("JSON ");
printf("JSON ");
#endif
if(have_rar)
printf("RAR ");
if (have_rar)
printf("RAR ");
if (have_clamjit)
printf("JIT");
printf("JIT");
printf("\n");
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;
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;
}
printf("\nDatabase information\n--------------------\n");
printf("Database directory: %s\n", dbdir);
if(strcmp(dbdir, clamd_dbdir))
printf("WARNING: freshclam.conf and clamd.conf point to different database directories\n");
if (strcmp(dbdir, clamd_dbdir))
printf("WARNING: freshclam.conf and clamd.conf point to different database directories\n");
print_dbs(dbdir);
cli_detect_environment(&env);

View file

@ -118,7 +118,7 @@ int main(int argc, char **argv)
{
static struct cl_engine *engine = NULL;
const struct optstruct *opt;
#ifndef _WIN32
#ifndef _WIN32
struct passwd *user = NULL;
struct sigaction sa;
struct rlimit rlim;
@ -127,8 +127,8 @@ int main(int argc, char **argv)
const char *dbdir, *cfgfile;
char *pua_cats = NULL, *pt;
int ret, tcpsock = 0, localsock = 0, min_port, max_port;
unsigned int sigs = 0;
int *lsockets=NULL;
unsigned int sigs = 0;
int *lsockets = NULL;
unsigned int nlsockets = 0;
unsigned int dboptions = 0;
unsigned int i;
@ -138,7 +138,7 @@ int main(int argc, char **argv)
STATBUF sb;
#endif
if(check_flevel())
if (check_flevel())
exit(1);
#ifndef _WIN32
@ -148,45 +148,39 @@ int main(int argc, char **argv)
sigaction(SIGUSR2, &sa, NULL);
#endif
if((opts = optparse(NULL, argc, argv, 1, OPT_CLAMD, 0, NULL)) == NULL) {
if ((opts = optparse(NULL, argc, argv, 1, OPT_CLAMD, 0, NULL)) == NULL) {
mprintf("!Can't parse command line options\n");
return 1;
}
if(optget(opts, "help")->enabled) {
if (optget(opts, "help")->enabled) {
help();
optfree(opts);
return 0;
}
if(optget(opts, "debug")->enabled) {
if (optget(opts, "debug")->enabled) {
#if defined(C_LINUX)
/* njh@bandsman.co.uk: create a dump if needed */
rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
if(setrlimit(RLIMIT_CORE, &rlim) < 0)
if (setrlimit(RLIMIT_CORE, &rlim) < 0)
perror("setrlimit");
#endif
debug_mode = 1;
}
/* check foreground option from command line to override config file */
for(j = 0; j < argc; j += 1)
{
if ((memcmp(argv[j], "--foreground", 12) == 0) || (memcmp(argv[j], "-F", 2) == 0))
{
for (j = 0; j < argc; j += 1) {
if ((memcmp(argv[j], "--foreground", 12) == 0) || (memcmp(argv[j], "-F", 2) == 0)) {
/* found */
break;
}
}
if (j < argc)
{
if(optget(opts, "Foreground")->enabled)
{
if (j < argc) {
if (optget(opts, "Foreground")->enabled) {
foreground = 1;
}
else
{
} else {
foreground = 0;
}
}
@ -195,19 +189,19 @@ int main(int argc, char **argv)
/* parse the config file */
cfgfile = optget(opts, "config-file")->strarg;
pt = strdup(cfgfile);
pt = strdup(cfgfile);
if (pt == NULL) {
fprintf(stderr, "ERROR: Unable to allocate memory for config file\n");
return 1;
fprintf(stderr, "ERROR: Unable to allocate memory for config file\n");
return 1;
}
if((opts = optparse(cfgfile, 0, NULL, 1, OPT_CLAMD, 0, opts)) == NULL) {
if ((opts = optparse(cfgfile, 0, NULL, 1, OPT_CLAMD, 0, opts)) == NULL) {
fprintf(stderr, "ERROR: Can't open/parse the config file %s\n", pt);
free(pt);
return 1;
}
free(pt);
if(optget(opts, "version")->enabled) {
if (optget(opts, "version")->enabled) {
print_version(optget(opts, "DatabaseDirectory")->strarg);
optfree(opts);
return 0;
@ -215,35 +209,35 @@ int main(int argc, char **argv)
/* drop privileges */
#ifndef _WIN32
if(geteuid() == 0 && (opt = optget(opts, "User"))->enabled) {
if((user = getpwnam(opt->strarg)) == NULL) {
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);
return 1;
}
#ifdef HAVE_INITGROUPS
if(initgroups(opt->strarg, user->pw_gid)) {
fprintf(stderr, "ERROR: initgroups() failed.\n");
optfree(opts);
return 1;
}
if (initgroups(opt->strarg, user->pw_gid)) {
fprintf(stderr, "ERROR: initgroups() failed.\n");
optfree(opts);
return 1;
}
#elif HAVE_SETGROUPS
if(setgroups(1, &user->pw_gid)) {
fprintf(stderr, "ERROR: setgroups() failed.\n");
optfree(opts);
return 1;
}
if (setgroups(1, &user->pw_gid)) {
fprintf(stderr, "ERROR: setgroups() failed.\n");
optfree(opts);
return 1;
}
#endif
if(setgid(user->pw_gid)) {
fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid);
if (setgid(user->pw_gid)) {
fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int)user->pw_gid);
optfree(opts);
return 1;
}
if(setuid(user->pw_uid)) {
fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid);
if (setuid(user->pw_uid)) {
fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int)user->pw_uid);
optfree(opts);
return 1;
}
@ -251,26 +245,26 @@ int main(int argc, char **argv)
#endif
/* initialize logger */
logg_lock = !optget(opts, "LogFileUnlock")->enabled;
logg_time = optget(opts, "LogTime")->enabled;
logok = optget(opts, "LogClean")->enabled;
logg_size = optget(opts, "LogFileMaxSize")->numarg;
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;
if (logg_size)
logg_rotate = optget(opts, "LogRotate")->enabled;
mprintf_send_timeout = optget(opts, "SendBufTimeout")->numarg;
do { /* logger initialized */
if((opt = optget(opts, "LogFile"))->enabled) {
if ((opt = optget(opts, "LogFile"))->enabled) {
char timestr[32];
logg_file = opt->strarg;
if(!cli_is_abspath(logg_file)) {
if (!cli_is_abspath(logg_file)) {
fprintf(stderr, "ERROR: LogFile requires full path.\n");
ret = 1;
break;
}
time(&currtime);
if(logg("#+++ Started at %s", cli_ctime(&currtime, timestr, sizeof(timestr)))) {
if (logg("#+++ Started at %s", cli_ctime(&currtime, timestr, sizeof(timestr)))) {
fprintf(stderr, "ERROR: Can't initialize the internal logger\n");
ret = 1;
break;
@ -279,27 +273,27 @@ int main(int argc, char **argv)
logg_file = NULL;
}
if (optget(opts,"DevLiblog")->enabled)
if (optget(opts, "DevLiblog")->enabled)
cl_set_clcb_msg(msg_callback);
if((ret = cl_init(CL_INIT_DEFAULT))) {
if ((ret = cl_init(CL_INIT_DEFAULT))) {
logg("!Can't initialize libclamav: %s\n", cl_strerror(ret));
ret = 1;
break;
}
if(optget(opts, "Debug")->enabled) {
if (optget(opts, "Debug")->enabled) {
/* enable debug messages in libclamav */
cl_debug();
logg_verbose = 2;
}
#if defined(USE_SYSLOG) && !defined(C_AIX)
if(optget(opts, "LogSyslog")->enabled) {
if (optget(opts, "LogSyslog")->enabled) {
int fac = LOG_LOCAL6;
opt = optget(opts, "LogFacility");
if((fac = logg_facility(opt->strarg)) == -1) {
if ((fac = logg_facility(opt->strarg)) == -1) {
logg("!LogFacility: %s: No such facility.\n", opt->strarg);
ret = 1;
break;
@ -312,53 +306,52 @@ int main(int argc, char **argv)
#ifdef C_LINUX
procdev = 0;
if(CLAMSTAT("/proc", &sb) != -1 && !sb.st_size)
if (CLAMSTAT("/proc", &sb) != -1 && !sb.st_size)
procdev = sb.st_dev;
#endif
/* check socket type */
if(optget(opts, "TCPSocket")->enabled)
if (optget(opts, "TCPSocket")->enabled)
tcpsock = 1;
if(optget(opts, "LocalSocket")->enabled)
if (optget(opts, "LocalSocket")->enabled)
localsock = 1;
logg("#Received %d file descriptor(s) from systemd.\n", num_fd);
if(!tcpsock && !localsock && num_fd == 0) {
if (!tcpsock && !localsock && num_fd == 0) {
logg("!Please define server type (local and/or TCP).\n");
ret = 1;
break;
}
logg("#clamd daemon %s (OS: "TARGET_OS_TYPE", ARCH: "TARGET_ARCH_TYPE", CPU: "TARGET_CPU_TYPE")\n", get_version());
logg("#clamd daemon %s (OS: " TARGET_OS_TYPE ", ARCH: " TARGET_ARCH_TYPE ", CPU: " TARGET_CPU_TYPE ")\n", get_version());
#ifndef _WIN32
if(user)
if (user)
logg("#Running as user %s (UID %u, GID %u)\n", user->pw_name, user->pw_uid, user->pw_gid);
#endif
#if defined(RLIMIT_DATA) && defined(C_BSD)
if (getrlimit(RLIMIT_DATA, &rlim) == 0) {
/* bb #1941.
/* bb #1941.
* On 32-bit FreeBSD if you set ulimit -d to >2GB then mmap() will fail
* too soon (after ~120 MB).
* Set limit lower than 2G if on 32-bit */
uint64_t lim = rlim.rlim_cur;
if (sizeof(void*) == 4 &&
lim > (1ULL << 31)) {
rlim.rlim_cur = 1ULL << 31;
if (setrlimit(RLIMIT_DATA, &rlim) < 0)
logg("!setrlimit(RLIMIT_DATA) failed: %s\n", strerror(errno));
else
logg("Running on 32-bit system, and RLIMIT_DATA > 2GB, lowering to 2GB!\n");
}
uint64_t lim = rlim.rlim_cur;
if (sizeof(void *) == 4 &&
lim > (1ULL << 31)) {
rlim.rlim_cur = 1ULL << 31;
if (setrlimit(RLIMIT_DATA, &rlim) < 0)
logg("!setrlimit(RLIMIT_DATA) failed: %s\n", strerror(errno));
else
logg("Running on 32-bit system, and RLIMIT_DATA > 2GB, lowering to 2GB!\n");
}
}
#endif
if(logg_size)
if (logg_size)
logg("#Log file size limited to %lld bytes.\n", (long long int)logg_size);
else
logg("#Log file size limit disabled.\n");
@ -372,7 +365,7 @@ int main(int argc, char **argv)
}
/* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
if(optget(opts, "OnAccessExtraScanning")->enabled) {
if (optget(opts, "OnAccessExtraScanning")->enabled) {
logg("*ScanOnAccess: OnAccessExtraScanning was requested, but has "
"been disabled due to a known issue with thread resource "
"cleanup. The OnAccessExtraScanning feature will be "
@ -380,7 +373,7 @@ int main(int argc, char **argv)
"For details, see: https://bugzilla.clamav.net/show_bug.cgi?id=12048\n");
}
if(!(engine = cl_engine_new())) {
if (!(engine = cl_engine_new())) {
logg("!Can't initialize antivirus engine\n");
ret = 1;
break;
@ -393,16 +386,16 @@ int main(int argc, char **argv)
dbdir = optget(opts, "DatabaseDirectory")->strarg;
logg("#Reading databases from %s\n", dbdir);
if(optget(opts, "DetectPUA")->enabled) {
if (optget(opts, "DetectPUA")->enabled) {
dboptions |= CL_DB_PUA;
if((opt = optget(opts, "ExcludePUA"))->enabled) {
if ((opt = optget(opts, "ExcludePUA"))->enabled) {
dboptions |= CL_DB_PUA_EXCLUDE;
i = 0;
logg("#Excluded PUA categories:");
while(opt) {
if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
while (opt) {
if (!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
logg("!Can't allocate memory for pua_cats\n");
cl_engine_free(engine);
ret = 1;
@ -414,19 +407,19 @@ int main(int argc, char **argv)
sprintf(pua_cats + i, ".%s", opt->strarg);
i += strlen(opt->strarg) + 1;
pua_cats[i] = 0;
opt = opt->nextarg;
opt = opt->nextarg;
}
if (ret)
break;
logg("#\n");
pua_cats[i] = '.';
pua_cats[i] = '.';
pua_cats[i + 1] = 0;
}
if((opt = optget(opts, "IncludePUA"))->enabled) {
if(pua_cats) {
if ((opt = optget(opts, "IncludePUA"))->enabled) {
if (pua_cats) {
logg("!ExcludePUA and IncludePUA cannot be used at the same time\n");
free(pua_cats);
ret = 1;
@ -436,8 +429,8 @@ int main(int argc, char **argv)
dboptions |= CL_DB_PUA_INCLUDE;
i = 0;
logg("#Included PUA categories:");
while(opt) {
if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
while (opt) {
if (!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
logg("!Can't allocate memory for pua_cats\n");
ret = 1;
break;
@ -448,19 +441,19 @@ int main(int argc, char **argv)
sprintf(pua_cats + i, ".%s", opt->strarg);
i += strlen(opt->strarg) + 1;
pua_cats[i] = 0;
opt = opt->nextarg;
opt = opt->nextarg;
}
if (ret)
break;
logg("#\n");
pua_cats[i] = '.';
pua_cats[i] = '.';
pua_cats[i + 1] = 0;
}
if(pua_cats) {
if((ret = cl_engine_set_str(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))) {
if (pua_cats) {
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));
free(pua_cats);
ret = 1;
@ -472,14 +465,14 @@ int main(int argc, char **argv)
logg("#Not loading PUA signatures.\n");
}
if(optget(opts, "OfficialDatabaseOnly")->enabled) {
if (optget(opts, "OfficialDatabaseOnly")->enabled) {
dboptions |= CL_DB_OFFICIAL_ONLY;
logg("#Only loading official signatures.\n");
}
/* set the temporary dir */
if((opt = optget(opts, "TemporaryDirectory"))->enabled) {
if((ret = cl_engine_set_str(engine, CL_ENGINE_TMPDIR, opt->strarg))) {
if ((opt = optget(opts, "TemporaryDirectory"))->enabled) {
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));
ret = 1;
break;
@ -490,20 +483,20 @@ int main(int argc, char **argv)
cl_engine_set_clcb_virus_found(engine, clamd_virus_found_cb);
if(optget(opts, "LeaveTemporaryFiles")->enabled)
if (optget(opts, "LeaveTemporaryFiles")->enabled)
cl_engine_set_num(engine, CL_ENGINE_KEEPTMP, 1);
if(optget(opts, "ForceToDisk")->enabled)
if (optget(opts, "ForceToDisk")->enabled)
cl_engine_set_num(engine, CL_ENGINE_FORCETODISK, 1);
if(optget(opts, "PhishingSignatures")->enabled)
if (optget(opts, "PhishingSignatures")->enabled)
dboptions |= CL_DB_PHISHING;
else
logg("#Not loading phishing signatures.\n");
if(optget(opts,"Bytecode")->enabled) {
if (optget(opts, "Bytecode")->enabled) {
dboptions |= CL_DB_BYTECODE;
if((opt = optget(opts,"BytecodeSecurity"))->enabled) {
if ((opt = optget(opts, "BytecodeSecurity"))->enabled) {
enum bytecode_security s;
if (!strcmp(opt->strarg, "TrustSigned")) {
@ -514,7 +507,7 @@ int main(int argc, char **argv)
logg("#Bytecode: Security mode set to \"Paranoid\".\n");
} else {
logg("!Unable to parse bytecode security setting:%s\n",
opt->strarg);
opt->strarg);
ret = 1;
break;
}
@ -525,54 +518,54 @@ int main(int argc, char **argv)
break;
}
}
if((opt = optget(opts,"BytecodeUnsigned"))->enabled) {
if ((opt = optget(opts, "BytecodeUnsigned"))->enabled) {
dboptions |= CL_DB_BYTECODE_UNSIGNED;
logg("#Bytecode: Enabled support for unsigned bytecode.\n");
}
if((opt = optget(opts,"BytecodeMode"))->enabled) {
if ((opt = optget(opts, "BytecodeMode"))->enabled) {
enum bytecode_mode mode;
if (!strcmp(opt->strarg, "ForceJIT"))
mode = CL_BYTECODE_MODE_JIT;
else if(!strcmp(opt->strarg, "ForceInterpreter"))
else if (!strcmp(opt->strarg, "ForceInterpreter"))
mode = CL_BYTECODE_MODE_INTERPRETER;
else if(!strcmp(opt->strarg, "Test"))
else if (!strcmp(opt->strarg, "Test"))
mode = CL_BYTECODE_MODE_TEST;
else
mode = CL_BYTECODE_MODE_AUTO;
cl_engine_set_num(engine, CL_ENGINE_BYTECODE_MODE, mode);
}
if((opt = optget(opts,"BytecodeTimeout"))->enabled) {
if ((opt = optget(opts, "BytecodeTimeout"))->enabled) {
cl_engine_set_num(engine, CL_ENGINE_BYTECODE_TIMEOUT, opt->numarg);
}
} else {
logg("#Bytecode support disabled.\n");
}
if(optget(opts,"PhishingScanURLs")->enabled)
if (optget(opts, "PhishingScanURLs")->enabled)
dboptions |= CL_DB_PHISHING_URLS;
else
logg("#Disabling URL based phishing detection.\n");
if(optget(opts,"DevACOnly")->enabled) {
if (optget(opts, "DevACOnly")->enabled) {
logg("#Only using the A-C matcher.\n");
cl_engine_set_num(engine, CL_ENGINE_AC_ONLY, 1);
}
if((opt = optget(opts, "DevACDepth"))->enabled) {
if ((opt = optget(opts, "DevACDepth"))->enabled) {
cl_engine_set_num(engine, CL_ENGINE_AC_MAXDEPTH, opt->numarg);
logg("#Max A-C depth set to %u\n", (unsigned int) opt->numarg);
logg("#Max A-C depth set to %u\n", (unsigned int)opt->numarg);
}
if((ret = cl_load(dbdir, engine, &sigs, dboptions))) {
if ((ret = cl_load(dbdir, engine, &sigs, dboptions))) {
logg("!%s\n", cl_strerror(ret));
ret = 1;
break;
}
if((ret = statinidir_th(dbdir))) {
if ((ret = statinidir_th(dbdir))) {
logg("!%s\n", cl_strerror(ret));
ret = 1;
break;
@ -584,29 +577,29 @@ int main(int argc, char **argv)
logg("#Loaded %u signatures.\n", sigs);
/* pcre engine limits - required for cl_engine_compile */
if((opt = optget(opts, "PCREMatchLimit"))->active) {
if((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_MATCH_LIMIT, opt->numarg))) {
if ((opt = optget(opts, "PCREMatchLimit"))->active) {
if ((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_MATCH_LIMIT, opt->numarg))) {
logg("!cli_engine_set_num(PCREMatchLimit) failed: %s\n", cl_strerror(ret));
cl_engine_free(engine);
return 1;
}
}
if((opt = optget(opts, "PCRERecMatchLimit"))->active) {
if((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_RECMATCH_LIMIT, opt->numarg))) {
if ((opt = optget(opts, "PCRERecMatchLimit"))->active) {
if ((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_RECMATCH_LIMIT, opt->numarg))) {
logg("!cli_engine_set_num(PCRERecMatchLimit) failed: %s\n", cl_strerror(ret));
cl_engine_free(engine);
return 1;
}
}
if((ret = cl_engine_compile(engine)) != 0) {
if ((ret = cl_engine_compile(engine)) != 0) {
logg("!Database initialization error: %s\n", cl_strerror(ret));
ret = 1;
break;
}
if(tcpsock || num_fd > 0) {
if (tcpsock || num_fd > 0) {
int *t;
opt = optget(opts, "TCPAddr");
@ -617,7 +610,7 @@ int main(int argc, char **argv)
char *ipaddr = (!strcmp(opt->strarg, "all") ? NULL : opt->strarg);
if (tcpserver(&lsockets, &nlsockets, ipaddr, opts) == -1) {
ret = 1;
ret = 1;
breakout = 1;
break;
}
@ -635,7 +628,7 @@ int main(int argc, char **argv)
}
}
#ifndef _WIN32
if(localsock && num_fd == 0) {
if (localsock && num_fd == 0) {
int *t;
mode_t sock_mode, umsk = umask(0777); /* socket is created with 000 to avoid races */
@ -653,14 +646,14 @@ int main(int argc, char **argv)
}
umask(umsk); /* restore umask */
if(optget(opts, "LocalSocketGroup")->enabled) {
char *gname = optget(opts, "LocalSocketGroup")->strarg, *end;
if (optget(opts, "LocalSocketGroup")->enabled) {
char *gname = optget(opts, "LocalSocketGroup")->strarg, *end;
gid_t sock_gid = strtol(gname, &end, 10);
if(*end) {
if (*end) {
struct group *pgrp = getgrnam(gname);
if(!pgrp) {
if (!pgrp) {
logg("!Unknown group %s\n", gname);
ret = 1;
break;
@ -668,18 +661,18 @@ int main(int argc, char **argv)
sock_gid = pgrp->gr_gid;
}
if(chown(optget(opts, "LocalSocket")->strarg, -1, sock_gid)) {
if (chown(optget(opts, "LocalSocket")->strarg, -1, sock_gid)) {
logg("!Failed to change socket ownership to group %s\n", gname);
ret = 1;
break;
}
}
if(optget(opts, "LocalSocketMode")->enabled) {
if (optget(opts, "LocalSocketMode")->enabled) {
char *end;
sock_mode = strtol(optget(opts, "LocalSocketMode")->strarg, &end, 8);
if(*end) {
if (*end) {
logg("!Invalid LocalSocketMode %s\n", optget(opts, "LocalSocketMode")->strarg);
ret = 1;
break;
@ -688,7 +681,7 @@ int main(int argc, char **argv)
sock_mode = 0777 /* & ~umsk*/; /* conservative default: umask was 0 in clamd < 0.96 */
}
if(chmod(optget(opts, "LocalSocket")->strarg, sock_mode & 0666)) {
if (chmod(optget(opts, "LocalSocket")->strarg, sock_mode & 0666)) {
logg("!Cannot set socket permission to %s\n", optget(opts, "LocalSocketMode")->strarg);
ret = 1;
break;
@ -698,8 +691,7 @@ int main(int argc, char **argv)
}
/* check for local sockets passed by systemd */
if (num_fd > 0)
{
if (num_fd > 0) {
int *t;
t = realloc(lsockets, sizeof(int) * (nlsockets + 1));
if (!(t)) {
@ -709,34 +701,26 @@ int main(int argc, char **argv)
lsockets = t;
lsockets[nlsockets] = localserver(opts);
if (lsockets[nlsockets] == -1)
{
if (lsockets[nlsockets] == -1) {
ret = 1;
break;
}
else if (lsockets[nlsockets] > 0)
{
} else if (lsockets[nlsockets] > 0) {
nlsockets++;
}
}
/* fork into background */
if (foreground == -1)
{
if (optget(opts, "Foreground")->enabled)
{
if (foreground == -1) {
if (optget(opts, "Foreground")->enabled) {
foreground = 1;
}
else
{
} else {
foreground = 0;
}
}
if(foreground == 0)
{
if (foreground == 0) {
#ifdef C_BSD
/* workaround for OpenBSD bug, see https://wwws.clamav.net/bugzilla/show_bug.cgi?id=885 */
for(ret=0;(unsigned int)ret<nlsockets;ret++) {
for (ret = 0; (unsigned int)ret < nlsockets; ret++) {
if (fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) | O_NONBLOCK) == -1) {
logg("!fcntl for lsockets[] failed\n");
close(lsockets[ret]);
@ -747,14 +731,14 @@ int main(int argc, char **argv)
#endif
gengine = engine;
atexit(free_engine);
if(daemonize() == -1) {
if (daemonize() == -1) {
logg("!daemonize() failed: %s\n", strerror(errno));
ret = 1;
break;
}
gengine = NULL;
#ifdef C_BSD
for(ret=0;(unsigned int)ret<nlsockets;ret++) {
for (ret = 0; (unsigned int)ret < nlsockets; ret++) {
if (fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) & ~O_NONBLOCK) == -1) {
logg("!fcntl for lsockets[] failed\n");
close(lsockets[ret]);
@ -763,10 +747,9 @@ int main(int argc, char **argv)
}
}
#endif
if(!debug_mode)
if(chdir("/") == -1)
if (!debug_mode)
if (chdir("/") == -1)
logg("^Can't change current working directory to root\n");
}
#endif
@ -780,18 +763,17 @@ int main(int argc, char **argv)
} while (0);
if (num_fd == 0)
{
if (num_fd == 0) {
logg("*Closing the main socket%s.\n", (nlsockets > 1) ? "s" : "");
for (i = 0; i < nlsockets; i++) {
closesocket(lsockets[i]);
}
#ifndef _WIN32
if(nlsockets && localsock) {
if (nlsockets && localsock) {
opt = optget(opts, "LocalSocket");
if(unlink(opt->strarg) == -1)
if (unlink(opt->strarg) == -1)
logg("!Can't unlink the socket file %s\n", opt->strarg);
else
logg("Socket file removed.\n");
@ -816,8 +798,8 @@ int is_valid_hostid(void)
if (strlen(hostid) != 36)
return 0;
count=0;
for (i=0; i < 36; i++)
count = 0;
for (i = 0; i < 36; i++)
if (hostid[i] == '-')
count++;

View file

@ -26,7 +26,7 @@
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#ifndef _WIN32
#ifndef _WIN32
#include <sys/socket.h>
#include <sys/un.h>
#endif
@ -58,41 +58,33 @@ int localserver(const struct optstruct *opts)
int localserver(const struct optstruct *opts)
{
struct sockaddr_un server;
int sockfd = 0, backlog;
STATBUF foo;
char *estr;
char *sockdir;
char *pos;
struct stat sb;
int cnt;
struct sockaddr_un server;
int sockfd = 0, backlog;
STATBUF foo;
char *estr;
char *sockdir;
char *pos;
struct stat sb;
int cnt;
int num_fd = sd_listen_fds(0);
if (num_fd > 2)
{
if (num_fd > 2) {
logg("!LOCAL: Received more than two file descriptors from systemd.\n");
return -1;
}
else if (num_fd > 0)
{
} else if (num_fd > 0) {
/* use socket passed by systemd */
int i;
for(i = 0; i < num_fd; i += 1)
{
for (i = 0; i < num_fd; i += 1) {
sockfd = SD_LISTEN_FDS_START + i;
if (sd_is_socket(sockfd, AF_UNIX, SOCK_STREAM, 1) == 1)
{
if (sd_is_socket(sockfd, AF_UNIX, SOCK_STREAM, 1) == 1) {
/* correct socket */
break;
}
else
{
} else {
/* wrong socket */
sockfd = -2;
}
}
if (sockfd == -2)
{
if (sockfd == -2) {
logg("#LOCAL: No local AF_UNIX SOCK_STREAM socket received from systemd.\n");
return -2;
}
@ -100,22 +92,21 @@ int localserver(const struct optstruct *opts)
return sockfd;
}
/* create socket */
memset((char *) &server, 0, sizeof(server));
memset((char *)&server, 0, sizeof(server));
server.sun_family = AF_UNIX;
strncpy(server.sun_path, optget(opts, "LocalSocket")->strarg, sizeof(server.sun_path));
server.sun_path[sizeof(server.sun_path)-1]='\0';
server.sun_path[sizeof(server.sun_path) - 1] = '\0';
pos = NULL;
if ((pos = strstr(server.sun_path, "/")) && (pos = strstr(((char*) pos + 1), "/"))) {
cnt = 0;
if ((pos = strstr(server.sun_path, "/")) && (pos = strstr(((char *)pos + 1), "/"))) {
cnt = 0;
sockdir = NULL;
pos = server.sun_path + strlen(server.sun_path);
pos = server.sun_path + strlen(server.sun_path);
while (pos != server.sun_path) {
if (*pos == '/') {
sockdir = cli_strndup(server.sun_path, strlen(server.sun_path) - cnt);
break;
}
else {
} else {
pos--;
cnt++;
}
@ -124,11 +115,11 @@ int localserver(const struct optstruct *opts)
if (stat(sockdir, &sb)) {
if (errno == ENOENT) {
mode_t sock_mode;
if(optget(opts, "LocalSocketMode")->enabled) {
if (optget(opts, "LocalSocketMode")->enabled) {
char *end;
sock_mode = strtol(optget(opts, "LocalSocketMode")->strarg, &end, 8);
if(*end) {
if (*end) {
logg("!Invalid LocalSocketMode %s\n", optget(opts, "LocalSocketMode")->strarg);
free(sockdir);
return -1;
@ -142,8 +133,7 @@ int localserver(const struct optstruct *opts)
if (errno == ENOENT) {
logg("!LOCAL: Ensure parent directory exists.\n");
}
}
else {
} else {
logg("Localserver: Creating socket directory: %s\n", sockdir);
}
}
@ -151,44 +141,44 @@ int localserver(const struct optstruct *opts)
free(sockdir);
}
if((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
estr = strerror(errno);
logg("!LOCAL: Socket allocation error: %s\n", estr);
return -1;
if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
estr = strerror(errno);
logg("!LOCAL: Socket allocation error: %s\n", estr);
return -1;
}
if(bind(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) == -1) {
if(errno == EADDRINUSE) {
if(connect(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) >= 0) {
logg("!LOCAL: Socket file %s is in use by another process.\n", server.sun_path);
close(sockfd);
return -1;
}
if(optget(opts, "FixStaleSocket")->enabled) {
logg("#LOCAL: Removing stale socket file %s\n", server.sun_path);
if(unlink(server.sun_path) == -1) {
estr = strerror(errno);
logg("!LOCAL: Socket file %s could not be removed: %s\n", server.sun_path, estr);
close(sockfd);
return -1;
}
if(bind(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) == -1) {
estr = strerror(errno);
logg("!LOCAL: Socket file %s could not be bound: %s (unlink tried)\n", server.sun_path, estr);
close(sockfd);
return -1;
}
} else if(CLAMSTAT(server.sun_path, &foo) != -1) {
logg("!LOCAL: Socket file %s exists. Either remove it, or configure a different one.\n", server.sun_path);
close(sockfd);
return -1;
}
} else {
estr = strerror(errno);
logg("!LOCAL: Socket file %s could not be bound: %s\n", server.sun_path, estr);
close(sockfd);
return -1;
}
if (bind(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) == -1) {
if (errno == EADDRINUSE) {
if (connect(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) >= 0) {
logg("!LOCAL: Socket file %s is in use by another process.\n", server.sun_path);
close(sockfd);
return -1;
}
if (optget(opts, "FixStaleSocket")->enabled) {
logg("#LOCAL: Removing stale socket file %s\n", server.sun_path);
if (unlink(server.sun_path) == -1) {
estr = strerror(errno);
logg("!LOCAL: Socket file %s could not be removed: %s\n", server.sun_path, estr);
close(sockfd);
return -1;
}
if (bind(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) == -1) {
estr = strerror(errno);
logg("!LOCAL: Socket file %s could not be bound: %s (unlink tried)\n", server.sun_path, estr);
close(sockfd);
return -1;
}
} else if (CLAMSTAT(server.sun_path, &foo) != -1) {
logg("!LOCAL: Socket file %s exists. Either remove it, or configure a different one.\n", server.sun_path);
close(sockfd);
return -1;
}
} else {
estr = strerror(errno);
logg("!LOCAL: Socket file %s could not be bound: %s\n", server.sun_path, estr);
close(sockfd);
return -1;
}
}
logg("#LOCAL: Unix socket file %s\n", server.sun_path);
@ -196,11 +186,11 @@ int localserver(const struct optstruct *opts)
backlog = optget(opts, "MaxConnectionQueueLength")->numarg;
logg("#LOCAL: Setting connection queue length to %d\n", backlog);
if(listen(sockfd, backlog) == -1) {
estr = strerror(errno);
logg("!LOCAL: listen() error: %s\n", estr);
close(sockfd);
return -1;
if (listen(sockfd, backlog) == -1) {
estr = strerror(errno);
logg("!LOCAL: listen() error: %s\n", estr);
close(sockfd);
return -1;
}
return sockfd;

View file

@ -60,9 +60,9 @@ static int onas_ddd_init_wdlt(uint64_t nwatches);
static int onas_ddd_grow_wdlt();
static int onas_ddd_watch(const char *pathname, int fan_fd, uint64_t fan_mask, int in_fd, uint64_t in_mask);
static int onas_ddd_watch_hierarchy(const char* pathname, size_t len, int fd, uint64_t mask, uint32_t type);
static int onas_ddd_watch_hierarchy(const char *pathname, size_t len, int fd, uint64_t mask, uint32_t type);
static int onas_ddd_unwatch(const char *pathname, int fan_fd, int in_fd);
static int onas_ddd_unwatch_hierarchy(const char* pathname, size_t len, int fd, uint32_t type);
static int onas_ddd_unwatch_hierarchy(const char *pathname, size_t len, int fd, uint32_t type);
static void onas_ddd_handle_in_moved_to(struct ddd_thrarg *tharg, const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask);
static void onas_ddd_handle_in_create(struct ddd_thrarg *tharg, const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask);
@ -78,409 +78,417 @@ static char **wdlt;
static uint32_t wdlt_len;
static int onas_in_fd;
static int onas_ddd_init_ht(uint32_t ht_size) {
static int onas_ddd_init_ht(uint32_t ht_size)
{
if (ht_size <= 0)
ht_size = ONAS_DEFAULT_HT_SIZE;
if (ht_size <= 0)
ht_size = ONAS_DEFAULT_HT_SIZE;
return onas_ht_init(&ddd_ht, ht_size);
return onas_ht_init(&ddd_ht, ht_size);
}
static int onas_ddd_init_wdlt(uint64_t nwatches) {
static int onas_ddd_init_wdlt(uint64_t nwatches)
{
if (nwatches <= 0) return CL_EARG;
if (nwatches <= 0) return CL_EARG;
wdlt = (char **) cli_calloc(nwatches << 1, sizeof(char*));
if (!wdlt) return CL_EMEM;
wdlt = (char **)cli_calloc(nwatches << 1, sizeof(char *));
if (!wdlt) return CL_EMEM;
wdlt_len = nwatches << 1;
wdlt_len = nwatches << 1;
return CL_SUCCESS;
return CL_SUCCESS;
}
static int onas_ddd_grow_wdlt() {
static int onas_ddd_grow_wdlt()
{
char **ptr = NULL;
char **ptr = NULL;
ptr = (char **) cli_realloc(wdlt, wdlt_len << 1);
if (ptr) {
wdlt = ptr;
memset(&ptr[wdlt_len], 0, sizeof(char *) * (wdlt_len - 1));
} else {
return CL_EMEM;
}
ptr = (char **)cli_realloc(wdlt, wdlt_len << 1);
if (ptr) {
wdlt = ptr;
memset(&ptr[wdlt_len], 0, sizeof(char *) * (wdlt_len - 1));
} else {
return CL_EMEM;
}
wdlt_len <<= 1;
wdlt_len <<= 1;
return CL_SUCCESS;
return CL_SUCCESS;
}
/* TODO: Support configuration for changing/setting number of inotify watches. */
int onas_ddd_init(uint64_t nwatches, size_t ht_size) {
int onas_ddd_init(uint64_t nwatches, size_t ht_size)
{
const char* nwatch_file = "/proc/sys/fs/inotify/max_user_watches";
int nwfd = 0;
int ret = 0;
char nwatch_str[MAX_WATCH_LEN];
char *p = NULL;
nwatches = 0;
const char *nwatch_file = "/proc/sys/fs/inotify/max_user_watches";
int nwfd = 0;
int ret = 0;
char nwatch_str[MAX_WATCH_LEN];
char *p = NULL;
nwatches = 0;
nwfd = open(nwatch_file, O_RDONLY);
if (nwfd < 0) return CL_EOPEN;
nwfd = open(nwatch_file, O_RDONLY);
if (nwfd < 0) return CL_EOPEN;
ret = read(nwfd, nwatch_str, MAX_WATCH_LEN);
close(nwfd);
if (ret < 0) return CL_EREAD;
ret = read(nwfd, nwatch_str, MAX_WATCH_LEN);
close(nwfd);
if (ret < 0) return CL_EREAD;
nwatches = strtol(nwatch_str, &p, 10);
nwatches = strtol(nwatch_str, &p, 10);
ret = onas_ddd_init_wdlt(nwatches);
if (ret) return ret;
ret = onas_ddd_init_wdlt(nwatches);
if (ret) return ret;
ret = onas_ddd_init_ht(ht_size);
if (ret) return ret;
ret = onas_ddd_init_ht(ht_size);
if (ret) return ret;
return CL_SUCCESS;
return CL_SUCCESS;
}
static int onas_ddd_watch(const char *pathname, int fan_fd, uint64_t fan_mask, int in_fd, uint64_t in_mask) {
if (!pathname || fan_fd <= 0 || in_fd <= 0) return CL_ENULLARG;
static int onas_ddd_watch(const char *pathname, int fan_fd, uint64_t fan_mask, int in_fd, uint64_t in_mask)
{
if (!pathname || fan_fd <= 0 || in_fd <= 0) return CL_ENULLARG;
int ret = CL_SUCCESS;
size_t len = strlen(pathname);
int ret = CL_SUCCESS;
size_t len = strlen(pathname);
ret = onas_ddd_watch_hierarchy(pathname, len, in_fd, in_mask, ONAS_IN);
if (ret) return ret;
ret = onas_ddd_watch_hierarchy(pathname, len, in_fd, in_mask, ONAS_IN);
if (ret) return ret;
ret = onas_ddd_watch_hierarchy(pathname, len, fan_fd, fan_mask, ONAS_FAN);
if (ret) return ret;
ret = onas_ddd_watch_hierarchy(pathname, len, fan_fd, fan_mask, ONAS_FAN);
if (ret) return ret;
return CL_SUCCESS;
return CL_SUCCESS;
}
static int onas_ddd_watch_hierarchy(const char* pathname, size_t len, int fd, uint64_t mask, uint32_t type) {
static int onas_ddd_watch_hierarchy(const char *pathname, size_t len, int fd, uint64_t mask, uint32_t type)
{
if (!pathname || fd <= 0 || !type) return CL_ENULLARG;
if (!pathname || fd <= 0 || !type) return CL_ENULLARG;
if (type == (ONAS_IN | ONAS_FAN)) return CL_EARG;
if (type == (ONAS_IN | ONAS_FAN)) return CL_EARG;
struct onas_hnode *hnode = NULL;
struct onas_element *elem = NULL;
int wd = 0;
struct onas_hnode *hnode = NULL;
struct onas_element *elem = NULL;
int wd = 0;
if(onas_ht_get(ddd_ht, pathname, len, &elem) != CL_SUCCESS) return CL_EARG;
if (onas_ht_get(ddd_ht, pathname, len, &elem) != CL_SUCCESS) return CL_EARG;
hnode = elem->data;
hnode = elem->data;
if (type & ONAS_IN) {
wd = inotify_add_watch(fd, pathname, (uint32_t) mask);
if (type & ONAS_IN) {
wd = inotify_add_watch(fd, pathname, (uint32_t)mask);
if (wd < 0) return CL_EARG;
if (wd < 0) return CL_EARG;
if ((uint32_t) wd >= wdlt_len) {
onas_ddd_grow_wdlt();
}
if ((uint32_t)wd >= wdlt_len) {
onas_ddd_grow_wdlt();
}
/* Link the hash node to the watch descriptor lookup table */
hnode->wd = wd;
wdlt[wd] = hnode->pathname;
/* Link the hash node to the watch descriptor lookup table */
hnode->wd = wd;
wdlt[wd] = hnode->pathname;
hnode->watched |= ONAS_INWATCH;
} else if (type & ONAS_FAN) {
if(fanotify_mark(fd, FAN_MARK_ADD, mask, AT_FDCWD, hnode->pathname) < 0) return CL_EARG;
hnode->watched |= ONAS_FANWATCH;
} else {
return CL_EARG;
}
hnode->watched |= ONAS_INWATCH;
} else if (type & ONAS_FAN) {
if (fanotify_mark(fd, FAN_MARK_ADD, mask, AT_FDCWD, hnode->pathname) < 0) return CL_EARG;
hnode->watched |= ONAS_FANWATCH;
} else {
return CL_EARG;
}
struct onas_lnode *curr = hnode->childhead;
struct onas_lnode *curr = hnode->childhead;
while (curr->next != hnode->childtail) {
curr = curr->next;
while (curr->next != hnode->childtail) {
curr = curr->next;
size_t size = len + strlen(curr->dirname) + 2;
char *child_path = (char *) cli_malloc(size);
if (child_path == NULL)
return CL_EMEM;
if (hnode->pathname[len-1] == '/')
snprintf(child_path, --size, "%s%s", hnode->pathname, curr->dirname);
else
snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname);
size_t size = len + strlen(curr->dirname) + 2;
char *child_path = (char *)cli_malloc(size);
if (child_path == NULL)
return CL_EMEM;
if (hnode->pathname[len - 1] == '/')
snprintf(child_path, --size, "%s%s", hnode->pathname, curr->dirname);
else
snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname);
if(onas_ddd_watch_hierarchy(child_path, strlen(child_path), fd, mask, type)) {
return CL_EARG;
}
free(child_path);
}
if (onas_ddd_watch_hierarchy(child_path, strlen(child_path), fd, mask, type)) {
return CL_EARG;
}
free(child_path);
}
return CL_SUCCESS;
return CL_SUCCESS;
}
static int onas_ddd_unwatch(const char *pathname, int fan_fd, int in_fd) {
if (!pathname || fan_fd <= 0 || in_fd <= 0) return CL_ENULLARG;
static int onas_ddd_unwatch(const char *pathname, int fan_fd, int in_fd)
{
if (!pathname || fan_fd <= 0 || in_fd <= 0) return CL_ENULLARG;
int ret = CL_SUCCESS;
size_t len = strlen(pathname);
int ret = CL_SUCCESS;
size_t len = strlen(pathname);
ret = onas_ddd_unwatch_hierarchy(pathname, len, in_fd, ONAS_IN);
if (ret) return ret;
ret = onas_ddd_unwatch_hierarchy(pathname, len, in_fd, ONAS_IN);
if (ret) return ret;
ret = onas_ddd_unwatch_hierarchy(pathname, len,fan_fd, ONAS_FAN);
if (ret) return ret;
ret = onas_ddd_unwatch_hierarchy(pathname, len, fan_fd, ONAS_FAN);
if (ret) return ret;
return CL_SUCCESS;
return CL_SUCCESS;
}
static int onas_ddd_unwatch_hierarchy(const char* pathname, size_t len, int fd, uint32_t type) {
static int onas_ddd_unwatch_hierarchy(const char *pathname, size_t len, int fd, uint32_t type)
{
if (!pathname || fd <= 0 || !type) return CL_ENULLARG;
if (!pathname || fd <= 0 || !type) return CL_ENULLARG;
if (type == (ONAS_IN | ONAS_FAN)) return CL_EARG;
if (type == (ONAS_IN | ONAS_FAN)) return CL_EARG;
struct onas_hnode *hnode = NULL;
struct onas_element *elem = NULL;
int wd = 0;
struct onas_hnode *hnode = NULL;
struct onas_element *elem = NULL;
int wd = 0;
if(onas_ht_get(ddd_ht, pathname, len, &elem)) return CL_EARG;
if (onas_ht_get(ddd_ht, pathname, len, &elem)) return CL_EARG;
hnode = elem->data;
hnode = elem->data;
if (type & ONAS_IN) {
wd = hnode->wd;
if (type & ONAS_IN) {
wd = hnode->wd;
if(!inotify_rm_watch(fd, wd)) return CL_EARG;
if (!inotify_rm_watch(fd, wd)) return CL_EARG;
/* Unlink the hash node from the watch descriptor lookup table */
hnode->wd = 0;
wdlt[wd] = NULL;
/* Unlink the hash node from the watch descriptor lookup table */
hnode->wd = 0;
wdlt[wd] = NULL;
hnode->watched = ONAS_STOPWATCH;
} else if (type & ONAS_FAN) {
if(fanotify_mark(fd, FAN_MARK_REMOVE, 0, AT_FDCWD, hnode->pathname) < 0) return CL_EARG;
hnode->watched = ONAS_STOPWATCH;
} else {
return CL_EARG;
}
hnode->watched = ONAS_STOPWATCH;
} else if (type & ONAS_FAN) {
if (fanotify_mark(fd, FAN_MARK_REMOVE, 0, AT_FDCWD, hnode->pathname) < 0) return CL_EARG;
hnode->watched = ONAS_STOPWATCH;
} else {
return CL_EARG;
}
struct onas_lnode *curr = hnode->childhead;
struct onas_lnode *curr = hnode->childhead;
while (curr->next != hnode->childtail) {
curr = curr->next;
while (curr->next != hnode->childtail) {
curr = curr->next;
size_t size = len + strlen(curr->dirname) + 2;
char *child_path = (char *) cli_malloc(size);
if (child_path == NULL)
return CL_EMEM;
if (hnode->pathname[len-1] == '/')
snprintf(child_path, --size, "%s%s", hnode->pathname, curr->dirname);
else
snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname);
size_t size = len + strlen(curr->dirname) + 2;
char *child_path = (char *)cli_malloc(size);
if (child_path == NULL)
return CL_EMEM;
if (hnode->pathname[len - 1] == '/')
snprintf(child_path, --size, "%s%s", hnode->pathname, curr->dirname);
else
snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname);
onas_ddd_unwatch_hierarchy(child_path, strlen(child_path), fd, type);
free(child_path);
}
onas_ddd_unwatch_hierarchy(child_path, strlen(child_path), fd, type);
free(child_path);
}
return CL_SUCCESS;
return CL_SUCCESS;
}
void *onas_ddd_th(void *arg) {
struct ddd_thrarg *tharg = (struct ddd_thrarg *) arg;
sigset_t sigset;
struct sigaction act;
const struct optstruct *pt;
uint64_t in_mask = IN_ONLYDIR | IN_MOVE | IN_DELETE | IN_CREATE;
fd_set rfds;
char buf[4096];
ssize_t bread;
const struct inotify_event *event;
int ret, len;
void *onas_ddd_th(void *arg)
{
struct ddd_thrarg *tharg = (struct ddd_thrarg *)arg;
sigset_t sigset;
struct sigaction act;
const struct optstruct *pt;
uint64_t in_mask = IN_ONLYDIR | IN_MOVE | IN_DELETE | IN_CREATE;
fd_set rfds;
char buf[4096];
ssize_t bread;
const struct inotify_event *event;
int ret, len;
/* ignore all signals except SIGUSR1 */
sigfillset(&sigset);
sigdelset(&sigset, SIGUSR1);
/* The behavior of a process is undefined after it ignores a
/* ignore all signals except SIGUSR1 */
sigfillset(&sigset);
sigdelset(&sigset, SIGUSR1);
/* The behavior of a process is undefined after it ignores a
* SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
sigdelset(&sigset, SIGFPE);
sigdelset(&sigset, SIGILL);
sigdelset(&sigset, SIGSEGV);
sigdelset(&sigset, SIGFPE);
sigdelset(&sigset, SIGILL);
sigdelset(&sigset, SIGSEGV);
#ifdef SIGBUS
sigdelset(&sigset, SIGBUS);
sigdelset(&sigset, SIGBUS);
#endif
pthread_sigmask(SIG_SETMASK, &sigset, NULL);
memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = onas_ddd_exit;
sigfillset(&(act.sa_mask));
sigaction(SIGUSR1, &act, NULL);
sigaction(SIGSEGV, &act, NULL);
pthread_sigmask(SIG_SETMASK, &sigset, NULL);
memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = onas_ddd_exit;
sigfillset(&(act.sa_mask));
sigaction(SIGUSR1, &act, NULL);
sigaction(SIGSEGV, &act, NULL);
onas_in_fd = inotify_init1(IN_NONBLOCK);
if (onas_in_fd == -1) {
logg("!ScanOnAccess: Could not init inotify.");
return NULL;
}
onas_in_fd = inotify_init1(IN_NONBLOCK);
if (onas_in_fd == -1) {
logg("!ScanOnAccess: Could not init inotify.");
return NULL;
}
ret = onas_ddd_init(0, ONAS_DEFAULT_HT_SIZE);
if (ret) {
logg("!ScanOnAccess: Failed to initialize 3D. \n");
return NULL;
}
ret = onas_ddd_init(0, ONAS_DEFAULT_HT_SIZE);
if (ret) {
logg("!ScanOnAccess: Failed to initialize 3D. \n");
return NULL;
}
/* Add provided paths recursively. */
if((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) {
while(pt) {
if (!strcmp(pt->strarg, "/")) {
logg("!ScanOnAccess: Not including path '%s' while DDD is enabled\n", pt->strarg);
logg("!ScanOnAccess: Please use the OnAccessMountPath option to watch '%s'\n", pt->strarg);
pt = (struct optstruct *) pt->nextarg;
continue;
}
if(onas_ht_get(ddd_ht, pt->strarg, strlen(pt->strarg), NULL) != CL_SUCCESS) {
if(onas_ht_add_hierarchy(ddd_ht, pt->strarg)) {
logg("!ScanOnAccess: Can't include path '%s'\n", pt->strarg);
return NULL;
} else
logg("ScanOnAccess: Protecting directory '%s' (and all sub-directories)\n", pt->strarg);
}
/* Add provided paths recursively. */
if ((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) {
while (pt) {
if (!strcmp(pt->strarg, "/")) {
logg("!ScanOnAccess: Not including path '%s' while DDD is enabled\n", pt->strarg);
logg("!ScanOnAccess: Please use the OnAccessMountPath option to watch '%s'\n", pt->strarg);
pt = (struct optstruct *)pt->nextarg;
continue;
}
if (onas_ht_get(ddd_ht, pt->strarg, strlen(pt->strarg), NULL) != CL_SUCCESS) {
if (onas_ht_add_hierarchy(ddd_ht, pt->strarg)) {
logg("!ScanOnAccess: Can't include path '%s'\n", pt->strarg);
return NULL;
} else
logg("ScanOnAccess: Protecting directory '%s' (and all sub-directories)\n", pt->strarg);
}
pt = (struct optstruct *) pt->nextarg;
}
} else {
logg("!ScanOnAccess: Please specify at least one path with OnAccessIncludePath\n");
return NULL;
}
pt = (struct optstruct *)pt->nextarg;
}
} else {
logg("!ScanOnAccess: Please specify at least one path with OnAccessIncludePath\n");
return NULL;
}
/* Remove provided paths recursively. */
if((pt = optget(tharg->opts, "OnAccessExcludePath"))->enabled) {
while(pt) {
size_t ptlen = strlen(pt->strarg);
if(onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) {
if(onas_ht_rm_hierarchy(ddd_ht, pt->strarg, ptlen, 0)) {
logg("!ScanOnAccess: Can't exclude path '%s'\n", pt->strarg);
return NULL;
} else
logg("ScanOnAccess: Excluding directory '%s' (and all sub-directories)\n", pt->strarg);
}
/* Remove provided paths recursively. */
if ((pt = optget(tharg->opts, "OnAccessExcludePath"))->enabled) {
while (pt) {
size_t ptlen = strlen(pt->strarg);
if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) {
if (onas_ht_rm_hierarchy(ddd_ht, pt->strarg, ptlen, 0)) {
logg("!ScanOnAccess: Can't exclude path '%s'\n", pt->strarg);
return NULL;
} else
logg("ScanOnAccess: Excluding directory '%s' (and all sub-directories)\n", pt->strarg);
}
pt = (struct optstruct *) pt->nextarg;
}
}
pt = (struct optstruct *)pt->nextarg;
}
}
/* Watch provided paths recursively */
if((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) {
while(pt) {
size_t ptlen = strlen(pt->strarg);
if(onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) {
if(onas_ddd_watch(pt->strarg, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask)) {
logg("!ScanOnAccess: Could not watch path '%s', %s\n", pt->strarg, strerror(errno));
if(errno == EINVAL && optget(tharg->opts, "OnAccessPrevention")->enabled) {
logg("!ScanOnAccess: When using the OnAccessPrevention option, please ensure your kernel\n\t\t\twas compiled with CONFIG_FANOTIFY_ACCESS_PERMISSIONS set to Y\n");
/* Watch provided paths recursively */
if ((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) {
while (pt) {
size_t ptlen = strlen(pt->strarg);
if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) {
if (onas_ddd_watch(pt->strarg, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask)) {
logg("!ScanOnAccess: Could not watch path '%s', %s\n", pt->strarg, strerror(errno));
if (errno == EINVAL && optget(tharg->opts, "OnAccessPrevention")->enabled) {
logg("!ScanOnAccess: When using the OnAccessPrevention option, please ensure your kernel\n\t\t\twas compiled with CONFIG_FANOTIFY_ACCESS_PERMISSIONS set to Y\n");
kill(getpid(), SIGTERM);
}
return NULL;
}
}
pt = (struct optstruct *) pt->nextarg;
}
}
kill(getpid(), SIGTERM);
}
return NULL;
}
}
pt = (struct optstruct *)pt->nextarg;
}
}
/* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
/* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
#if 0
if(optget(tharg->opts, "OnAccessExtraScanning")->enabled) {
logg("ScanOnAccess: Extra scanning and notifications enabled.\n");
}
#endif
#endif
FD_ZERO(&rfds);
FD_SET(onas_in_fd, &rfds);
FD_ZERO(&rfds);
FD_SET(onas_in_fd, &rfds);
while (1) {
do {
ret = select(onas_in_fd + 1, &rfds, NULL, NULL, NULL);
} while (ret == -1 && errno == EINTR);
while (1) {
do {
ret = select(onas_in_fd + 1, &rfds, NULL, NULL, NULL);
} while(ret == -1 && errno == EINTR);
while ((bread = read(onas_in_fd, buf, sizeof(buf))) > 0) {
while((bread = read(onas_in_fd, buf, sizeof(buf))) > 0) {
/* Handle events. */
int wd;
char *p = buf;
const char *path = NULL;
const char *child = NULL;
for (; p < buf + bread; p += sizeof(struct inotify_event) + event->len) {
/* Handle events. */
int wd;
char *p = buf;
const char *path = NULL;
const char *child = NULL;
for(; p < buf + bread; p += sizeof(struct inotify_event) + event->len) {
event = (const struct inotify_event *)p;
wd = event->wd;
path = wdlt[wd];
child = event->name;
event = (const struct inotify_event *) p;
wd = event->wd;
path = wdlt[wd];
child = event->name;
len = strlen(path);
size_t size = strlen(child) + len + 2;
char *child_path = (char *)cli_malloc(size);
if (child_path == NULL)
return NULL;
len = strlen(path);
size_t size = strlen(child) + len + 2;
char *child_path = (char *) cli_malloc(size);
if (child_path == NULL)
return NULL;
if (path[len - 1] == '/')
snprintf(child_path, --size, "%s%s", path, child);
else
snprintf(child_path, size, "%s/%s", path, child);
if (path[len-1] == '/')
snprintf(child_path, --size, "%s%s", path, child);
else
snprintf(child_path, size, "%s/%s", path, child);
if (event->mask & IN_DELETE) {
onas_ddd_handle_in_delete(tharg, path, child_path, event, wd);
if (event->mask & IN_DELETE) {
onas_ddd_handle_in_delete(tharg, path, child_path, event, wd);
} else if (event->mask & IN_MOVED_FROM) {
onas_ddd_handle_in_moved_from(tharg, path, child_path, event, wd);
} else if (event->mask & IN_MOVED_FROM) {
onas_ddd_handle_in_moved_from(tharg, path, child_path, event, wd);
} else if (event->mask & IN_CREATE) {
onas_ddd_handle_in_create(tharg, path, child_path, event, wd, in_mask);
} else if (event->mask & IN_CREATE) {
onas_ddd_handle_in_create(tharg, path, child_path, event, wd, in_mask);
} else if (event->mask & IN_MOVED_TO) {
onas_ddd_handle_in_moved_to(tharg, path, child_path, event, wd, in_mask);
}
}
}
}
} else if (event->mask & IN_MOVED_TO) {
onas_ddd_handle_in_moved_to(tharg, path, child_path, event, wd, in_mask);
}
}
}
}
return NULL;
return NULL;
}
static void onas_ddd_handle_in_delete(struct ddd_thrarg *tharg,
const char *path, const char *child_path, const struct inotify_event *event, int wd) {
const char *path, const char *child_path, const struct inotify_event *event, int wd)
{
struct stat s;
if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
if(!(event->mask & IN_ISDIR)) return;
struct stat s;
if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
if (!(event->mask & IN_ISDIR)) return;
logg("*ddd: DELETE - Removing %s from %s with wd:%d\n", child_path, path, wd);
onas_ddd_unwatch(child_path, tharg->fan_fd, onas_in_fd);
onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0);
logg("*ddd: DELETE - Removing %s from %s with wd:%d\n", child_path, path, wd);
onas_ddd_unwatch(child_path, tharg->fan_fd, onas_in_fd);
onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0);
return;
return;
}
static void onas_ddd_handle_in_moved_from(struct ddd_thrarg *tharg,
const char *path, const char *child_path, const struct inotify_event *event, int wd) {
const char *path, const char *child_path, const struct inotify_event *event, int wd)
{
struct stat s;
if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
if(!(event->mask & IN_ISDIR)) return;
struct stat s;
if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
if (!(event->mask & IN_ISDIR)) return;
logg("*ddd: MOVED_FROM - Removing %s from %s with wd:%d\n", child_path, path, wd);
onas_ddd_unwatch(child_path, tharg->fan_fd, onas_in_fd);
onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0);
logg("*ddd: MOVED_FROM - Removing %s from %s with wd:%d\n", child_path, path, wd);
onas_ddd_unwatch(child_path, tharg->fan_fd, onas_in_fd);
onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0);
return;
return;
}
static void onas_ddd_handle_in_create(struct ddd_thrarg *tharg,
const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask) {
const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask)
{
struct stat s;
struct stat s;
/* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
/* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
#if 0
if (optget(tharg->opts, "OnAccessExtraScanning")->enabled) {
if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) {
@ -496,23 +504,24 @@ static void onas_ddd_handle_in_create(struct ddd_thrarg *tharg,
}
else
#endif
{
if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
if(!(event->mask & IN_ISDIR)) return;
{
if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
if (!(event->mask & IN_ISDIR)) return;
logg("*ddd: MOVED_TO - Adding %s to %s with wd:%d\n", child_path, path, wd);
onas_ht_add_hierarchy(ddd_ht, child_path);
onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask);
}
logg("*ddd: MOVED_TO - Adding %s to %s with wd:%d\n", child_path, path, wd);
onas_ht_add_hierarchy(ddd_ht, child_path);
onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask);
}
return;
return;
}
static void onas_ddd_handle_in_moved_to(struct ddd_thrarg *tharg,
const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask) {
const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask)
{
struct stat s;
/* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
struct stat s;
/* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
#if 0
if (optget(tharg->opts, "OnAccessExtraScanning")->enabled) {
if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) {
@ -528,73 +537,74 @@ static void onas_ddd_handle_in_moved_to(struct ddd_thrarg *tharg,
}
else
#endif
{
if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
if(!(event->mask & IN_ISDIR)) return;
{
if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
if (!(event->mask & IN_ISDIR)) return;
logg("*ddd: MOVED_TO - Adding %s to %s with wd:%d\n", child_path, path, wd);
onas_ht_add_hierarchy(ddd_ht, child_path);
onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask);
}
logg("*ddd: MOVED_TO - Adding %s to %s with wd:%d\n", child_path, path, wd);
onas_ht_add_hierarchy(ddd_ht, child_path);
onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask);
}
return;
return;
}
static void onas_ddd_handle_extra_scanning(struct ddd_thrarg *tharg, const char *pathname, int extra_options) {
static void onas_ddd_handle_extra_scanning(struct ddd_thrarg *tharg, const char *pathname, int extra_options)
{
int thread_started = 1;
struct scth_thrarg *scth_tharg = NULL;
pthread_attr_t scth_attr;
pthread_t scth_pid = 0;
int thread_started = 1;
struct scth_thrarg *scth_tharg = NULL;
pthread_attr_t scth_attr;
pthread_t scth_pid = 0;
do {
if (pthread_attr_init(&scth_attr)) break;
pthread_attr_setdetachstate(&scth_attr, PTHREAD_CREATE_JOINABLE);
do {
if (pthread_attr_init(&scth_attr)) break;
pthread_attr_setdetachstate(&scth_attr, PTHREAD_CREATE_JOINABLE);
/* Allocate memory for arguments. Thread is responsible for freeing it. */
if (!(scth_tharg = (struct scth_thrarg *) calloc(sizeof(struct scth_thrarg), 1))) break;
if (!(scth_tharg->options = (struct cl_scan_options *) calloc(sizeof(struct cl_scan_options), 1))) break;
/* Allocate memory for arguments. Thread is responsible for freeing it. */
if (!(scth_tharg = (struct scth_thrarg *)calloc(sizeof(struct scth_thrarg), 1))) break;
if (!(scth_tharg->options = (struct cl_scan_options *)calloc(sizeof(struct cl_scan_options), 1))) break;
(void) memcpy(scth_tharg->options, tharg->options, sizeof(struct cl_scan_options));
(void)memcpy(scth_tharg->options, tharg->options, sizeof(struct cl_scan_options));
scth_tharg->extra_options = extra_options;
scth_tharg->opts = tharg->opts;
scth_tharg->pathname = strdup(pathname);
scth_tharg->engine = tharg->engine;
scth_tharg->extra_options = extra_options;
scth_tharg->opts = tharg->opts;
scth_tharg->pathname = strdup(pathname);
scth_tharg->engine = tharg->engine;
thread_started = pthread_create(&scth_pid, &scth_attr, onas_scan_th, scth_tharg);
} while(0);
thread_started = pthread_create(&scth_pid, &scth_attr, onas_scan_th, scth_tharg);
} while (0);
if (0 != thread_started) {
/* Failed to create thread. Free anything we may have allocated. */
logg("!ScanOnAccess: Unable to kick off extra scanning.\n");
if (NULL != scth_tharg) {
if (NULL != scth_tharg->pathname){
free(scth_tharg->pathname);
scth_tharg->pathname = NULL;
}
if (NULL != scth_tharg->options) {
free(scth_tharg->options);
scth_tharg->options = NULL;
}
free(scth_tharg);
scth_tharg = NULL;
}
}
if (0 != thread_started) {
/* Failed to create thread. Free anything we may have allocated. */
logg("!ScanOnAccess: Unable to kick off extra scanning.\n");
if (NULL != scth_tharg) {
if (NULL != scth_tharg->pathname) {
free(scth_tharg->pathname);
scth_tharg->pathname = NULL;
}
if (NULL != scth_tharg->options) {
free(scth_tharg->options);
scth_tharg->options = NULL;
}
free(scth_tharg);
scth_tharg = NULL;
}
}
return;
return;
}
static void onas_ddd_exit(int sig)
{
logg("*ScanOnAccess: onas_ddd_exit(), signal %d\n", sig);
static void onas_ddd_exit(int sig) {
logg("*ScanOnAccess: onas_ddd_exit(), signal %d\n", sig);
close(onas_in_fd);
close(onas_in_fd);
onas_free_ht(ddd_ht);
free(wdlt);
onas_free_ht(ddd_ht);
free(wdlt);
pthread_exit(NULL);
logg("ScanOnAccess: stopped\n");
pthread_exit(NULL);
logg("ScanOnAccess: stopped\n");
}
#endif

View file

@ -28,23 +28,21 @@
/*
* Extra options for onas_scan_th().
*/
#define ONAS_IN 0x01
#define ONAS_FAN 0x02
#define ONAS_IN 0x01
#define ONAS_FAN 0x02
#define MAX_WATCH_LEN 7
struct ddd_thrarg {
int sid;
struct cl_scan_options *options;
int fan_fd;
uint64_t fan_mask;
const struct optstruct *opts;
const struct cl_engine *engine;
int sid;
struct cl_scan_options *options;
int fan_fd;
uint64_t fan_mask;
const struct optstruct *opts;
const struct cl_engine *engine;
};
int onas_ddd_init(uint64_t nwatches, size_t ht_size);
void *onas_ddd_th(void *arg);
#endif

View file

@ -56,26 +56,26 @@ static int onas_fan_fd;
static void onas_fan_exit(int sig)
{
logg("*ScanOnAccess: onas_fan_exit(), signal %d\n", sig);
logg("*ScanOnAccess: onas_fan_exit(), signal %d\n", sig);
close(onas_fan_fd);
close(onas_fan_fd);
if (ddd_pid > 0) {
pthread_kill(ddd_pid, SIGUSR1);
pthread_join(ddd_pid, NULL);
}
if (ddd_pid > 0) {
pthread_kill(ddd_pid, SIGUSR1);
pthread_join(ddd_pid, NULL);
}
pthread_exit(NULL);
logg("ScanOnAccess: stopped\n");
pthread_exit(NULL);
logg("ScanOnAccess: stopped\n");
}
static int onas_fan_scanfile(int fan_fd, const char *fname, struct fanotify_event_metadata *fmd, int scan, int extinfo, struct thrarg *tharg)
{
struct fanotify_response res;
const char *virname = NULL;
int ret = 0;
struct fanotify_response res;
const char *virname = NULL;
int ret = 0;
res.fd = fmd->fd;
res.fd = fmd->fd;
res.response = FAN_ALLOW;
if (scan) {
@ -87,10 +87,10 @@ static int onas_fan_scanfile(int fan_fd, const char *fname, struct fanotify_even
}
}
if(fmd->mask & FAN_ALL_PERM_EVENTS) {
ret = write(fan_fd, &res, sizeof(res));
if(ret == -1)
logg("!ScanOnAccess: Internal error (can't write to fanotify)\n");
if (fmd->mask & FAN_ALL_PERM_EVENTS) {
ret = write(fan_fd, &res, sizeof(res));
if (ret == -1)
logg("!ScanOnAccess: Internal error (can't write to fanotify)\n");
}
return ret;
@ -98,26 +98,26 @@ static int onas_fan_scanfile(int fan_fd, const char *fname, struct fanotify_even
void *onas_fan_th(void *arg)
{
struct thrarg *tharg = (struct thrarg *) arg;
sigset_t sigset;
struct sigaction act;
const struct optstruct *pt;
short int scan;
unsigned int sizelimit = 0, extinfo;
STATBUF sb;
uint64_t fan_mask = FAN_EVENT_ON_CHILD | FAN_CLOSE;
fd_set rfds;
char buf[4096];
ssize_t bread;
struct fanotify_event_metadata *fmd;
char fname[1024];
int ret, len, check;
char err[128];
struct thrarg *tharg = (struct thrarg *)arg;
sigset_t sigset;
struct sigaction act;
const struct optstruct *pt;
short int scan;
unsigned int sizelimit = 0, extinfo;
STATBUF sb;
uint64_t fan_mask = FAN_EVENT_ON_CHILD | FAN_CLOSE;
fd_set rfds;
char buf[4096];
ssize_t bread;
struct fanotify_event_metadata *fmd;
char fname[1024];
int ret, len, check;
char err[128];
pthread_attr_t ddd_attr;
struct ddd_thrarg *ddd_tharg = NULL;
pthread_attr_t ddd_attr;
struct ddd_thrarg *ddd_tharg = NULL;
ddd_pid = 0;
ddd_pid = 0;
/* ignore all signals except SIGUSR1 */
sigfillset(&sigset);
@ -139,173 +139,170 @@ void *onas_fan_th(void *arg)
/* Initialize fanotify */
onas_fan_fd = fanotify_init(FAN_CLASS_CONTENT | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS, O_LARGEFILE | O_RDONLY);
if(onas_fan_fd < 0) {
logg("!ScanOnAccess: fanotify_init failed: %s\n", cli_strerror(errno, err, sizeof(err)));
if(errno == EPERM)
logg("ScanOnAccess: clamd must be started by root\n");
return NULL;
if (onas_fan_fd < 0) {
logg("!ScanOnAccess: fanotify_init failed: %s\n", cli_strerror(errno, err, sizeof(err)));
if (errno == EPERM)
logg("ScanOnAccess: clamd must be started by root\n");
return NULL;
}
if (!tharg) {
logg("!Unable to start on-access scanner. Bad thread args.\n");
return NULL;
logg("!Unable to start on-access scanner. Bad thread args.\n");
return NULL;
}
if (optget(tharg->opts, "OnAccessPrevention")->enabled && !optget(tharg->opts, "OnAccessMountPath")->enabled) {
logg("ScanOnAccess: preventing access attempts on malicious files.\n");
fan_mask |= FAN_ACCESS_PERM | FAN_OPEN_PERM;
logg("ScanOnAccess: preventing access attempts on malicious files.\n");
fan_mask |= FAN_ACCESS_PERM | FAN_OPEN_PERM;
} else {
logg("ScanOnAccess: notifying only for access attempts.\n");
fan_mask |= FAN_ACCESS | FAN_OPEN;
logg("ScanOnAccess: notifying only for access attempts.\n");
fan_mask |= FAN_ACCESS | FAN_OPEN;
}
if ((pt = optget(tharg->opts, "OnAccessMountPath"))->enabled) {
while(pt) {
if(fanotify_mark(onas_fan_fd, FAN_MARK_ADD | FAN_MARK_MOUNT, fan_mask, onas_fan_fd, pt->strarg) != 0) {
logg("!ScanOnAccess: Can't include mountpoint '%s'\n", pt->strarg);
return NULL;
} else
logg("ScanOnAccess: Protecting '%s' and rest of mount.\n", pt->strarg);
pt = (struct optstruct *) pt->nextarg;
}
while (pt) {
if (fanotify_mark(onas_fan_fd, FAN_MARK_ADD | FAN_MARK_MOUNT, fan_mask, onas_fan_fd, pt->strarg) != 0) {
logg("!ScanOnAccess: Can't include mountpoint '%s'\n", pt->strarg);
return NULL;
} else
logg("ScanOnAccess: Protecting '%s' and rest of mount.\n", pt->strarg);
pt = (struct optstruct *)pt->nextarg;
}
} else if (!optget(tharg->opts, "OnAccessDisableDDD")->enabled) {
int thread_started = 1;
do {
if(pthread_attr_init(&ddd_attr)) break;
pthread_attr_setdetachstate(&ddd_attr, PTHREAD_CREATE_JOINABLE);
int thread_started = 1;
do {
if (pthread_attr_init(&ddd_attr)) break;
pthread_attr_setdetachstate(&ddd_attr, PTHREAD_CREATE_JOINABLE);
/* Allocate memory for arguments. Thread is responsible for freeing it. */
if (!(ddd_tharg = (struct ddd_thrarg *) calloc(sizeof(struct ddd_thrarg), 1))) break;
if (!(ddd_tharg->options = (struct cl_scan_options *) calloc(sizeof(struct cl_scan_options), 1))) break;
/* Allocate memory for arguments. Thread is responsible for freeing it. */
if (!(ddd_tharg = (struct ddd_thrarg *)calloc(sizeof(struct ddd_thrarg), 1))) break;
if (!(ddd_tharg->options = (struct cl_scan_options *)calloc(sizeof(struct cl_scan_options), 1))) break;
(void) memcpy(ddd_tharg->options, tharg->options, sizeof(struct cl_scan_options));
ddd_tharg->fan_fd = onas_fan_fd;
ddd_tharg->fan_mask = fan_mask;
ddd_tharg->opts = tharg->opts;
ddd_tharg->engine = tharg->engine;
(void)memcpy(ddd_tharg->options, tharg->options, sizeof(struct cl_scan_options));
ddd_tharg->fan_fd = onas_fan_fd;
ddd_tharg->fan_mask = fan_mask;
ddd_tharg->opts = tharg->opts;
ddd_tharg->engine = tharg->engine;
thread_started = pthread_create(&ddd_pid, &ddd_attr, onas_ddd_th, ddd_tharg);
} while(0);
thread_started = pthread_create(&ddd_pid, &ddd_attr, onas_ddd_th, ddd_tharg);
} while (0);
if (0 != thread_started) {
/* Failed to create thread. Free anything we may have allocated. */
logg("!Unable to start dynamic directory determination.\n");
if (NULL != ddd_tharg) {
if (NULL != ddd_tharg->options) {
free(ddd_tharg->options);
ddd_tharg->options = NULL;
}
free(ddd_tharg);
ddd_tharg = NULL;
}
}
if (0 != thread_started) {
/* Failed to create thread. Free anything we may have allocated. */
logg("!Unable to start dynamic directory determination.\n");
if (NULL != ddd_tharg) {
if (NULL != ddd_tharg->options) {
free(ddd_tharg->options);
ddd_tharg->options = NULL;
}
free(ddd_tharg);
ddd_tharg = NULL;
}
}
} else {
if((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) {
while(pt) {
if(fanotify_mark(onas_fan_fd, FAN_MARK_ADD, fan_mask, onas_fan_fd, pt->strarg) != 0) {
logg("!ScanOnAccess: Can't include path '%s'\n", pt->strarg);
return NULL;
} else
logg("ScanOnAccess: Protecting directory '%s'\n", pt->strarg);
pt = (struct optstruct *) pt->nextarg;
}
} else {
logg("!ScanOnAccess: Please specify at least one path with OnAccessIncludePath\n");
return NULL;
}
if ((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) {
while (pt) {
if (fanotify_mark(onas_fan_fd, FAN_MARK_ADD, fan_mask, onas_fan_fd, pt->strarg) != 0) {
logg("!ScanOnAccess: Can't include path '%s'\n", pt->strarg);
return NULL;
} else
logg("ScanOnAccess: Protecting directory '%s'\n", pt->strarg);
pt = (struct optstruct *)pt->nextarg;
}
} else {
logg("!ScanOnAccess: Please specify at least one path with OnAccessIncludePath\n");
return NULL;
}
}
/* Load other options. */
sizelimit = optget(tharg->opts, "OnAccessMaxFileSize")->numarg;
if(sizelimit)
logg("ScanOnAccess: Max file size limited to %u bytes\n", sizelimit);
if (sizelimit)
logg("ScanOnAccess: Max file size limited to %u bytes\n", sizelimit);
else
logg("ScanOnAccess: File size limit disabled\n");
logg("ScanOnAccess: File size limit disabled\n");
extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled;
FD_ZERO(&rfds);
FD_SET(onas_fan_fd, &rfds);
do {
if (reload) sleep(1);
if (reload) sleep(1);
ret = select(onas_fan_fd + 1, &rfds, NULL, NULL, NULL);
} while((ret == -1 && errno == EINTR) || reload);
} while ((ret == -1 && errno == EINTR) || reload);
time_t start = time(NULL) - 30;
while(((bread = read(onas_fan_fd, buf, sizeof(buf))) > 0) || errno == EOVERFLOW) {
while (((bread = read(onas_fan_fd, buf, sizeof(buf))) > 0) || errno == EOVERFLOW) {
if (errno == EOVERFLOW) {
if (time(NULL) - start >= 30) {
logg("!ScanOnAccess: Internal error (failed to read data) ... %s\n", strerror(errno));
logg("!ScanOnAccess: File too large for fanotify ... recovering and continuing scans...\n");
start = time(NULL);
}
if (errno == EOVERFLOW) {
if (time(NULL) - start >= 30) {
logg("!ScanOnAccess: Internal error (failed to read data) ... %s\n", strerror(errno));
logg("!ScanOnAccess: File too large for fanotify ... recovering and continuing scans...\n");
start = time(NULL);
}
errno = 0;
continue;
}
errno = 0;
continue;
}
fmd = (struct fanotify_event_metadata *) buf;
while(FAN_EVENT_OK(fmd, bread)) {
scan = 1;
if(fmd->fd >= 0) {
sprintf(fname, "/proc/self/fd/%d", fmd->fd);
len = readlink(fname, fname, sizeof(fname) - 1);
if(len == -1) {
close(fmd->fd);
logg("!ScanOnAccess: Internal error (readlink() failed)\n");
return NULL;
}
fname[len] = 0;
fmd = (struct fanotify_event_metadata *)buf;
while (FAN_EVENT_OK(fmd, bread)) {
scan = 1;
if (fmd->fd >= 0) {
sprintf(fname, "/proc/self/fd/%d", fmd->fd);
len = readlink(fname, fname, sizeof(fname) - 1);
if (len == -1) {
close(fmd->fd);
logg("!ScanOnAccess: Internal error (readlink() failed)\n");
return NULL;
}
fname[len] = 0;
if((check = onas_fan_checkowner(fmd->pid, tharg->opts))) {
scan = 0;
/* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
#if 0
if ((check = onas_fan_checkowner(fmd->pid, tharg->opts))) {
scan = 0;
/* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
#if 0
if ((check != CHK_SELF) || !(optget(tharg->opts, "OnAccessExtraScanning")->enabled)) {
#else
if (check != CHK_SELF) {
#endif
logg("*ScanOnAccess: %s skipped (excluded UID)\n", fname);
}
}
#else
if (check != CHK_SELF) {
#endif
logg("*ScanOnAccess: %s skipped (excluded UID)\n", fname);
}
}
if(sizelimit) {
if(FSTAT(fmd->fd, &sb) != 0 || sb.st_size > sizelimit) {
scan = 0;
/* logg("*ScanOnAccess: %s skipped (size > %d)\n", fname, sizelimit); */
}
}
if (sizelimit) {
if (FSTAT(fmd->fd, &sb) != 0 || sb.st_size > sizelimit) {
scan = 0;
/* logg("*ScanOnAccess: %s skipped (size > %d)\n", fname, sizelimit); */
}
}
if(onas_fan_scanfile(onas_fan_fd, fname, fmd, scan, extinfo, tharg) == -1) {
close(fmd->fd);
return NULL;
}
if (onas_fan_scanfile(onas_fan_fd, fname, fmd, scan, extinfo, tharg) == -1) {
close(fmd->fd);
return NULL;
}
if(close(fmd->fd) == -1) {
printf("!ScanOnAccess: Internal error (close(%d) failed)\n", fmd->fd);
close(fmd->fd);
return NULL;
}
}
fmd = FAN_EVENT_NEXT(fmd, bread);
}
do {
if (reload) sleep(1);
ret = select(onas_fan_fd + 1, &rfds, NULL, NULL, NULL);
} while((ret == -1 && errno == EINTR) || reload);
if (close(fmd->fd) == -1) {
printf("!ScanOnAccess: Internal error (close(%d) failed)\n", fmd->fd);
close(fmd->fd);
return NULL;
}
}
fmd = FAN_EVENT_NEXT(fmd, bread);
}
if(bread < 0)
logg("!ScanOnAccess: Internal error (failed to read data) ... %s\n", strerror(errno));
return NULL;
do {
if (reload) sleep(1);
ret = select(onas_fan_fd + 1, &rfds, NULL, NULL, NULL);
} while ((ret == -1 && errno == EINTR) || reload);
}
if (bread < 0)
logg("!ScanOnAccess: Internal error (failed to read data) ... %s\n", strerror(errno));
return NULL;
}
/* CLAMAUTH is deprecated */
#elif defined(CLAMAUTH)
@ -331,7 +328,7 @@ void *onas_fan_th(void *arg)
#include "others.h"
#include "scanner.h"
#define SUPPORTED_PROTOCOL 2
#define SUPPORTED_PROTOCOL 2
static int cauth_fd = -1;
@ -344,32 +341,32 @@ struct ClamAuthEvent {
static void cauth_exit(int sig)
{
logg("*ScanOnAccess: cauth_exit(), signal %d\n", sig);
if(cauth_fd > 0)
close(cauth_fd);
if (cauth_fd > 0)
close(cauth_fd);
pthread_exit(NULL);
logg("ScanOnAccess: stopped\n");
}
static int cauth_scanfile(const char *fname, int extinfo, struct thrarg *tharg)
{
struct cb_context context;
const char *virname = NULL;
int ret = 0, fd;
struct cb_context context;
const char *virname = NULL;
int ret = 0, fd;
context.filename = fname;
context.virsize = 0;
context.virsize = 0;
context.scandata = NULL;
fd = open(fname, O_RDONLY);
if(fd == -1)
return -1;
if (fd == -1)
return -1;
if(cl_scandesc_callback(fd, fname, &virname, NULL, tharg->engine, tharg->options, &context) == CL_VIRUS) {
if(extinfo && context.virsize)
logg("ScanOnAccess: %s: %s(%s:%llu) FOUND\n", fname, virname, context.virhash, context.virsize);
else
logg("ScanOnAccess: %s: %s FOUND\n", fname, virname);
virusaction(fname, virname, tharg->opts);
if (cl_scandesc_callback(fd, fname, &virname, NULL, tharg->engine, tharg->options, &context) == CL_VIRUS) {
if (extinfo && context.virsize)
logg("ScanOnAccess: %s: %s(%s:%llu) FOUND\n", fname, virname, context.virhash, context.virsize);
else
logg("ScanOnAccess: %s: %s FOUND\n", fname, virname);
virusaction(fname, virname, tharg->opts);
}
close(fd);
return ret;
@ -377,12 +374,12 @@ static int cauth_scanfile(const char *fname, int extinfo, struct thrarg *tharg)
void *onas_fan_th(void *arg)
{
struct thrarg *tharg = (struct thrarg *) arg;
sigset_t sigset;
struct sigaction act;
int eventcnt = 1, extinfo;
char err[128];
struct ClamAuthEvent event;
struct thrarg *tharg = (struct thrarg *)arg;
sigset_t sigset;
struct sigaction act;
int eventcnt = 1, extinfo;
char err[128];
struct ClamAuthEvent event;
/* ignore all signals except SIGUSR1 */
sigfillset(&sigset);
@ -405,44 +402,44 @@ void *onas_fan_th(void *arg)
extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled;
cauth_fd = open("/dev/clamauth", O_RDONLY);
if(cauth_fd == -1) {
logg("!ScanOnAccess: Can't open /dev/clamauth\n");
if(errno == ENOENT)
logg("!ScanOnAccess: Please make sure ClamAuth.kext is loaded\n");
else if(errno == EACCES)
logg("!ScanOnAccess: This application requires root privileges\n");
else
logg("!ScanOnAccess: /dev/clamauth: %s\n", cli_strerror(errno, err, sizeof(err)));
if (cauth_fd == -1) {
logg("!ScanOnAccess: Can't open /dev/clamauth\n");
if (errno == ENOENT)
logg("!ScanOnAccess: Please make sure ClamAuth.kext is loaded\n");
else if (errno == EACCES)
logg("!ScanOnAccess: This application requires root privileges\n");
else
logg("!ScanOnAccess: /dev/clamauth: %s\n", cli_strerror(errno, err, sizeof(err)));
return NULL;
return NULL;
}
while(1) {
if(read(cauth_fd, &event, sizeof(event)) > 0) {
if(eventcnt == 1) {
if(event.action != SUPPORTED_PROTOCOL) {
logg("!ScanOnAccess: Protocol version mismatch (tool: %d, driver: %d)\n", SUPPORTED_PROTOCOL, event.action);
close(cauth_fd);
return NULL;
}
if(strncmp(event.path, "ClamAuth", 8)) {
logg("!ScanOnAccess: Invalid version event\n");
close(cauth_fd);
return NULL;
}
logg("ScanOnAccess: Driver version: %s, protocol version: %d\n", &event.path[9], event.action);
} else {
cauth_scanfile(event.path, extinfo, tharg);
}
eventcnt++;
} else {
if(errno == ENODEV) {
printf("^ScanOnAccess: ClamAuth module deactivated, terminating\n");
close(cauth_fd);
return NULL;
}
}
usleep(200);
while (1) {
if (read(cauth_fd, &event, sizeof(event)) > 0) {
if (eventcnt == 1) {
if (event.action != SUPPORTED_PROTOCOL) {
logg("!ScanOnAccess: Protocol version mismatch (tool: %d, driver: %d)\n", SUPPORTED_PROTOCOL, event.action);
close(cauth_fd);
return NULL;
}
if (strncmp(event.path, "ClamAuth", 8)) {
logg("!ScanOnAccess: Invalid version event\n");
close(cauth_fd);
return NULL;
}
logg("ScanOnAccess: Driver version: %s, protocol version: %d\n", &event.path[9], event.action);
} else {
cauth_scanfile(event.path, extinfo, tharg);
}
eventcnt++;
} else {
if (errno == ENODEV) {
printf("^ScanOnAccess: ClamAuth module deactivated, terminating\n");
close(cauth_fd);
return NULL;
}
}
usleep(200);
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -22,71 +22,70 @@
#ifndef __ONAS_HASH_H
#define __ONAS_HASH_H
#define ONAS_FANWATCH 0x1
#define ONAS_INWATCH 0x2
#define ONAS_FANWATCH 0x1
#define ONAS_INWATCH 0x2
#define ONAS_STOPWATCH 0x3
#define ONAS_DEFAULT_HT_SIZE 1 << 18
struct onas_element {
const char* key;
size_t klen;
struct onas_hnode *data;
const char *key;
size_t klen;
struct onas_hnode *data;
struct onas_element *next;
struct onas_element *prev;
struct onas_element *next;
struct onas_element *prev;
};
struct onas_bucket {
uint32_t size;
uint32_t size;
struct onas_element *head;
struct onas_element *tail;
struct onas_element *head;
struct onas_element *tail;
};
struct onas_ht {
struct onas_bucket **htable;
struct onas_bucket **htable;
/* Must be a sufficiently high power of two--will not grow. */
uint32_t size;
uint32_t nbckts;
/* Must be a sufficiently high power of two--will not grow. */
uint32_t size;
uint32_t nbckts;
};
/* Directory node struct for lists */
struct onas_lnode {
/* List stuffs */
char *dirname;
struct onas_lnode *next;
struct onas_lnode *prev;
/* List stuffs */
char *dirname;
struct onas_lnode *next;
struct onas_lnode *prev;
};
/* Directory node struct for hash tables */
struct onas_hnode {
/* Path info */
int pathlen;
char *pathname;
/* Path info */
int pathlen;
char *pathname;
/* Parent info */
int prnt_pathlen;
char *prnt_pathname;
/* Parent info */
int prnt_pathlen;
char *prnt_pathname;
/* Child head and tail are empty sentinels */
struct onas_lnode *childhead;
struct onas_lnode *childtail;
/* Child head and tail are empty sentinels */
struct onas_lnode *childhead;
struct onas_lnode *childtail;
/* Inotify watch descriptor */
int wd;
/* Inotify watch descriptor */
int wd;
/* Watched stuffs */
uint32_t watched;
/* Watched stuffs */
uint32_t watched;
};
void onas_free_ht(struct onas_ht *ht);
int onas_ht_init(struct onas_ht **ht, uint32_t table_size);
int onas_ht_insert(struct onas_ht *ht, struct onas_element *elem);

View file

@ -51,37 +51,36 @@ int onas_fan_checkowner(int pid, const struct optstruct *opts)
{
char path[32];
STATBUF sb;
const struct optstruct *opt = NULL;
const struct optstruct *opt = NULL;
const struct optstruct *opt_root = NULL;
/* always ignore ourselves */
if (pid == (int) getpid()) {
if (pid == (int)getpid()) {
return CHK_SELF;
}
/* look up options */
opt = optget (opts, "OnAccessExcludeUID");
opt_root = optget (opts, "OnAccessExcludeRootUID");
opt = optget(opts, "OnAccessExcludeUID");
opt_root = optget(opts, "OnAccessExcludeRootUID");
/* we can return immediately if no uid exclusions were requested */
if (!(opt->enabled || opt_root->enabled))
return CHK_CLEAN;
/* perform exclusion checks if we can stat OK */
snprintf (path, sizeof (path), "/proc/%u", pid);
if (CLAMSTAT (path, &sb) == 0) {
snprintf(path, sizeof(path), "/proc/%u", pid);
if (CLAMSTAT(path, &sb) == 0) {
/* check all our non-root UIDs first */
if (opt->enabled) {
while (opt)
{
if (opt->numarg == (long long) sb.st_uid)
while (opt) {
if (opt->numarg == (long long)sb.st_uid)
return CHK_FOUND;
opt = opt->nextarg;
}
}
/* finally check root UID */
if (opt_root->enabled) {
if (0 == (long long) sb.st_uid)
if (0 == (long long)sb.st_uid)
return CHK_FOUND;
}
} else if (errno == EACCES) {
@ -102,7 +101,7 @@ int onas_scan(const char *fname, int fd, const char **virname, const struct cl_e
pthread_mutex_lock(&onas_scan_lock);
context.filename = fname;
context.virsize = 0;
context.virsize = 0;
context.scandata = NULL;
ret = cl_scandesc_callback(fd, fname, virname, NULL, engine, options, &context);

View file

@ -42,123 +42,126 @@
#include "libclamav/clamav.h"
static int onas_scth_scanfile(const char *fname, int fd, int extinfo, struct scth_thrarg *tharg);
static int onas_scth_handle_dir(const char *pathname, struct scth_thrarg *tharg);
static int onas_scth_handle_file(const char *pathname, struct scth_thrarg *tharg);
static void onas_scth_exit(int sig);
static void onas_scth_exit(int sig) {
logg("*ScanOnAccess: onas_scth_exit(), signal %d\n", sig);
static void onas_scth_exit(int sig)
{
logg("*ScanOnAccess: onas_scth_exit(), signal %d\n", sig);
pthread_exit(NULL);
pthread_exit(NULL);
}
static int onas_scth_scanfile(const char *fname, int fd, int extinfo, struct scth_thrarg *tharg)
{
int ret = 0;
int ret = 0;
const char *virname = NULL;
return onas_scan(fname, fd, &virname, tharg->engine, tharg->options, extinfo);
}
static int onas_scth_handle_dir(const char *pathname, struct scth_thrarg *tharg) {
FTS *ftsp = NULL;
int fd;
int ftspopts = FTS_PHYSICAL | FTS_XDEV;
int extinfo;
int ret;
FTSENT *curr = NULL;
static int onas_scth_handle_dir(const char *pathname, struct scth_thrarg *tharg)
{
FTS *ftsp = NULL;
int fd;
int ftspopts = FTS_PHYSICAL | FTS_XDEV;
int extinfo;
int ret;
FTSENT *curr = NULL;
extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled;
extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled;
char *const pathargv[] = { (char *) pathname, NULL };
if (!(ftsp = _priv_fts_open(pathargv, ftspopts, NULL))) return CL_EOPEN;
char *const pathargv[] = {(char *)pathname, NULL};
if (!(ftsp = _priv_fts_open(pathargv, ftspopts, NULL))) return CL_EOPEN;
while ((curr = _priv_fts_read(ftsp))) {
if (curr->fts_info != FTS_D) {
if ((fd = safe_open(curr->fts_path, O_RDONLY | O_BINARY)) == -1)
return CL_EOPEN;
while ((curr = _priv_fts_read(ftsp))) {
if (curr->fts_info != FTS_D) {
if ((fd = safe_open(curr->fts_path, O_RDONLY | O_BINARY)) == -1)
return CL_EOPEN;
if (onas_scth_scanfile(curr->fts_path, fd, extinfo, tharg) == CL_VIRUS);
ret = CL_VIRUS;
if (onas_scth_scanfile(curr->fts_path, fd, extinfo, tharg) == CL_VIRUS)
;
ret = CL_VIRUS;
close(fd);
}
}
close(fd);
}
}
return ret;
return ret;
}
static int onas_scth_handle_file(const char *pathname, struct scth_thrarg *tharg)
{
int fd;
int extinfo;
int ret;
static int onas_scth_handle_file(const char *pathname, struct scth_thrarg *tharg) {
int fd;
int extinfo;
int ret;
if (!pathname) return CL_ENULLARG;
if (!pathname) return CL_ENULLARG;
extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled;
extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled;
if ((fd = safe_open(pathname, O_RDONLY | O_BINARY)) == -1)
return CL_EOPEN;
ret = onas_scth_scanfile(pathname, fd, extinfo, tharg);
if ((fd = safe_open(pathname, O_RDONLY | O_BINARY)) == -1)
return CL_EOPEN;
ret = onas_scth_scanfile(pathname, fd, extinfo, tharg);
close(fd);
close(fd);
return ret;
return ret;
}
void *onas_scan_th(void *arg) {
struct scth_thrarg *tharg = (struct scth_thrarg *) arg;
sigset_t sigset;
struct sigaction act;
void *onas_scan_th(void *arg)
{
struct scth_thrarg *tharg = (struct scth_thrarg *)arg;
sigset_t sigset;
struct sigaction act;
/* ignore all signals except SIGUSR1 */
sigfillset(&sigset);
sigdelset(&sigset, SIGUSR1);
/* The behavior of a process is undefined after it ignores a
/* ignore all signals except SIGUSR1 */
sigfillset(&sigset);
sigdelset(&sigset, SIGUSR1);
/* The behavior of a process is undefined after it ignores a
* SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
sigdelset(&sigset, SIGFPE);
sigdelset(&sigset, SIGILL);
sigdelset(&sigset, SIGSEGV);
sigdelset(&sigset, SIGFPE);
sigdelset(&sigset, SIGILL);
sigdelset(&sigset, SIGSEGV);
#ifdef SIGBUS
sigdelset(&sigset, SIGBUS);
sigdelset(&sigset, SIGBUS);
#endif
pthread_sigmask(SIG_SETMASK, &sigset, NULL);
memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = onas_scth_exit;
sigfillset(&(act.sa_mask));
sigaction(SIGUSR1, &act, NULL);
sigaction(SIGSEGV, &act, NULL);
pthread_sigmask(SIG_SETMASK, &sigset, NULL);
memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = onas_scth_exit;
sigfillset(&(act.sa_mask));
sigaction(SIGUSR1, &act, NULL);
sigaction(SIGSEGV, &act, NULL);
if (NULL == tharg || NULL == tharg->pathname || NULL == tharg->opts || NULL == tharg->engine) {
logg("ScanOnAccess: Invalid thread arguments for extra scanning\n");
goto done;
}
if (NULL == tharg || NULL == tharg->pathname || NULL == tharg->opts || NULL == tharg->engine) {
logg("ScanOnAccess: Invalid thread arguments for extra scanning\n");
goto done;
}
if (tharg->extra_options & ONAS_SCTH_ISDIR) {
logg("*ScanOnAccess: Performing additional scanning on directory '%s'\n", tharg->pathname);
onas_scth_handle_dir(tharg->pathname, tharg);
} else if (tharg->extra_options & ONAS_SCTH_ISFILE) {
logg("*ScanOnAccess: Performing additional scanning on file '%s'\n", tharg->pathname);
onas_scth_handle_file(tharg->pathname, tharg);
}
if (tharg->extra_options & ONAS_SCTH_ISDIR) {
logg("*ScanOnAccess: Performing additional scanning on directory '%s'\n", tharg->pathname);
onas_scth_handle_dir(tharg->pathname, tharg);
} else if (tharg->extra_options & ONAS_SCTH_ISFILE) {
logg("*ScanOnAccess: Performing additional scanning on file '%s'\n", tharg->pathname);
onas_scth_handle_file(tharg->pathname, tharg);
}
done:
if (NULL != tharg->pathname){
free(tharg->pathname);
tharg->pathname = NULL;
}
if (NULL != tharg->options) {
free(tharg->options);
tharg->options = NULL;
}
if (NULL != tharg) {
free(tharg);
}
if (NULL != tharg->pathname) {
free(tharg->pathname);
tharg->pathname = NULL;
}
if (NULL != tharg->options) {
free(tharg->options);
tharg->options = NULL;
}
if (NULL != tharg) {
free(tharg);
}
return NULL;
return NULL;
}
#endif

View file

@ -24,15 +24,15 @@
#include "shared/optparser.h"
#include "libclamav/clamav.h"
#define ONAS_SCTH_ISDIR 0x01
#define ONAS_SCTH_ISDIR 0x01
#define ONAS_SCTH_ISFILE 0x02
struct scth_thrarg {
uint32_t extra_options;
struct cl_scan_options *options;
const struct optstruct *opts;
const struct cl_engine *engine;
char *pathname;
uint32_t extra_options;
struct cl_scan_options *options;
const struct optstruct *opts;
const struct cl_engine *engine;
char *pathname;
};
void *onas_scan_th(void *arg);

View file

@ -29,14 +29,14 @@
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#include <errno.h>
#ifndef _WIN32
#ifndef _WIN32
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/socket.h>
@ -84,23 +84,21 @@ static void xfree(void *p)
free(p);
}
#ifdef _WIN32
void
virusaction (const char *filename, const char *virname,
const struct optstruct *opts)
#ifdef _WIN32
void virusaction(const char *filename, const char *virname,
const struct optstruct *opts)
{
if (optget (opts, "VirusEvent")->enabled)
logg ("^VirusEvent is not supported on this platform"); /* Yet */
if (optget(opts, "VirusEvent")->enabled)
logg("^VirusEvent is not supported on this platform"); /* Yet */
}
#else
#define VE_FILENAME "CLAM_VIRUSEVENT_FILENAME"
#define VE_FILENAME "CLAM_VIRUSEVENT_FILENAME"
#define VE_VIRUSNAME "CLAM_VIRUSEVENT_VIRUSNAME"
void
virusaction (const char *filename, const char *virname,
const struct optstruct *opts)
void virusaction(const char *filename, const char *virname,
const struct optstruct *opts)
{
pid_t pid;
const struct optstruct *opt;
@ -109,132 +107,113 @@ virusaction (const char *filename, const char *virname,
size_t i, j, v = 0, len;
char *env[4];
if (!(opt = optget (opts, "VirusEvent"))->enabled)
if (!(opt = optget(opts, "VirusEvent"))->enabled)
return;
path = getenv ("PATH");
path = getenv("PATH");
env[0] = path ? strdup(path) : NULL;
j = env[0] ? 1 : 0;
j = env[0] ? 1 : 0;
/* Allocate env vars.. to be portable env vars should not be freed */
buffer_file =
(char *) malloc (strlen (VE_FILENAME) + strlen (filename) + 2);
if (buffer_file)
{
sprintf (buffer_file, "%s=%s", VE_FILENAME, filename);
(char *)malloc(strlen(VE_FILENAME) + strlen(filename) + 2);
if (buffer_file) {
sprintf(buffer_file, "%s=%s", VE_FILENAME, filename);
env[j++] = buffer_file;
}
buffer_vir =
(char *) malloc (strlen (VE_VIRUSNAME) + strlen (virname) + 2);
if (buffer_vir)
{
sprintf (buffer_vir, "%s=%s", VE_VIRUSNAME, virname);
(char *)malloc(strlen(VE_VIRUSNAME) + strlen(virname) + 2);
if (buffer_vir) {
sprintf(buffer_vir, "%s=%s", VE_VIRUSNAME, virname);
env[j++] = buffer_vir;
}
env[j++] = NULL;
pt = opt->strarg;
while ((pt = strstr (pt, "%v")))
{
while ((pt = strstr(pt, "%v"))) {
pt += 2;
v++;
}
len = strlen (opt->strarg);
len = strlen(opt->strarg);
buffer_cmd =
(char *) calloc (len + v * strlen (virname) + 1, sizeof (char));
if (!buffer_cmd)
{
(char *)calloc(len + v * strlen(virname) + 1, sizeof(char));
if (!buffer_cmd) {
if (path)
xfree(env[0]);
xfree (buffer_file);
xfree (buffer_vir);
xfree(buffer_file);
xfree(buffer_vir);
return;
}
for (i = 0, j = 0; i < len; i++)
{
if (i + 1 < len && opt->strarg[i] == '%' && opt->strarg[i + 1] == 'v')
{
strcat (buffer_cmd, virname);
j += strlen (virname);
for (i = 0, j = 0; i < len; i++) {
if (i + 1 < len && opt->strarg[i] == '%' && opt->strarg[i + 1] == 'v') {
strcat(buffer_cmd, virname);
j += strlen(virname);
i++;
}
else
{
} else {
buffer_cmd[j++] = opt->strarg[i];
}
}
pthread_mutex_lock (&virusaction_lock);
pthread_mutex_lock(&virusaction_lock);
/* We can only call async-signal-safe functions after fork(). */
pid = fork ();
if (pid == 0)
{ /* child */
exit (execle ("/bin/sh", "sh", "-c", buffer_cmd, NULL, env));
}
else if (pid > 0)
{ /* parent */
pthread_mutex_unlock (&virusaction_lock);
while (waitpid (pid, NULL, 0) == -1 && errno == EINTR) continue;
}
else
{
pid = fork();
if (pid == 0) { /* child */
exit(execle("/bin/sh", "sh", "-c", buffer_cmd, NULL, env));
} else if (pid > 0) { /* parent */
pthread_mutex_unlock(&virusaction_lock);
logg ("!VirusEvent: fork failed.\n");
while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) continue;
} else {
pthread_mutex_unlock(&virusaction_lock);
logg("!VirusEvent: fork failed.\n");
}
if (path)
xfree(env[0]);
xfree (buffer_cmd);
xfree (buffer_file);
xfree (buffer_vir);
xfree(buffer_cmd);
xfree(buffer_file);
xfree(buffer_vir);
}
#endif /* _WIN32 */
/* Function: writen
Try hard to write the specified number of bytes
*/
int
writen (int fd, void *buff, unsigned int count)
int writen(int fd, void *buff, unsigned int count)
{
int retval;
unsigned int todo;
unsigned char *current;
todo = count;
current = (unsigned char *) buff;
todo = count;
current = (unsigned char *)buff;
do
{
retval = write (fd, current, todo);
if (retval < 0)
{
if (errno == EINTR)
{
do {
retval = write(fd, current, todo);
if (retval < 0) {
if (errno == EINTR) {
continue;
}
return -1;
}
todo -= retval;
current += retval;
}
while (todo > 0);
} while (todo > 0);
return count;
}
static int
realloc_polldata (struct fd_data *data)
realloc_polldata(struct fd_data *data)
{
#ifdef HAVE_POLL
if (data->poll_data_nfds == data->nfds)
return 0;
if (data->poll_data)
free (data->poll_data);
data->poll_data = malloc (data->nfds * sizeof (*data->poll_data));
if (!data->poll_data)
{
logg ("!realloc_polldata: Memory allocation failed for poll_data\n");
free(data->poll_data);
data->poll_data = malloc(data->nfds * sizeof(*data->poll_data));
if (!data->poll_data) {
logg("!realloc_polldata: Memory allocation failed for poll_data\n");
return -1;
}
data->poll_data_nfds = data->nfds;
@ -242,35 +221,29 @@ realloc_polldata (struct fd_data *data)
return 0;
}
int
poll_fd (int fd, int timeout_sec, int check_signals)
int poll_fd(int fd, int timeout_sec, int check_signals)
{
int ret;
struct fd_data fds = FDS_INIT (NULL);
struct fd_data fds = FDS_INIT(NULL);
if (fds_add (&fds, fd, 1, timeout_sec) == -1)
if (fds_add(&fds, fd, 1, timeout_sec) == -1)
return -1;
do
{
ret = fds_poll_recv (&fds, timeout_sec, check_signals, NULL);
}
while (ret == -1 && errno == EINTR);
fds_free (&fds);
do {
ret = fds_poll_recv(&fds, timeout_sec, check_signals, NULL);
} while (ret == -1 && errno == EINTR);
fds_free(&fds);
return ret;
}
void
fds_cleanup (struct fd_data *data)
void fds_cleanup(struct fd_data *data)
{
struct fd_buf *newbuf;
unsigned i, j;
for (i = 0, j = 0; i < data->nfds; i++)
{
if (data->buf[i].fd < 0)
{
for (i = 0, j = 0; i < data->nfds; i++) {
if (data->buf[i].fd < 0) {
if (data->buf[i].buffer)
free (data->buf[i].buffer);
free(data->buf[i].buffer);
continue;
}
if (i != j)
@ -282,29 +255,29 @@ fds_cleanup (struct fd_data *data)
for (i = j; i < data->nfds; i++)
data->buf[i].fd = -1;
data->nfds = j;
logg ("$Number of file descriptors polled: %u fds\n",
(unsigned) data->nfds);
logg("$Number of file descriptors polled: %u fds\n",
(unsigned)data->nfds);
/* Shrink buffer */
newbuf = realloc (data->buf, j * sizeof (*newbuf));
newbuf = realloc(data->buf, j * sizeof(*newbuf));
if (!j)
data->buf = NULL;
else if (newbuf)
data->buf = newbuf; /* non-fatal if shrink fails */
data->buf = newbuf; /* non-fatal if shrink fails */
}
static int
read_fd_data (struct fd_buf *buf)
read_fd_data(struct fd_buf *buf)
{
ssize_t n;
buf->got_newdata = 1;
if (!buf->buffer) /* listen-only socket */
if (!buf->buffer) /* listen-only socket */
return 1;
if (buf->off >= buf->bufsize)
return -1;
/* Read the pending packet, it may contain more than one command, but
/* Read the pending packet, it may contain more than one command, but
* that is to the cmdparser to handle.
* It will handle 1st command, and then move leftover to beginning of buffer
*/
@ -312,69 +285,62 @@ read_fd_data (struct fd_buf *buf)
{
struct msghdr msg;
struct cmsghdr *cmsg;
union
{
unsigned char buff[CMSG_SPACE (sizeof (int))];
union {
unsigned char buff[CMSG_SPACE(sizeof(int))];
struct cmsghdr hdr;
} b;
struct iovec iov[1];
if (buf->recvfd != -1)
{
logg ("$Closing unclaimed FD: %d\n", buf->recvfd);
close (buf->recvfd);
if (buf->recvfd != -1) {
logg("$Closing unclaimed FD: %d\n", buf->recvfd);
close(buf->recvfd);
buf->recvfd = -1;
}
memset (&msg, 0, sizeof (msg));
iov[0].iov_base = buf->buffer + buf->off;
iov[0].iov_len = buf->bufsize - buf->off;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control = b.buff;
msg.msg_controllen = sizeof (b.buff);
memset(&msg, 0, sizeof(msg));
iov[0].iov_base = buf->buffer + buf->off;
iov[0].iov_len = buf->bufsize - buf->off;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control = b.buff;
msg.msg_controllen = sizeof(b.buff);
n = recvmsg (buf->fd, &msg, 0);
n = recvmsg(buf->fd, &msg, 0);
if (n < 0)
return -1;
if (msg.msg_flags & MSG_TRUNC)
{
logg ("^Message truncated at %d bytes\n", (int) n);
if (msg.msg_flags & MSG_TRUNC) {
logg("^Message truncated at %d bytes\n", (int)n);
return -1;
}
if (msg.msg_flags & MSG_CTRUNC)
{
if (msg.msg_flags & MSG_CTRUNC) {
if (msg.msg_controllen > 0)
logg ("^Control message truncated at %d bytes, %d data read\n", (int) msg.msg_controllen, (int) n);
logg("^Control message truncated at %d bytes, %d data read\n", (int)msg.msg_controllen, (int)n);
else
logg ("^Control message truncated, no control data received, %d bytes read"
logg("^Control message truncated, no control data received, %d bytes read"
#ifdef C_LINUX
"(Is SELinux/AppArmor enabled, and blocking file descriptor passing?)"
"(Is SELinux/AppArmor enabled, and blocking file descriptor passing?)"
#endif
"\n", (int) n);
"\n",
(int)n);
return -1;
}
if (msg.msg_controllen)
{
for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL;
cmsg = CMSG_NXTHDR (&msg, cmsg))
{
if (cmsg->cmsg_len == CMSG_LEN (sizeof (int)) &&
if (msg.msg_controllen) {
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)) &&
cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS)
{
if (buf->recvfd != -1)
{
logg ("$Unclaimed file descriptor received. closing: %d\n", buf->recvfd);
close (buf->recvfd);
cmsg->cmsg_type == SCM_RIGHTS) {
if (buf->recvfd != -1) {
logg("$Unclaimed file descriptor received. closing: %d\n", buf->recvfd);
close(buf->recvfd);
}
buf->recvfd = *(int *) CMSG_DATA (cmsg);
logg ("$Receveived a file descriptor: %d\n", buf->recvfd);
buf->recvfd = *(int *)CMSG_DATA(cmsg);
logg("$Receveived a file descriptor: %d\n", buf->recvfd);
}
}
}
}
#else
n = recv (buf->fd, buf->buffer + buf->off, buf->bufsize - buf->off, 0);
n = recv(buf->fd, buf->buffer + buf->off, buf->bufsize - buf->off, 0);
if (n < 0)
return -1;
#endif
@ -383,120 +349,104 @@ read_fd_data (struct fd_buf *buf)
}
static int
buf_init (struct fd_buf *buf, int listen_only, int timeout)
buf_init(struct fd_buf *buf, int listen_only, int timeout)
{
buf->off = 0;
buf->off = 0;
buf->got_newdata = 0;
buf->recvfd = -1;
buf->mode = MODE_COMMAND;
buf->id = 0;
buf->dumpfd = -1;
buf->chunksize = 0;
buf->quota = 0;
buf->dumpname = NULL;
buf->group = NULL;
buf->term = '\0';
if (!listen_only)
{
if (!buf->buffer)
{
buf->recvfd = -1;
buf->mode = MODE_COMMAND;
buf->id = 0;
buf->dumpfd = -1;
buf->chunksize = 0;
buf->quota = 0;
buf->dumpname = NULL;
buf->group = NULL;
buf->term = '\0';
if (!listen_only) {
if (!buf->buffer) {
buf->bufsize = PATH_MAX + 8;
/* plus extra space for a \0 so we can make sure every command is \0
* terminated */
if (!(buf->buffer = malloc (buf->bufsize + 1)))
{
logg ("!add_fd: Memory allocation failed for command buffer\n");
if (!(buf->buffer = malloc(buf->bufsize + 1))) {
logg("!add_fd: Memory allocation failed for command buffer\n");
return -1;
}
}
}
else
{
} else {
if (buf->buffer)
free (buf->buffer);
free(buf->buffer);
buf->bufsize = 0;
buf->buffer = NULL;
buf->buffer = NULL;
}
if (timeout)
{
time (&buf->timeout_at);
if (timeout) {
time(&buf->timeout_at);
buf->timeout_at += timeout;
}
else
{
} else {
buf->timeout_at = 0;
}
return 0;
}
int
fds_add (struct fd_data *data, int fd, int listen_only, int timeout)
int fds_add(struct fd_data *data, int fd, int listen_only, int timeout)
{
struct fd_buf *buf;
unsigned n;
if (fd < 0)
{
logg ("!add_fd: invalid fd passed to add_fd\n");
if (fd < 0) {
logg("!add_fd: invalid fd passed to add_fd\n");
return -1;
}
/* we may already have this fd, if
* the old FD got closed, and the kernel reused the FD */
for (n = 0; n < data->nfds; n++)
if (data->buf[n].fd == fd)
{
if (data->buf[n].fd == fd) {
/* clear stale data in buffer */
if (buf_init (&data->buf[n], listen_only, timeout) < 0)
if (buf_init(&data->buf[n], listen_only, timeout) < 0)
return -1;
return 0;
}
n++;
buf = realloc (data->buf, n * sizeof (*buf));
if (!buf)
{
logg ("!add_fd: Memory allocation failed for fd_buf\n");
buf = realloc(data->buf, n * sizeof(*buf));
if (!buf) {
logg("!add_fd: Memory allocation failed for fd_buf\n");
return -1;
}
data->buf = buf;
data->nfds = n;
data->buf = buf;
data->nfds = n;
data->buf[n - 1].buffer = NULL;
if (buf_init (&data->buf[n - 1], listen_only, timeout) < 0)
if (buf_init(&data->buf[n - 1], listen_only, timeout) < 0)
return -1;
data->buf[n - 1].fd = fd;
return 0;
}
static inline void
fds_lock (struct fd_data *data)
fds_lock(struct fd_data *data)
{
if (data->buf_mutex)
pthread_mutex_lock (data->buf_mutex);
pthread_mutex_lock(data->buf_mutex);
}
static inline void
fds_unlock (struct fd_data *data)
fds_unlock(struct fd_data *data)
{
if (data->buf_mutex)
pthread_mutex_unlock (data->buf_mutex);
pthread_mutex_unlock(data->buf_mutex);
}
void
fds_remove (struct fd_data *data, int fd)
void fds_remove(struct fd_data *data, int fd)
{
size_t i;
fds_lock (data);
if (data->buf)
{
for (i = 0; i < data->nfds; i++)
{
if (data->buf[i].fd == fd)
{
fds_lock(data);
if (data->buf) {
for (i = 0; i < data->nfds; i++) {
if (data->buf[i].fd == fd) {
data->buf[i].fd = -1;
break;
}
}
}
fds_unlock (data);
fds_unlock(data);
}
#define BUFFSIZE 1024
@ -509,9 +459,8 @@ fds_remove (struct fd_data *data, int fd)
* Must be called with buf_mutex lock held.
*/
/* TODO: handle ReadTimeout */
int
fds_poll_recv (struct fd_data *data, int timeout, int check_signals,
void *event)
int fds_poll_recv(struct fd_data *data, int timeout, int check_signals,
void *event)
{
unsigned fdsok = data->nfds;
size_t i;
@ -521,33 +470,28 @@ fds_poll_recv (struct fd_data *data, int timeout, int check_signals,
UNUSEDPARAM(event);
/* we must have at least one fd, the control fd! */
fds_cleanup (data);
fds_cleanup(data);
#ifndef _WIN32
if (!data->nfds)
return 0;
#endif
for (i = 0; i < data->nfds; i++)
{
for (i = 0; i < data->nfds; i++) {
data->buf[i].got_newdata = 0;
}
time (&now);
time(&now);
if (timeout > 0)
closest_timeout = now + timeout;
else
closest_timeout = 0;
for (i = 0; i < data->nfds; i++)
{
for (i = 0; i < data->nfds; i++) {
time_t timeout_at = data->buf[i].timeout_at;
if (timeout_at && timeout_at < now)
{
if (timeout_at && timeout_at < now) {
/* timed out */
data->buf[i].got_newdata = -2;
/* we must return immediately from poll/select, we have a timeout! */
closest_timeout = now;
}
else
{
} else {
if (!closest_timeout)
closest_timeout = timeout_at;
else if (timeout_at && timeout_at < closest_timeout)
@ -559,7 +503,7 @@ fds_poll_recv (struct fd_data *data, int timeout, int check_signals,
else
timeout = -1;
if (timeout > 0)
logg ("$fds_poll_recv: timeout after %d seconds\n", timeout);
logg("$fds_poll_recv: timeout after %d seconds\n", timeout);
#ifdef HAVE_POLL
/* Use poll() if available, preferred because:
* - can poll any number of FDs
@ -569,65 +513,56 @@ fds_poll_recv (struct fd_data *data, int timeout, int check_signals,
* recv() may still block according to the manpage
*/
if (realloc_polldata (data) == -1)
if (realloc_polldata(data) == -1)
return -1;
if (timeout > 0)
{
if (timeout > 0) {
/* seconds to ms */
timeout *= 1000;
}
for (i = 0; i < data->nfds; i++)
{
data->poll_data[i].fd = data->buf[i].fd;
data->poll_data[i].events = POLLIN;
for (i = 0; i < data->nfds; i++) {
data->poll_data[i].fd = data->buf[i].fd;
data->poll_data[i].events = POLLIN;
data->poll_data[i].revents = 0;
}
do
{
do {
int n = data->nfds;
fds_unlock (data);
fds_unlock(data);
#ifdef _WIN32
retval = poll_with_event (data->poll_data, n, timeout, event);
retval = poll_with_event(data->poll_data, n, timeout, event);
#else
retval = poll (data->poll_data, n, timeout);
retval = poll(data->poll_data, n, timeout);
#endif
fds_lock (data);
fds_lock(data);
if (retval > 0)
{
if (retval > 0) {
fdsok = 0;
/* nfds may change during poll, but not
* poll_data_nfds */
for (i = 0; i < data->poll_data_nfds; i++)
{
for (i = 0; i < data->poll_data_nfds; i++) {
short revents;
if (data->buf[i].fd < 0)
continue;
if (data->buf[i].fd != data->poll_data[i].fd)
{
if (data->buf[i].fd != data->poll_data[i].fd) {
/* should never happen */
logg ("!poll_recv_fds FD mismatch\n");
logg("!poll_recv_fds FD mismatch\n");
continue;
}
revents = data->poll_data[i].revents;
if (revents & (POLLIN | POLLHUP))
{
logg ("$Received POLLIN|POLLHUP on fd %d\n",
data->poll_data[i].fd);
if (revents & (POLLIN | POLLHUP)) {
logg("$Received POLLIN|POLLHUP on fd %d\n",
data->poll_data[i].fd);
}
#ifndef _WIN32
if (revents & POLLHUP)
{
if (revents & POLLHUP) {
/* avoid SHUT_WR problem on Mac OS X */
int ret = send (data->poll_data[i].fd, &n, 0, 0);
int ret = send(data->poll_data[i].fd, &n, 0, 0);
if (!ret || (ret == -1 && errno == EINTR))
revents &= ~POLLHUP;
}
#endif
if (revents & POLLIN)
{
int ret = read_fd_data (&data->buf[i]);
if (revents & POLLIN) {
int ret = read_fd_data(&data->buf[i]);
/* Data available to be read */
if (ret == -1)
revents |= POLLERR;
@ -635,168 +570,139 @@ fds_poll_recv (struct fd_data *data, int timeout, int check_signals,
revents = POLLHUP;
}
if (revents & (POLLHUP | POLLERR | POLLNVAL))
{
if (revents & (POLLHUP | POLLNVAL))
{
if (revents & (POLLHUP | POLLERR | POLLNVAL)) {
if (revents & (POLLHUP | POLLNVAL)) {
/* remote disconnected */
logg ("*Client disconnected (FD %d)\n",
data->poll_data[i].fd);
}
else
{
logg("*Client disconnected (FD %d)\n",
data->poll_data[i].fd);
} else {
/* error on file descriptor */
logg ("^Error condition on fd %d\n",
data->poll_data[i].fd);
logg("^Error condition on fd %d\n",
data->poll_data[i].fd);
}
data->buf[i].got_newdata = -1;
}
else
{
} else {
fdsok++;
}
}
}
}
while (retval == -1 && !check_signals && errno == EINTR);
} while (retval == -1 && !check_signals && errno == EINTR);
#else
{
fd_set rfds;
struct timeval tv;
int maxfd = -1;
for (i = 0; i < data->nfds; i++)
{
for (i = 0; i < data->nfds; i++) {
int fd = data->buf[i].fd;
if (fd >= FD_SETSIZE)
{
logg ("!File descriptor is too high for FD_SET\n");
if (fd >= FD_SETSIZE) {
logg("!File descriptor is too high for FD_SET\n");
return -1;
}
maxfd = MAX (maxfd, fd);
maxfd = MAX(maxfd, fd);
}
do
{
FD_ZERO (&rfds);
for (i = 0; i < data->nfds; i++)
{
do {
FD_ZERO(&rfds);
for (i = 0; i < data->nfds; i++) {
int fd = data->buf[i].fd;
if (fd >= 0)
FD_SET (fd, &rfds);
FD_SET(fd, &rfds);
}
tv.tv_sec = timeout;
tv.tv_sec = timeout;
tv.tv_usec = 0;
fds_unlock (data);
fds_unlock(data);
retval =
select (maxfd + 1, &rfds, NULL, NULL,
timeout >= 0 ? &tv : NULL);
fds_lock (data);
if (retval > 0)
{
select(maxfd + 1, &rfds, NULL, NULL,
timeout >= 0 ? &tv : NULL);
fds_lock(data);
if (retval > 0) {
fdsok = data->nfds;
for (i = 0; i < data->nfds; i++)
{
if (data->buf[i].fd < 0)
{
for (i = 0; i < data->nfds; i++) {
if (data->buf[i].fd < 0) {
fdsok--;
continue;
}
if (FD_ISSET (data->buf[i].fd, &rfds))
{
int ret = read_fd_data (&data->buf[i]);
if (ret == -1 || !ret)
{
if (FD_ISSET(data->buf[i].fd, &rfds)) {
int ret = read_fd_data(&data->buf[i]);
if (ret == -1 || !ret) {
if (ret == -1)
logg ("!Error condition on fd %d\n",
data->buf[i].fd);
else
{
logg("!Error condition on fd %d\n",
data->buf[i].fd);
else {
/* avoid SHUT_WR problem on Mac OS X */
int ret = send (data->buf[i].fd, &i, 0, 0);
int ret = send(data->buf[i].fd, &i, 0, 0);
if (!ret || (ret == -1 && errno == EINTR))
continue;
logg ("*Client disconnected\n");
logg("*Client disconnected\n");
}
data->buf[i].got_newdata = -1;
}
}
}
}
if (retval < 0 && errno == EBADF)
{
if (retval < 0 && errno == EBADF) {
/* unlike poll(), select() won't tell us which FD is bad, so
* we have to check them one by one. */
tv.tv_sec = 0;
tv.tv_sec = 0;
tv.tv_usec = 0;
/* with tv == 0 it doesn't check for EBADF */
FD_ZERO (&rfds);
for (i = 0; i < data->nfds; i++)
{
FD_ZERO(&rfds);
for (i = 0; i < data->nfds; i++) {
if (data->buf[i].fd == -1)
continue;
FD_SET (data->buf[i].fd, &rfds);
do
{
FD_SET(data->buf[i].fd, &rfds);
do {
retval =
select (data->buf[i].fd + 1, &rfds, NULL, NULL,
&tv);
}
while (retval == -1 && errno == EINTR);
if (retval == -1)
{
select(data->buf[i].fd + 1, &rfds, NULL, NULL,
&tv);
} while (retval == -1 && errno == EINTR);
if (retval == -1) {
data->buf[i].fd = -1;
}
else
{
FD_CLR (data->buf[i].fd, &rfds);
} else {
FD_CLR(data->buf[i].fd, &rfds);
}
}
retval = -1;
errno = EINTR;
errno = EINTR;
continue;
}
}
while (retval == -1 && !check_signals && errno == EINTR);
} while (retval == -1 && !check_signals && errno == EINTR);
}
#endif
if (retval == -1 && errno != EINTR)
{
if (retval == -1 && errno != EINTR) {
char err[128];
#ifdef HAVE_POLL
logg ("!poll_recv_fds: poll failed: %s\n",
cli_strerror (errno, err, sizeof (err)));
logg("!poll_recv_fds: poll failed: %s\n",
cli_strerror(errno, err, sizeof(err)));
#else
logg ("!poll_recv_fds: select failed: %s\n",
cli_strerror (errno, err, sizeof (err)));
logg("!poll_recv_fds: select failed: %s\n",
cli_strerror(errno, err, sizeof(err)));
#endif
}
return retval;
}
void
fds_free (struct fd_data *data)
void fds_free(struct fd_data *data)
{
unsigned i;
fds_lock (data);
for (i = 0; i < data->nfds; i++)
{
if (data->buf[i].buffer)
{
free (data->buf[i].buffer);
fds_lock(data);
for (i = 0; i < data->nfds; i++) {
if (data->buf[i].buffer) {
free(data->buf[i].buffer);
}
}
if (data->buf)
free (data->buf);
free(data->buf);
#ifdef HAVE_POLL
if (data->poll_data)
free (data->poll_data);
free(data->poll_data);
#endif
data->buf = NULL;
data->buf = NULL;
data->nfds = 0;
fds_unlock (data);
fds_unlock(data);
}

View file

@ -69,9 +69,15 @@ struct fd_data {
};
#ifdef HAVE_POLL
#define FDS_INIT(mutex) { (mutex), NULL, 0, NULL, 0}
#define FDS_INIT(mutex) \
{ \
(mutex), NULL, 0, NULL, 0 \
}
#else
#define FDS_INIT(mutex) { (mutex), NULL, 0}
#define FDS_INIT(mutex) \
{ \
(mutex), NULL, 0 \
}
#endif
int poll_fd(int fd, int timeout_sec, int check_signals);

View file

@ -26,14 +26,14 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#ifndef _WIN32
#ifndef _WIN32
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/param.h>
@ -81,18 +81,18 @@ void msg_callback(enum cl_msg severity, const char *fullmsg, const char *msg, vo
UNUSEDPARAM(fullmsg);
switch (severity) {
case CL_MSG_ERROR:
logg("^[LibClamAV] %s: %s", filename, msg);
break;
case CL_MSG_WARN:
logg("~[LibClamAV] %s: %s", filename, msg);
break;
case CL_MSG_INFO_VERBOSE:
logg("*[LibClamAV] %s: %s", filename, msg);
break;
default:
logg("$[LibClamAV] %s: %s", filename, msg);
break;
case CL_MSG_ERROR:
logg("^[LibClamAV] %s: %s", filename, msg);
break;
case CL_MSG_WARN:
logg("~[LibClamAV] %s: %s", filename, msg);
break;
case CL_MSG_INFO_VERBOSE:
logg("*[LibClamAV] %s: %s", filename, msg);
break;
default:
logg("$[LibClamAV] %s: %s", filename, msg);
break;
}
}
@ -103,7 +103,7 @@ void hash_callback(int fd, unsigned long long size, const unsigned char *md5, co
UNUSEDPARAM(virname);
if (!c)
return;
return;
c->virsize = size;
strncpy(c->virhash, (const char *)md5, 32);
c->virhash[32] = '\0';
@ -111,7 +111,7 @@ void hash_callback(int fd, unsigned long long size, const unsigned char *md5, co
void clamd_virus_found_cb(int fd, const char *virname, void *ctx)
{
struct cb_context *c = ctx;
struct cb_context *c = ctx;
struct scan_cb_data *d = c->scandata;
const char *fname;
@ -127,7 +127,7 @@ void clamd_virus_found_cb(int fd, const char *virname, void *ctx)
if (virname) {
d->infected++;
conn_reply_virus(d->conn, fname, virname);
if(c->virsize > 0 && optget(d->opts, "ExtendedDetectionInfo")->enabled)
if (c->virsize > 0 && optget(d->opts, "ExtendedDetectionInfo")->enabled)
logg("~%s: %s(%s:%llu) FOUND\n", fname, virname, c->virhash, c->virsize);
logg("~%s: %s FOUND\n", fname, virname);
}
@ -139,7 +139,7 @@ void clamd_virus_found_cb(int fd, const char *virname, void *ctx)
int scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data)
{
struct scan_cb_data *scandata = data->data;
const char *virname = NULL;
const char *virname = NULL;
int ret;
int type = scandata->type;
struct cb_context context;
@ -147,127 +147,127 @@ int scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_ftw_rea
/* detect disconnected socket,
* this should NOT detect half-shutdown sockets (SHUT_WR) */
if (send(scandata->conn->sd, &ret, 0, 0) == -1 && errno != EINTR) {
logg("$Client disconnected while command was active!\n");
thrmgr_group_terminate(scandata->conn->group);
if (reason == visit_file)
free(filename);
return CL_BREAK;
logg("$Client disconnected while command was active!\n");
thrmgr_group_terminate(scandata->conn->group);
if (reason == visit_file)
free(filename);
return CL_BREAK;
}
if (thrmgr_group_need_terminate(scandata->conn->group)) {
logg("^Client disconnected while scanjob was active\n");
if (reason == visit_file)
free(filename);
return CL_BREAK;
logg("^Client disconnected while scanjob was active\n");
if (reason == visit_file)
free(filename);
return CL_BREAK;
}
scandata->total++;
switch (reason) {
case error_mem:
if (msg)
logg("!Memory allocation failed during cli_ftw() on %s\n",
msg);
else
logg("!Memory allocation failed during cli_ftw()\n");
scandata->errors++;
return CL_EMEM;
case error_stat:
conn_reply_errno(scandata->conn, msg, "lstat() failed:");
logg("^lstat() failed on: %s\n", msg);
scandata->errors++;
return CL_SUCCESS;
case warning_skipped_dir:
logg("^Directory recursion limit reached, skipping %s\n",
msg);
return CL_SUCCESS;
case warning_skipped_link:
logg("$Skipping symlink: %s\n", msg);
return CL_SUCCESS;
case warning_skipped_special:
if (msg == scandata->toplevel_path)
conn_reply(scandata->conn, msg, "Not supported file type", "ERROR");
logg("*Not supported file type: %s\n", msg);
return CL_SUCCESS;
case visit_directory_toplev:
return CL_SUCCESS;
case visit_file:
break;
case error_mem:
if (msg)
logg("!Memory allocation failed during cli_ftw() on %s\n",
msg);
else
logg("!Memory allocation failed during cli_ftw()\n");
scandata->errors++;
return CL_EMEM;
case error_stat:
conn_reply_errno(scandata->conn, msg, "lstat() failed:");
logg("^lstat() failed on: %s\n", msg);
scandata->errors++;
return CL_SUCCESS;
case warning_skipped_dir:
logg("^Directory recursion limit reached, skipping %s\n",
msg);
return CL_SUCCESS;
case warning_skipped_link:
logg("$Skipping symlink: %s\n", msg);
return CL_SUCCESS;
case warning_skipped_special:
if (msg == scandata->toplevel_path)
conn_reply(scandata->conn, msg, "Not supported file type", "ERROR");
logg("*Not supported file type: %s\n", msg);
return CL_SUCCESS;
case visit_directory_toplev:
return CL_SUCCESS;
case visit_file:
break;
}
/* check whether the file is excluded */
/* check whether the file is excluded */
#ifdef C_LINUX
if(procdev && sb && (sb->st_dev == procdev)) {
free(filename);
return CL_SUCCESS;
if (procdev && sb && (sb->st_dev == procdev)) {
free(filename);
return CL_SUCCESS;
}
#endif
if(sb && sb->st_size == 0) { /* empty file */
if (msg == scandata->toplevel_path)
conn_reply_single(scandata->conn, filename, "Empty file");
free(filename);
return CL_SUCCESS;
if (sb && sb->st_size == 0) { /* empty file */
if (msg == scandata->toplevel_path)
conn_reply_single(scandata->conn, filename, "Empty file");
free(filename);
return CL_SUCCESS;
}
if (type == TYPE_MULTISCAN) {
client_conn_t *client_conn = (client_conn_t *) calloc(1, sizeof(struct client_conn_tag));
if(client_conn) {
client_conn->scanfd = -1;
client_conn->sd = scandata->odesc;
client_conn->filename = filename;
client_conn->cmdtype = COMMAND_MULTISCANFILE;
client_conn->term = scandata->conn->term;
client_conn->options = scandata->options;
client_conn->opts = scandata->opts;
client_conn->group = scandata->group;
if(cl_engine_addref(scandata->engine)) {
logg("!cl_engine_addref() failed\n");
free(filename);
free(client_conn);
return CL_EMEM;
} else {
client_conn->engine = scandata->engine;
pthread_mutex_lock(&reload_mutex);
client_conn->engine_timestamp = reloaded_time;
pthread_mutex_unlock(&reload_mutex);
if(!thrmgr_group_dispatch(scandata->thr_pool, scandata->group, client_conn, 1)) {
logg("!thread dispatch failed\n");
cl_engine_free(scandata->engine);
free(filename);
free(client_conn);
return CL_EMEM;
}
}
} else {
logg("!Can't allocate memory for client_conn\n");
scandata->errors++;
free(filename);
return CL_EMEM;
}
return CL_SUCCESS;
client_conn_t *client_conn = (client_conn_t *)calloc(1, sizeof(struct client_conn_tag));
if (client_conn) {
client_conn->scanfd = -1;
client_conn->sd = scandata->odesc;
client_conn->filename = filename;
client_conn->cmdtype = COMMAND_MULTISCANFILE;
client_conn->term = scandata->conn->term;
client_conn->options = scandata->options;
client_conn->opts = scandata->opts;
client_conn->group = scandata->group;
if (cl_engine_addref(scandata->engine)) {
logg("!cl_engine_addref() failed\n");
free(filename);
free(client_conn);
return CL_EMEM;
} else {
client_conn->engine = scandata->engine;
pthread_mutex_lock(&reload_mutex);
client_conn->engine_timestamp = reloaded_time;
pthread_mutex_unlock(&reload_mutex);
if (!thrmgr_group_dispatch(scandata->thr_pool, scandata->group, client_conn, 1)) {
logg("!thread dispatch failed\n");
cl_engine_free(scandata->engine);
free(filename);
free(client_conn);
return CL_EMEM;
}
}
} else {
logg("!Can't allocate memory for client_conn\n");
scandata->errors++;
free(filename);
return CL_EMEM;
}
return CL_SUCCESS;
}
if (access(filename, R_OK)) {
if (conn_reply(scandata->conn, filename, "Access denied.", "ERROR") == -1) {
free(filename);
return CL_ETIMEOUT;
}
logg("*Access denied: %s\n", filename);
scandata->errors++;
free(filename);
return CL_SUCCESS;
if (conn_reply(scandata->conn, filename, "Access denied.", "ERROR") == -1) {
free(filename);
return CL_ETIMEOUT;
}
logg("*Access denied: %s\n", filename);
scandata->errors++;
free(filename);
return CL_SUCCESS;
}
thrmgr_setactivetask(filename, NULL);
context.filename = filename;
context.virsize = 0;
context.virsize = 0;
context.scandata = scandata;
ret = cl_scanfile_callback(filename, &virname, &scandata->scanned, scandata->engine, scandata->options, &context);
ret = cl_scanfile_callback(filename, &virname, &scandata->scanned, scandata->engine, scandata->options, &context);
thrmgr_setactivetask(NULL, NULL);
if (thrmgr_group_need_terminate(scandata->conn->group)) {
free(filename);
logg("*Client disconnected while scanjob was active\n");
return ret == CL_ETIMEOUT ? ret : CL_BREAK;
free(filename);
logg("*Client disconnected while scanjob was active\n");
return ret == CL_ETIMEOUT ? ret : CL_BREAK;
}
if ((ret == CL_VIRUS) && (virname == NULL)) {
@ -277,46 +277,46 @@ int scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_ftw_rea
if (ret == CL_VIRUS) {
if (scandata->options->general & CL_SCAN_GENERAL_ALLMATCHES || (scandata->infected && scandata->options->general & CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE)) {
if(optget(scandata->opts, "PreludeEnable")->enabled){
if (scandata->options->general & CL_SCAN_GENERAL_ALLMATCHES || (scandata->infected && scandata->options->general & CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE)) {
if (optget(scandata->opts, "PreludeEnable")->enabled) {
prelude_logging(filename, virname, context.virhash, context.virsize);
}
virusaction(filename, virname, scandata->opts);
} else {
scandata->infected++;
scandata->infected++;
if (conn_reply_virus(scandata->conn, filename, virname) == -1) {
free(filename);
return CL_ETIMEOUT;
}
if(optget(scandata->opts, "PreludeEnable")->enabled){
if (optget(scandata->opts, "PreludeEnable")->enabled) {
prelude_logging(filename, virname, context.virhash, context.virsize);
}
if(context.virsize && optget(scandata->opts, "ExtendedDetectionInfo")->enabled)
if (context.virsize && optget(scandata->opts, "ExtendedDetectionInfo")->enabled)
logg("~%s: %s(%s:%llu) FOUND\n", filename, virname, context.virhash, context.virsize);
else
logg("~%s: %s FOUND\n", filename, virname);
virusaction(filename, virname, scandata->opts);
}
} else if (ret != CL_CLEAN) {
scandata->errors++;
if (conn_reply(scandata->conn, filename, cl_strerror(ret), "ERROR") == -1) {
free(filename);
return CL_ETIMEOUT;
}
logg("~%s: %s ERROR\n", filename, cl_strerror(ret));
scandata->errors++;
if (conn_reply(scandata->conn, filename, cl_strerror(ret), "ERROR") == -1) {
free(filename);
return CL_ETIMEOUT;
}
logg("~%s: %s ERROR\n", filename, cl_strerror(ret));
} else if (logok) {
logg("~%s: OK\n", filename);
logg("~%s: OK\n", filename);
}
free(filename);
if(ret == CL_EMEM) /* stop scanning */
return ret;
if (ret == CL_EMEM) /* stop scanning */
return ret;
if (type == TYPE_SCAN) {
/* virus -> break */
return ret;
/* virus -> break */
return ret;
}
/* keep scanning always */
@ -325,280 +325,279 @@ int scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_ftw_rea
int scan_pathchk(const char *path, struct cli_ftw_cbdata *data)
{
struct scan_cb_data *scandata = data->data;
const struct optstruct *opt;
STATBUF statbuf;
struct scan_cb_data *scandata = data->data;
const struct optstruct *opt;
STATBUF statbuf;
if((opt = optget(scandata->opts, "ExcludePath"))->enabled) {
while(opt) {
if(match_regex(path, opt->strarg) == 1) {
if(scandata->type != TYPE_MULTISCAN)
conn_reply_single(scandata->conn, path, "Excluded");
return 1;
}
opt = (const struct optstruct *) opt->nextarg;
}
if ((opt = optget(scandata->opts, "ExcludePath"))->enabled) {
while (opt) {
if (match_regex(path, opt->strarg) == 1) {
if (scandata->type != TYPE_MULTISCAN)
conn_reply_single(scandata->conn, path, "Excluded");
return 1;
}
opt = (const struct optstruct *)opt->nextarg;
}
}
if(!optget(scandata->opts, "CrossFilesystems")->enabled) {
if(CLAMSTAT(path, &statbuf) == 0) {
if(statbuf.st_dev != scandata->dev) {
if(scandata->type != TYPE_MULTISCAN)
conn_reply_single(scandata->conn, path, "Excluded (another filesystem)");
return 1;
}
}
if (!optget(scandata->opts, "CrossFilesystems")->enabled) {
if (CLAMSTAT(path, &statbuf) == 0) {
if (statbuf.st_dev != scandata->dev) {
if (scandata->type != TYPE_MULTISCAN)
conn_reply_single(scandata->conn, path, "Excluded (another filesystem)");
return 1;
}
}
}
return 0;
}
int scanfd(
const client_conn_t *conn,
unsigned long int *scanned,
const struct cl_engine *engine,
struct cl_scan_options *options,
const struct optstruct *opts,
int odesc,
int stream)
const client_conn_t *conn,
unsigned long int *scanned,
const struct cl_engine *engine,
struct cl_scan_options *options,
const struct optstruct *opts,
int odesc,
int stream)
{
int ret, fd = conn->scanfd;
const char *virname = NULL;
STATBUF statbuf;
struct cb_context context;
char fdstr[32];
const char*reply_fdstr;
const char *virname = NULL;
STATBUF statbuf;
struct cb_context context;
char fdstr[32];
const char *reply_fdstr;
UNUSEDPARAM(odesc);
if (stream) {
struct sockaddr_in sa;
socklen_t salen = sizeof(sa);
if(getpeername(conn->sd, (struct sockaddr *)&sa, &salen) || salen > sizeof(sa) || sa.sin_family != AF_INET)
strncpy(fdstr, "instream(local)", sizeof(fdstr));
else
snprintf(fdstr, sizeof(fdstr), "instream(%s@%u)", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));
reply_fdstr = "stream";
} else {
snprintf(fdstr, sizeof(fdstr), "fd[%d]", fd);
reply_fdstr = fdstr;
}
if(FSTAT(fd, &statbuf) == -1 || !S_ISREG(statbuf.st_mode)) {
logg("%s: Not a regular file. ERROR\n", fdstr);
if (conn_reply(conn, reply_fdstr, "Not a regular file", "ERROR") == -1)
return CL_ETIMEOUT;
return -1;
}
if (stream) {
struct sockaddr_in sa;
socklen_t salen = sizeof(sa);
if (getpeername(conn->sd, (struct sockaddr *)&sa, &salen) || salen > sizeof(sa) || sa.sin_family != AF_INET)
strncpy(fdstr, "instream(local)", sizeof(fdstr));
else
snprintf(fdstr, sizeof(fdstr), "instream(%s@%u)", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));
reply_fdstr = "stream";
} else {
snprintf(fdstr, sizeof(fdstr), "fd[%d]", fd);
reply_fdstr = fdstr;
}
if (FSTAT(fd, &statbuf) == -1 || !S_ISREG(statbuf.st_mode)) {
logg("%s: Not a regular file. ERROR\n", fdstr);
if (conn_reply(conn, reply_fdstr, "Not a regular file", "ERROR") == -1)
return CL_ETIMEOUT;
return -1;
}
thrmgr_setactivetask(fdstr, NULL);
context.filename = fdstr;
context.virsize = 0;
context.scandata = NULL;
ret = cl_scandesc_callback(fd, NULL, &virname, scanned, engine, options, &context);
thrmgr_setactivetask(NULL, NULL);
thrmgr_setactivetask(fdstr, NULL);
context.filename = fdstr;
context.virsize = 0;
context.scandata = NULL;
ret = cl_scandesc_callback(fd, NULL, &virname, scanned, engine, options, &context);
thrmgr_setactivetask(NULL, NULL);
if (thrmgr_group_need_terminate(conn->group)) {
logg("*Client disconnected while scanjob was active\n");
return ret == CL_ETIMEOUT ? ret : CL_BREAK;
}
if (thrmgr_group_need_terminate(conn->group)) {
logg("*Client disconnected while scanjob was active\n");
return ret == CL_ETIMEOUT ? ret : CL_BREAK;
}
if(ret == CL_VIRUS) {
if (conn_reply_virus(conn, reply_fdstr, virname) == -1)
ret = CL_ETIMEOUT;
if(context.virsize && optget(opts, "ExtendedDetectionInfo")->enabled)
logg("%s: %s(%s:%llu) FOUND\n", fdstr, virname, context.virhash, context.virsize);
else
logg("%s: %s FOUND\n", fdstr, virname);
virusaction(reply_fdstr, virname, opts);
} else if(ret != CL_CLEAN) {
if (conn_reply(conn, reply_fdstr, cl_strerror(ret), "ERROR") == -1)
ret = CL_ETIMEOUT;
logg("%s: %s ERROR\n", fdstr, cl_strerror(ret));
} else {
if (conn_reply_single(conn, reply_fdstr, "OK") == CL_ETIMEOUT)
ret = CL_ETIMEOUT;
if(logok)
logg("%s: OK\n", fdstr);
}
return ret;
if (ret == CL_VIRUS) {
if (conn_reply_virus(conn, reply_fdstr, virname) == -1)
ret = CL_ETIMEOUT;
if (context.virsize && optget(opts, "ExtendedDetectionInfo")->enabled)
logg("%s: %s(%s:%llu) FOUND\n", fdstr, virname, context.virhash, context.virsize);
else
logg("%s: %s FOUND\n", fdstr, virname);
virusaction(reply_fdstr, virname, opts);
} else if (ret != CL_CLEAN) {
if (conn_reply(conn, reply_fdstr, cl_strerror(ret), "ERROR") == -1)
ret = CL_ETIMEOUT;
logg("%s: %s ERROR\n", fdstr, cl_strerror(ret));
} else {
if (conn_reply_single(conn, reply_fdstr, "OK") == CL_ETIMEOUT)
ret = CL_ETIMEOUT;
if (logok)
logg("%s: OK\n", fdstr);
}
return ret;
}
int scanstream(
int odesc,
unsigned long int *scanned,
const struct cl_engine *engine,
struct cl_scan_options *options,
const struct optstruct *opts,
char term)
int odesc,
unsigned long int *scanned,
const struct cl_engine *engine,
struct cl_scan_options *options,
const struct optstruct *opts,
char term)
{
int ret, sockfd, acceptd;
int tmpd, bread, retval, firsttimeout, timeout, btread;
unsigned int port = 0, portscan, min_port, max_port;
unsigned long int quota = 0, maxsize = 0;
short bound = 0;
const char *virname = NULL;
char buff[FILEBUFF];
char peer_addr[32];
struct cb_context context;
struct sockaddr_in server;
struct sockaddr_in peer;
socklen_t addrlen;
char *tmpname;
int ret, sockfd, acceptd;
int tmpd, bread, retval, firsttimeout, timeout, btread;
unsigned int port = 0, portscan, min_port, max_port;
unsigned long int quota = 0, maxsize = 0;
short bound = 0;
const char *virname = NULL;
char buff[FILEBUFF];
char peer_addr[32];
struct cb_context context;
struct sockaddr_in server;
struct sockaddr_in peer;
socklen_t addrlen;
char *tmpname;
min_port = optget(opts, "StreamMinPort")->numarg;
max_port = optget(opts, "StreamMaxPort")->numarg;
/* search for a free port to bind to */
port = cli_rndnum(max_port - min_port);
port = cli_rndnum(max_port - min_port);
bound = 0;
for (portscan = 0; portscan < 1000; portscan++) {
port = (port - 1) % (max_port - min_port + 1);
port = (port - 1) % (max_port - min_port + 1);
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(min_port + port);
server.sin_addr.s_addr = htonl(INADDR_ANY);
memset((char *)&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(min_port + port);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
continue;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
continue;
if(bind(sockfd, (struct sockaddr *) &server, (socklen_t)sizeof(struct sockaddr_in)) == -1)
closesocket(sockfd);
else {
bound = 1;
break;
}
if (bind(sockfd, (struct sockaddr *)&server, (socklen_t)sizeof(struct sockaddr_in)) == -1)
closesocket(sockfd);
else {
bound = 1;
break;
}
}
port += min_port;
timeout = optget(opts, "ReadTimeout")->numarg;
timeout = optget(opts, "ReadTimeout")->numarg;
firsttimeout = optget(opts, "CommandReadTimeout")->numarg;
if(!bound) {
logg("!ScanStream: Can't find any free port.\n");
mdprintf(odesc, "Can't find any free port. ERROR%c", term);
return -1;
} else {
if (listen(sockfd, 1) == -1) {
logg("!ScanStream: listen() error on socket. Error returned is %s.\n", strerror(errno));
closesocket(sockfd);
if (!bound) {
logg("!ScanStream: Can't find any free port.\n");
mdprintf(odesc, "Can't find any free port. ERROR%c", term);
return -1;
}
if(mdprintf(odesc, "PORT %u%c", port, term) <= 0) {
logg("!ScanStream: error transmitting port.\n");
closesocket(sockfd);
return -1;
}
} else {
if (listen(sockfd, 1) == -1) {
logg("!ScanStream: listen() error on socket. Error returned is %s.\n", strerror(errno));
closesocket(sockfd);
return -1;
}
if (mdprintf(odesc, "PORT %u%c", port, term) <= 0) {
logg("!ScanStream: error transmitting port.\n");
closesocket(sockfd);
return -1;
}
}
retval = poll_fd(sockfd, firsttimeout, 0);
if (!retval || retval == -1) {
const char *reason = !retval ? "timeout" : "poll";
mdprintf(odesc, "Accept %s. ERROR%c", reason, term);
logg("!ScanStream %u: accept %s.\n", port, reason);
closesocket(sockfd);
return -1;
const char *reason = !retval ? "timeout" : "poll";
mdprintf(odesc, "Accept %s. ERROR%c", reason, term);
logg("!ScanStream %u: accept %s.\n", port, reason);
closesocket(sockfd);
return -1;
}
addrlen = sizeof(peer);
if((acceptd = accept(sockfd, (struct sockaddr *) &peer, (socklen_t *)&addrlen)) == -1) {
closesocket(sockfd);
mdprintf(odesc, "accept() ERROR%c", term);
logg("!ScanStream %u: accept() failed.\n", port);
return -1;
if ((acceptd = accept(sockfd, (struct sockaddr *)&peer, (socklen_t *)&addrlen)) == -1) {
closesocket(sockfd);
mdprintf(odesc, "accept() ERROR%c", term);
logg("!ScanStream %u: accept() failed.\n", port);
return -1;
}
*peer_addr = '\0';
inet_ntop(peer.sin_family, &peer.sin_addr, peer_addr, sizeof(peer_addr));
logg("*Accepted connection from %s on port %u, fd %d\n", peer_addr, port, acceptd);
if(cli_gentempfd(optget(opts, "TemporaryDirectory")->strarg, &tmpname, &tmpd)) {
shutdown(sockfd, 2);
closesocket(sockfd);
closesocket(acceptd);
mdprintf(odesc, "cli_gentempfd() failed. ERROR%c", term);
logg("!ScanStream(%s@%u): Can't create temporary file.\n", peer_addr, port);
return -1;
if (cli_gentempfd(optget(opts, "TemporaryDirectory")->strarg, &tmpname, &tmpd)) {
shutdown(sockfd, 2);
closesocket(sockfd);
closesocket(acceptd);
mdprintf(odesc, "cli_gentempfd() failed. ERROR%c", term);
logg("!ScanStream(%s@%u): Can't create temporary file.\n", peer_addr, port);
return -1;
}
quota = maxsize = optget(opts, "StreamMaxLength")->numarg;
while((retval = poll_fd(acceptd, timeout, 0)) == 1) {
/* only read up to max */
btread = (maxsize && (quota < sizeof(buff))) ? quota : sizeof(buff);
if (!btread) {
logg("^ScanStream(%s@%u): Size limit reached (max: %lu)\n", peer_addr, port, maxsize);
break; /* Scan what we have */
}
bread = recv(acceptd, buff, btread, 0);
if(bread <= 0)
break;
while ((retval = poll_fd(acceptd, timeout, 0)) == 1) {
/* only read up to max */
btread = (maxsize && (quota < sizeof(buff))) ? quota : sizeof(buff);
if (!btread) {
logg("^ScanStream(%s@%u): Size limit reached (max: %lu)\n", peer_addr, port, maxsize);
break; /* Scan what we have */
}
bread = recv(acceptd, buff, btread, 0);
if (bread <= 0)
break;
quota -= bread;
quota -= bread;
if(writen(tmpd, buff, bread) != bread) {
shutdown(sockfd, 2);
closesocket(sockfd);
closesocket(acceptd);
mdprintf(odesc, "Temporary file -> write ERROR%c", term);
logg("!ScanStream(%s@%u): Can't write to temporary file.\n", peer_addr, port);
close(tmpd);
if(!optget(opts, "LeaveTemporaryFiles")->enabled)
unlink(tmpname);
free(tmpname);
return -1;
}
if (writen(tmpd, buff, bread) != bread) {
shutdown(sockfd, 2);
closesocket(sockfd);
closesocket(acceptd);
mdprintf(odesc, "Temporary file -> write ERROR%c", term);
logg("!ScanStream(%s@%u): Can't write to temporary file.\n", peer_addr, port);
close(tmpd);
if (!optget(opts, "LeaveTemporaryFiles")->enabled)
unlink(tmpname);
free(tmpname);
return -1;
}
}
switch(retval) {
case 0: /* timeout */
mdprintf(odesc, "read timeout ERROR%c", term);
logg("!ScanStream(%s@%u): read timeout.\n", peer_addr, port);
break;
case -1:
mdprintf(odesc, "read poll ERROR%c", term);
logg("!ScanStream(%s@%u): read poll failed.\n", peer_addr, port);
break;
switch (retval) {
case 0: /* timeout */
mdprintf(odesc, "read timeout ERROR%c", term);
logg("!ScanStream(%s@%u): read timeout.\n", peer_addr, port);
break;
case -1:
mdprintf(odesc, "read poll ERROR%c", term);
logg("!ScanStream(%s@%u): read poll failed.\n", peer_addr, port);
break;
}
if(retval == 1) {
lseek(tmpd, 0, SEEK_SET);
thrmgr_setactivetask(peer_addr, NULL);
context.filename = peer_addr;
context.virsize = 0;
context.scandata = NULL;
ret = cl_scandesc_callback(tmpd, NULL, &virname, scanned, engine, options, &context);
thrmgr_setactivetask(NULL, NULL);
if (retval == 1) {
lseek(tmpd, 0, SEEK_SET);
thrmgr_setactivetask(peer_addr, NULL);
context.filename = peer_addr;
context.virsize = 0;
context.scandata = NULL;
ret = cl_scandesc_callback(tmpd, NULL, &virname, scanned, engine, options, &context);
thrmgr_setactivetask(NULL, NULL);
} else {
ret = -1;
ret = -1;
}
close(tmpd);
if(!optget(opts, "LeaveTemporaryFiles")->enabled)
unlink(tmpname);
if (!optget(opts, "LeaveTemporaryFiles")->enabled)
unlink(tmpname);
free(tmpname);
closesocket(acceptd);
closesocket(sockfd);
if(ret == CL_VIRUS) {
if(context.virsize && optget(opts, "ExtendedDetectionInfo")->enabled) {
mdprintf(odesc, "stream: %s(%s:%llu) FOUND%c", virname, context.virhash, context.virsize, term);
logg("stream(%s@%u): %s(%s:%llu) FOUND\n", peer_addr, port, virname, context.virhash, context.virsize);
} else {
mdprintf(odesc, "stream: %s FOUND%c", virname, term);
logg("stream(%s@%u): %s FOUND\n", peer_addr, port, virname);
}
virusaction("stream", virname, opts);
} else if(ret != CL_CLEAN) {
if(retval == 1) {
mdprintf(odesc, "stream: %s ERROR%c", cl_strerror(ret), term);
logg("stream(%s@%u): %s ERROR\n", peer_addr, port, cl_strerror(ret));
}
if (ret == CL_VIRUS) {
if (context.virsize && optget(opts, "ExtendedDetectionInfo")->enabled) {
mdprintf(odesc, "stream: %s(%s:%llu) FOUND%c", virname, context.virhash, context.virsize, term);
logg("stream(%s@%u): %s(%s:%llu) FOUND\n", peer_addr, port, virname, context.virhash, context.virsize);
} else {
mdprintf(odesc, "stream: %s FOUND%c", virname, term);
logg("stream(%s@%u): %s FOUND\n", peer_addr, port, virname);
}
virusaction("stream", virname, opts);
} else if (ret != CL_CLEAN) {
if (retval == 1) {
mdprintf(odesc, "stream: %s ERROR%c", cl_strerror(ret), term);
logg("stream(%s@%u): %s ERROR\n", peer_addr, port, cl_strerror(ret));
}
} else {
mdprintf(odesc, "stream: OK%c", term);
if(logok)
logg("stream(%s@%u): OK\n", peer_addr, port);
mdprintf(odesc, "stream: OK%c", term);
if (logok)
logg("stream(%s@%u): OK\n", peer_addr, port);
}
return ret;

View file

@ -30,7 +30,10 @@
#include "thrmgr.h"
#include "session.h"
enum scan_type { TYPE_INIT = -1, TYPE_SCAN = 0, TYPE_CONTSCAN = 1, TYPE_MULTISCAN = 2 };
enum scan_type { TYPE_INIT = -1,
TYPE_SCAN = 0,
TYPE_CONTSCAN = 1,
TYPE_MULTISCAN = 2 };
struct scan_cb_data {
int scantype;

File diff suppressed because it is too large Load diff

View file

@ -38,7 +38,7 @@ struct thrarg {
};
int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsigned int dboptions, const struct optstruct *opts);
int statinidir_th(const char* dirname);
int statinidir_th(const char *dirname);
void sighandler(int sig);
void sighandler_th(int sig);
void sigsegv(int sig);

View file

@ -26,12 +26,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/types.h>
#include <dirent.h>
#ifndef _WIN32
#ifndef _WIN32
#include <sys/socket.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
@ -78,54 +78,53 @@ static struct {
int support_old;
int enabled;
} commands[] = {
{CMD1, sizeof(CMD1)-1, COMMAND_SCAN, 1, 1, 0},
{CMD3, sizeof(CMD3)-1, COMMAND_SHUTDOWN, 0, 1, 0},
{CMD4, sizeof(CMD4)-1, COMMAND_RELOAD, 0, 1, 0},
{CMD5, sizeof(CMD5)-1, COMMAND_PING, 0, 1, 0},
{CMD6, sizeof(CMD6)-1, COMMAND_CONTSCAN, 1, 1, 0},
{CMD1, sizeof(CMD1) - 1, COMMAND_SCAN, 1, 1, 0},
{CMD3, sizeof(CMD3) - 1, COMMAND_SHUTDOWN, 0, 1, 0},
{CMD4, sizeof(CMD4) - 1, COMMAND_RELOAD, 0, 1, 0},
{CMD5, sizeof(CMD5) - 1, COMMAND_PING, 0, 1, 0},
{CMD6, sizeof(CMD6) - 1, COMMAND_CONTSCAN, 1, 1, 0},
/* must be before VERSION, because they share common prefix! */
{CMD18, sizeof(CMD18)-1, COMMAND_COMMANDS, 0, 0, 1},
{CMD7, sizeof(CMD7)-1, COMMAND_VERSION, 0, 1, 1},
{CMD8, sizeof(CMD8)-1, COMMAND_STREAM, 0, 1, 1},
{CMD10, sizeof(CMD10)-1, COMMAND_END, 0, 0, 1},
{CMD11, sizeof(CMD11)-1, COMMAND_SHUTDOWN, 0, 1, 1},
{CMD13, sizeof(CMD13)-1, COMMAND_MULTISCAN, 1, 1, 1},
{CMD14, sizeof(CMD14)-1, COMMAND_FILDES, 0, 1, FEATURE_FDPASSING},
{CMD15, sizeof(CMD15)-1, COMMAND_STATS, 0, 0, 1},
{CMD16, sizeof(CMD16)-1, COMMAND_IDSESSION, 0, 0, 1},
{CMD17, sizeof(CMD17)-1, COMMAND_INSTREAM, 0, 0, 1},
{CMD19, sizeof(CMD19)-1, COMMAND_DETSTATSCLEAR, 0, 1, 1},
{CMD20, sizeof(CMD20)-1, COMMAND_DETSTATS, 0, 1, 1},
{CMD21, sizeof(CMD21)-1, COMMAND_ALLMATCHSCAN, 1, 0, 1}
};
{CMD18, sizeof(CMD18) - 1, COMMAND_COMMANDS, 0, 0, 1},
{CMD7, sizeof(CMD7) - 1, COMMAND_VERSION, 0, 1, 1},
{CMD8, sizeof(CMD8) - 1, COMMAND_STREAM, 0, 1, 1},
{CMD10, sizeof(CMD10) - 1, COMMAND_END, 0, 0, 1},
{CMD11, sizeof(CMD11) - 1, COMMAND_SHUTDOWN, 0, 1, 1},
{CMD13, sizeof(CMD13) - 1, COMMAND_MULTISCAN, 1, 1, 1},
{CMD14, sizeof(CMD14) - 1, COMMAND_FILDES, 0, 1, FEATURE_FDPASSING},
{CMD15, sizeof(CMD15) - 1, COMMAND_STATS, 0, 0, 1},
{CMD16, sizeof(CMD16) - 1, COMMAND_IDSESSION, 0, 0, 1},
{CMD17, sizeof(CMD17) - 1, COMMAND_INSTREAM, 0, 0, 1},
{CMD19, sizeof(CMD19) - 1, COMMAND_DETSTATSCLEAR, 0, 1, 1},
{CMD20, sizeof(CMD20) - 1, COMMAND_DETSTATS, 0, 1, 1},
{CMD21, sizeof(CMD21) - 1, COMMAND_ALLMATCHSCAN, 1, 0, 1}};
enum commands parse_command(const char *cmd, const char **argument, int oldstyle)
{
size_t i;
*argument = NULL;
for (i=0; i < sizeof(commands)/sizeof(commands[0]); i++) {
const size_t len = commands[i].len;
if (!strncmp(cmd, commands[i].cmd, len)) {
const char *arg = cmd + len;
if (commands[i].need_arg) {
if (!*arg) {/* missing argument */
logg("$Command %s missing argument!\n", commands[i].cmd);
return COMMAND_UNKNOWN;
}
*argument = arg+1;
} else {
if (*arg) {/* extra stuff after command */
logg("$Command %s has trailing garbage!\n", commands[i].cmd);
return COMMAND_UNKNOWN;
}
*argument = NULL;
}
if (oldstyle && !commands[i].support_old) {
logg("$Command sent as old-style when not supported: %s\n", commands[i].cmd);
return COMMAND_UNKNOWN;
}
return commands[i].cmdtype;
}
for (i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) {
const size_t len = commands[i].len;
if (!strncmp(cmd, commands[i].cmd, len)) {
const char *arg = cmd + len;
if (commands[i].need_arg) {
if (!*arg) { /* missing argument */
logg("$Command %s missing argument!\n", commands[i].cmd);
return COMMAND_UNKNOWN;
}
*argument = arg + 1;
} else {
if (*arg) { /* extra stuff after command */
logg("$Command %s has trailing garbage!\n", commands[i].cmd);
return COMMAND_UNKNOWN;
}
*argument = NULL;
}
if (oldstyle && !commands[i].support_old) {
logg("$Command sent as old-style when not supported: %s\n", commands[i].cmd);
return COMMAND_UNKNOWN;
}
return commands[i].cmdtype;
}
}
return COMMAND_UNKNOWN;
}
@ -133,36 +132,36 @@ enum commands parse_command(const char *cmd, const char **argument, int oldstyle
int conn_reply_single(const client_conn_t *conn, const char *path, const char *status)
{
if (conn->id) {
if (path)
return mdprintf(conn->sd, "%u: %s: %s%c", conn->id, path, status, conn->term);
return mdprintf(conn->sd, "%u: %s%c", conn->id, status, conn->term);
if (path)
return mdprintf(conn->sd, "%u: %s: %s%c", conn->id, path, status, conn->term);
return mdprintf(conn->sd, "%u: %s%c", conn->id, status, conn->term);
}
if (path)
return mdprintf(conn->sd, "%s: %s%c", path, status, conn->term);
return mdprintf(conn->sd, "%s: %s%c", path, status, conn->term);
return mdprintf(conn->sd, "%s%c", status, conn->term);
}
int conn_reply(const client_conn_t *conn, const char *path,
const char *msg, const char *status)
const char *msg, const char *status)
{
if (conn->id) {
if (path)
return mdprintf(conn->sd, "%u: %s: %s %s%c", conn->id, path, msg,
status, conn->term);
return mdprintf(conn->sd, "%u: %s %s%c", conn->id, msg, status,
conn->term);
if (path)
return mdprintf(conn->sd, "%u: %s: %s %s%c", conn->id, path, msg,
status, conn->term);
return mdprintf(conn->sd, "%u: %s %s%c", conn->id, msg, status,
conn->term);
}
if (path)
return mdprintf(conn->sd, "%s: %s %s%c", path, msg, status, conn->term);
return mdprintf(conn->sd, "%s: %s %s%c", path, msg, status, conn->term);
return mdprintf(conn->sd, "%s %s%c", msg, status, conn->term);
}
int conn_reply_virus(const client_conn_t *conn, const char *file,
const char *virname)
const char *virname)
{
if (conn->id) {
return mdprintf(conn->sd, "%u: %s: %s FOUND%c", conn->id, file, virname,
conn->term);
return mdprintf(conn->sd, "%u: %s: %s FOUND%c", conn->id, file, virname,
conn->term);
}
return mdprintf(conn->sd, "%s: %s FOUND%c", file, virname, conn->term);
}
@ -174,10 +173,10 @@ int conn_reply_error(const client_conn_t *conn, const char *msg)
#define BUFFSIZE 1024
int conn_reply_errno(const client_conn_t *conn, const char *path,
const char *msg)
const char *msg)
{
char err[BUFFSIZE + sizeof(". ERROR")];
cli_strerror(errno, err, BUFFSIZE-1);
cli_strerror(errno, err, BUFFSIZE - 1);
strcat(err, ". ERROR");
return conn_reply(conn, path, msg, err);
}
@ -189,13 +188,13 @@ int conn_reply_errno(const client_conn_t *conn, const char *path,
*/
int command(client_conn_t *conn, int *virus)
{
int desc = conn->sd;
struct cl_engine *engine = conn->engine;
int desc = conn->sd;
struct cl_engine *engine = conn->engine;
struct cl_scan_options *options = conn->options;
const struct optstruct *opts = conn->opts;
enum scan_type type = TYPE_INIT;
const struct optstruct *opts = conn->opts;
enum scan_type type = TYPE_INIT;
int maxdirrec;
int ret = 0;
int ret = 0;
int flags = CLI_FTW_STD;
struct scan_cb_data scandata;
@ -205,281 +204,280 @@ int command(client_conn_t *conn, int *virus)
jobgroup_t *group = NULL;
if (thrmgr_group_need_terminate(conn->group)) {
logg("$Client disconnected while command was active\n");
if (conn->scanfd != -1)
close(conn->scanfd);
return 1;
logg("$Client disconnected while command was active\n");
if (conn->scanfd != -1)
close(conn->scanfd);
return 1;
}
thrmgr_setactiveengine(engine);
data.data = &scandata;
memset(&scandata, 0, sizeof(scandata));
scandata.id = conn->id;
scandata.group = conn->group;
scandata.odesc = desc;
scandata.conn = conn;
scandata.options = options;
scandata.engine = engine;
scandata.opts = opts;
scandata.thr_pool = conn->thrpool;
scandata.id = conn->id;
scandata.group = conn->group;
scandata.odesc = desc;
scandata.conn = conn;
scandata.options = options;
scandata.engine = engine;
scandata.opts = opts;
scandata.thr_pool = conn->thrpool;
scandata.toplevel_path = conn->filename;
switch (conn->cmdtype) {
case COMMAND_SCAN:
thrmgr_setactivetask(NULL, "SCAN");
type = TYPE_SCAN;
break;
case COMMAND_CONTSCAN:
thrmgr_setactivetask(NULL, "CONTSCAN");
type = TYPE_CONTSCAN;
break;
case COMMAND_MULTISCAN: {
int multiscan, max, alive;
case COMMAND_SCAN:
thrmgr_setactivetask(NULL, "SCAN");
type = TYPE_SCAN;
break;
case COMMAND_CONTSCAN:
thrmgr_setactivetask(NULL, "CONTSCAN");
type = TYPE_CONTSCAN;
break;
case COMMAND_MULTISCAN: {
int multiscan, max, alive;
/* use MULTISCAN only for directories (bb #1869) */
if (CLAMSTAT(conn->filename, &sb) == 0 &&
!S_ISDIR(sb.st_mode)) {
thrmgr_setactivetask(NULL, "CONTSCAN");
type = TYPE_CONTSCAN;
break;
}
/* use MULTISCAN only for directories (bb #1869) */
if (CLAMSTAT(conn->filename, &sb) == 0 &&
!S_ISDIR(sb.st_mode)) {
thrmgr_setactivetask(NULL, "CONTSCAN");
type = TYPE_CONTSCAN;
break;
}
pthread_mutex_lock(&conn->thrpool->pool_mutex);
multiscan = conn->thrpool->thr_multiscan;
max = conn->thrpool->thr_max;
if (multiscan+1 < max)
conn->thrpool->thr_multiscan = multiscan+1;
else {
alive = conn->thrpool->thr_alive;
ret = -1;
}
pthread_mutex_unlock(&conn->thrpool->pool_mutex);
if (ret) {
/* multiscan has 1 control thread, so there needs to be at least
pthread_mutex_lock(&conn->thrpool->pool_mutex);
multiscan = conn->thrpool->thr_multiscan;
max = conn->thrpool->thr_max;
if (multiscan + 1 < max)
conn->thrpool->thr_multiscan = multiscan + 1;
else {
alive = conn->thrpool->thr_alive;
ret = -1;
}
pthread_mutex_unlock(&conn->thrpool->pool_mutex);
if (ret) {
/* multiscan has 1 control thread, so there needs to be at least
1 threads that is a non-multiscan controlthread to scan and
make progress. */
logg("^Not enough threads for multiscan. Max: %d, Alive: %d, Multiscan: %d+1\n",
max, alive, multiscan);
conn_reply(conn, conn->filename, "Not enough threads for multiscan. Increase MaxThreads.", "ERROR");
return 1;
}
flags &= ~CLI_FTW_NEED_STAT;
thrmgr_setactivetask(NULL, "MULTISCAN");
type = TYPE_MULTISCAN;
scandata.group = group = thrmgr_group_new();
if (!group) {
if(optget(opts, "ExitOnOOM")->enabled)
return -1;
else
return 1;
}
break;
}
case COMMAND_MULTISCANFILE:
thrmgr_setactivetask(NULL, "MULTISCANFILE");
scandata.group = NULL;
scandata.type = TYPE_SCAN;
scandata.thr_pool = NULL;
/* TODO: check ret value */
ret = scan_callback(NULL, conn->filename, conn->filename, visit_file, &data); /* callback freed it */
conn->filename = NULL;
*virus = scandata.infected;
if (ret == CL_BREAK) {
thrmgr_group_terminate(conn->group);
return 1;
}
return scandata.errors > 0 ? scandata.errors : 0;
case COMMAND_FILDES:
thrmgr_setactivetask(NULL, "FILDES");
logg("^Not enough threads for multiscan. Max: %d, Alive: %d, Multiscan: %d+1\n",
max, alive, multiscan);
conn_reply(conn, conn->filename, "Not enough threads for multiscan. Increase MaxThreads.", "ERROR");
return 1;
}
flags &= ~CLI_FTW_NEED_STAT;
thrmgr_setactivetask(NULL, "MULTISCAN");
type = TYPE_MULTISCAN;
scandata.group = group = thrmgr_group_new();
if (!group) {
if (optget(opts, "ExitOnOOM")->enabled)
return -1;
else
return 1;
}
break;
}
case COMMAND_MULTISCANFILE:
thrmgr_setactivetask(NULL, "MULTISCANFILE");
scandata.group = NULL;
scandata.type = TYPE_SCAN;
scandata.thr_pool = NULL;
/* TODO: check ret value */
ret = scan_callback(NULL, conn->filename, conn->filename, visit_file, &data); /* callback freed it */
conn->filename = NULL;
*virus = scandata.infected;
if (ret == CL_BREAK) {
thrmgr_group_terminate(conn->group);
return 1;
}
return scandata.errors > 0 ? scandata.errors : 0;
case COMMAND_FILDES:
thrmgr_setactivetask(NULL, "FILDES");
#ifdef HAVE_FD_PASSING
if (conn->scanfd == -1) {
conn_reply_error(conn, "FILDES: didn't receive file descriptor.");
return 1;
}
else {
ret = scanfd(conn, NULL, engine, options, opts, desc, 0);
if (ret == CL_VIRUS) {
*virus = 1;
ret = 0;
} else if (ret == CL_EMEM) {
if(optget(opts, "ExitOnOOM")->enabled)
ret = -1;
else
ret = 1;
} else if (ret == CL_ETIMEOUT) {
thrmgr_group_terminate(conn->group);
ret = 1;
} else
ret = 0;
logg("$Closed fd %d\n", conn->scanfd);
close(conn->scanfd);
}
return ret;
if (conn->scanfd == -1) {
conn_reply_error(conn, "FILDES: didn't receive file descriptor.");
return 1;
} else {
ret = scanfd(conn, NULL, engine, options, opts, desc, 0);
if (ret == CL_VIRUS) {
*virus = 1;
ret = 0;
} else if (ret == CL_EMEM) {
if (optget(opts, "ExitOnOOM")->enabled)
ret = -1;
else
ret = 1;
} else if (ret == CL_ETIMEOUT) {
thrmgr_group_terminate(conn->group);
ret = 1;
} else
ret = 0;
logg("$Closed fd %d\n", conn->scanfd);
close(conn->scanfd);
}
return ret;
#else
conn_reply_error(conn, "FILDES support not compiled in.");
close(conn->scanfd);
return 0;
#endif
case COMMAND_STATS:
thrmgr_setactivetask(NULL, "STATS");
if (conn->group)
mdprintf(desc, "%u: ", conn->id);
thrmgr_printstats(desc, conn->term);
return 0;
case COMMAND_STREAM:
thrmgr_setactivetask(NULL, "STREAM");
ret = scanstream(desc, NULL, engine, options, opts, conn->term);
if (ret == CL_VIRUS)
*virus = 1;
if (ret == CL_EMEM) {
if(optget(opts, "ExitOnOOM")->enabled)
return -1;
else
return 1;
}
return 0;
case COMMAND_INSTREAMSCAN:
thrmgr_setactivetask(NULL, "INSTREAM");
ret = scanfd(conn, NULL, engine, options, opts, desc, 1);
if (ret == CL_VIRUS) {
*virus = 1;
ret = 0;
} else if (ret == CL_EMEM) {
if(optget(opts, "ExitOnOOM")->enabled)
ret = -1;
else
ret = 1;
} else if (ret == CL_ETIMEOUT) {
thrmgr_group_terminate(conn->group);
ret = 1;
} else
ret = 0;
if (ftruncate(conn->scanfd, 0) == -1) {
/* not serious, we're going to close it and unlink it anyway */
logg("*ftruncate failed: %d\n", errno);
}
close(conn->scanfd);
conn->scanfd = -1;
cli_unlink(conn->filename);
return ret;
case COMMAND_ALLMATCHSCAN:
if (!optget(opts, "AllowAllMatchScan")->enabled) {
logg("$Rejecting ALLMATCHSCAN command.\n");
conn_reply(conn, conn->filename, "ALLMATCHSCAN command disabled by clamd configuration.", "ERROR");
return 1;
}
thrmgr_setactivetask(NULL, "ALLMATCHSCAN");
scandata.options->general |= CL_SCAN_GENERAL_ALLMATCHES;
type = TYPE_SCAN;
break;
default:
logg("!Invalid command dispatched: %d\n", conn->cmdtype);
return 1;
}
conn_reply_error(conn, "FILDES support not compiled in.");
close(conn->scanfd);
return 0;
#endif
case COMMAND_STATS:
thrmgr_setactivetask(NULL, "STATS");
if (conn->group)
mdprintf(desc, "%u: ", conn->id);
thrmgr_printstats(desc, conn->term);
return 0;
case COMMAND_STREAM:
thrmgr_setactivetask(NULL, "STREAM");
ret = scanstream(desc, NULL, engine, options, opts, conn->term);
if (ret == CL_VIRUS)
*virus = 1;
if (ret == CL_EMEM) {
if (optget(opts, "ExitOnOOM")->enabled)
return -1;
else
return 1;
}
return 0;
case COMMAND_INSTREAMSCAN:
thrmgr_setactivetask(NULL, "INSTREAM");
ret = scanfd(conn, NULL, engine, options, opts, desc, 1);
if (ret == CL_VIRUS) {
*virus = 1;
ret = 0;
} else if (ret == CL_EMEM) {
if (optget(opts, "ExitOnOOM")->enabled)
ret = -1;
else
ret = 1;
} else if (ret == CL_ETIMEOUT) {
thrmgr_group_terminate(conn->group);
ret = 1;
} else
ret = 0;
if (ftruncate(conn->scanfd, 0) == -1) {
/* not serious, we're going to close it and unlink it anyway */
logg("*ftruncate failed: %d\n", errno);
}
close(conn->scanfd);
conn->scanfd = -1;
cli_unlink(conn->filename);
return ret;
case COMMAND_ALLMATCHSCAN:
if (!optget(opts, "AllowAllMatchScan")->enabled) {
logg("$Rejecting ALLMATCHSCAN command.\n");
conn_reply(conn, conn->filename, "ALLMATCHSCAN command disabled by clamd configuration.", "ERROR");
return 1;
}
thrmgr_setactivetask(NULL, "ALLMATCHSCAN");
scandata.options->general |= CL_SCAN_GENERAL_ALLMATCHES;
type = TYPE_SCAN;
break;
default:
logg("!Invalid command dispatched: %d\n", conn->cmdtype);
return 1;
}
scandata.type = type;
maxdirrec = optget(opts, "MaxDirectoryRecursion")->numarg;
if (optget(opts, "FollowDirectorySymlinks")->enabled)
flags |= CLI_FTW_FOLLOW_DIR_SYMLINK;
if (optget(opts, "FollowFileSymlinks")->enabled)
flags |= CLI_FTW_FOLLOW_FILE_SYMLINK;
scandata.type = type;
maxdirrec = optget(opts, "MaxDirectoryRecursion")->numarg;
if (optget(opts, "FollowDirectorySymlinks")->enabled)
flags |= CLI_FTW_FOLLOW_DIR_SYMLINK;
if (optget(opts, "FollowFileSymlinks")->enabled)
flags |= CLI_FTW_FOLLOW_FILE_SYMLINK;
if(!optget(opts, "CrossFilesystems")->enabled)
if(CLAMSTAT(conn->filename, &sb) == 0)
scandata.dev = sb.st_dev;
if (!optget(opts, "CrossFilesystems")->enabled)
if (CLAMSTAT(conn->filename, &sb) == 0)
scandata.dev = sb.st_dev;
ret = cli_ftw(conn->filename, flags, maxdirrec ? maxdirrec : INT_MAX, scan_callback, &data, scan_pathchk);
if (ret == CL_EMEM) {
if(optget(opts, "ExitOnOOM")->enabled)
return -1;
else
return 1;
}
if (scandata.group && type == TYPE_MULTISCAN) {
thrmgr_group_waitforall(group, &ok, &error, &total);
pthread_mutex_lock(&conn->thrpool->pool_mutex);
conn->thrpool->thr_multiscan--;
pthread_mutex_unlock(&conn->thrpool->pool_mutex);
} else {
error = scandata.errors;
total = scandata.total;
ok = total - error - scandata.infected;
}
ret = cli_ftw(conn->filename, flags, maxdirrec ? maxdirrec : INT_MAX, scan_callback, &data, scan_pathchk);
if (ret == CL_EMEM) {
if (optget(opts, "ExitOnOOM")->enabled)
return -1;
else
return 1;
}
if (scandata.group && type == TYPE_MULTISCAN) {
thrmgr_group_waitforall(group, &ok, &error, &total);
pthread_mutex_lock(&conn->thrpool->pool_mutex);
conn->thrpool->thr_multiscan--;
pthread_mutex_unlock(&conn->thrpool->pool_mutex);
} else {
error = scandata.errors;
total = scandata.total;
ok = total - error - scandata.infected;
}
if (ok + error == total && (error != total)) {
if (conn_reply_single(conn, conn->filename, "OK") == -1)
ret = CL_ETIMEOUT;
}
*virus = total - (ok + error);
if (ok + error == total && (error != total)) {
if (conn_reply_single(conn, conn->filename, "OK") == -1)
ret = CL_ETIMEOUT;
}
*virus = total - (ok + error);
if (ret == CL_ETIMEOUT)
thrmgr_group_terminate(conn->group);
return error;
}
if (ret == CL_ETIMEOUT)
thrmgr_group_terminate(conn->group);
return error;
}
static int dispatch_command(client_conn_t *conn, enum commands cmd, const char *argument)
{
int ret = 0;
int bulk;
client_conn_t *dup_conn = (client_conn_t *) malloc(sizeof(struct client_conn_tag));
static int dispatch_command(client_conn_t *conn, enum commands cmd, const char *argument)
{
int ret = 0;
int bulk;
client_conn_t *dup_conn = (client_conn_t *)malloc(sizeof(struct client_conn_tag));
if(!dup_conn) {
logg("!Can't allocate memory for client_conn\n");
return -1;
}
memcpy(dup_conn, conn, sizeof(*conn));
dup_conn->cmdtype = cmd;
if(cl_engine_addref(dup_conn->engine)) {
logg("!cl_engine_addref() failed\n");
free(dup_conn);
return -1;
}
dup_conn->scanfd = -1;
bulk = 1;
switch (cmd) {
case COMMAND_FILDES:
if (conn->scanfd == -1) {
conn_reply_error(dup_conn, "No file descriptor received.");
ret = 1;
}
dup_conn->scanfd = conn->scanfd;
/* consume FD */
conn->scanfd = -1;
break;
case COMMAND_SCAN:
case COMMAND_CONTSCAN:
case COMMAND_MULTISCAN:
case COMMAND_ALLMATCHSCAN:
dup_conn->filename = cli_strdup_to_utf8(argument);
if (!dup_conn->filename) {
logg("!Failed to allocate memory for filename\n");
ret = -1;
}
break;
case COMMAND_INSTREAMSCAN:
dup_conn->scanfd = conn->scanfd;
conn->scanfd = -1;
break;
case COMMAND_STREAM:
case COMMAND_STATS:
/* not a scan command, don't queue to bulk */
bulk = 0;
/* just dispatch the command */
break;
default:
logg("!Invalid command dispatch: %d\n", cmd);
ret = -2;
break;
if (!dup_conn) {
logg("!Can't allocate memory for client_conn\n");
return -1;
}
memcpy(dup_conn, conn, sizeof(*conn));
dup_conn->cmdtype = cmd;
if (cl_engine_addref(dup_conn->engine)) {
logg("!cl_engine_addref() failed\n");
free(dup_conn);
return -1;
}
dup_conn->scanfd = -1;
bulk = 1;
switch (cmd) {
case COMMAND_FILDES:
if (conn->scanfd == -1) {
conn_reply_error(dup_conn, "No file descriptor received.");
ret = 1;
}
dup_conn->scanfd = conn->scanfd;
/* consume FD */
conn->scanfd = -1;
break;
case COMMAND_SCAN:
case COMMAND_CONTSCAN:
case COMMAND_MULTISCAN:
case COMMAND_ALLMATCHSCAN:
dup_conn->filename = cli_strdup_to_utf8(argument);
if (!dup_conn->filename) {
logg("!Failed to allocate memory for filename\n");
ret = -1;
}
break;
case COMMAND_INSTREAMSCAN:
dup_conn->scanfd = conn->scanfd;
conn->scanfd = -1;
break;
case COMMAND_STREAM:
case COMMAND_STATS:
/* not a scan command, don't queue to bulk */
bulk = 0;
/* just dispatch the command */
break;
default:
logg("!Invalid command dispatch: %d\n", cmd);
ret = -2;
break;
}
if (!dup_conn->group)
bulk = 0;
if(!ret && !thrmgr_group_dispatch(dup_conn->thrpool, dup_conn->group, dup_conn, bulk)) {
logg("!thread dispatch failed\n");
ret = -2;
bulk = 0;
if (!ret && !thrmgr_group_dispatch(dup_conn->thrpool, dup_conn->group, dup_conn, bulk)) {
logg("!thread dispatch failed\n");
ret = -2;
}
if (ret) {
cl_engine_free(dup_conn->engine);
free(dup_conn);
cl_engine_free(dup_conn->engine);
free(dup_conn);
}
return ret;
}
@ -489,15 +487,15 @@ static int print_ver(int desc, char term, const struct cl_engine *engine)
uint32_t ver;
ver = cl_engine_get_num(engine, CL_ENGINE_DB_VERSION, NULL);
if(ver) {
char timestr[32];
const char *tstr;
time_t t;
t = cl_engine_get_num(engine, CL_ENGINE_DB_TIME, NULL);
tstr = cli_ctime(&t, timestr, sizeof(timestr));
/* cut trailing \n */
timestr[strlen(tstr)-1] = '\0';
return mdprintf(desc, "ClamAV %s/%u/%s%c", get_version(), (unsigned int) ver, tstr, term);
if (ver) {
char timestr[32];
const char *tstr;
time_t t;
t = cl_engine_get_num(engine, CL_ENGINE_DB_TIME, NULL);
tstr = cli_ctime(&t, timestr, sizeof(timestr));
/* cut trailing \n */
timestr[strlen(tstr) - 1] = '\0';
return mdprintf(desc, "ClamAV %s/%u/%s%c", get_version(), (unsigned int)ver, tstr, term);
}
return mdprintf(desc, "ClamAV %s%c", get_version(), term);
}
@ -506,17 +504,17 @@ static void print_commands(int desc, char term, const struct cl_engine *engine)
{
unsigned i, n;
const char *engine_ver = cl_retver();
const char *clamd_ver = get_version();
const char *clamd_ver = get_version();
if (strcmp(engine_ver, clamd_ver)) {
mdprintf(desc, "ENGINE VERSION MISMATCH: %s != %s. ERROR%c",
engine_ver, clamd_ver, term);
return;
mdprintf(desc, "ENGINE VERSION MISMATCH: %s != %s. ERROR%c",
engine_ver, clamd_ver, term);
return;
}
print_ver(desc, '|', engine);
mdprintf(desc, " COMMANDS:");
n = sizeof(commands)/sizeof(commands[0]);
for (i=0;i<n;i++) {
mdprintf(desc, " %s", commands[i].cmd);
n = sizeof(commands) / sizeof(commands[0]);
for (i = 0; i < n; i++) {
mdprintf(desc, " %s", commands[i].cmd);
}
mdprintf(desc, "%c", term);
}
@ -530,8 +528,8 @@ static void print_commands(int desc, char term, const struct cl_engine *engine)
*/
int execute_or_dispatch_command(client_conn_t *conn, enum commands cmd, const char *argument)
{
int desc = conn->sd;
char term = conn->term;
int desc = conn->sd;
char term = conn->term;
const struct cl_engine *engine = conn->engine;
/* execute commands that can be executed quickly on the recvloop thread,
* these must:
@ -540,105 +538,100 @@ int execute_or_dispatch_command(client_conn_t *conn, enum commands cmd, const ch
* - send of atomic message is allowed.
* Dispatch other commands */
if (conn->group) {
switch (cmd) {
case COMMAND_FILDES:
case COMMAND_SCAN:
case COMMAND_END:
case COMMAND_INSTREAM:
case COMMAND_INSTREAMSCAN:
case COMMAND_VERSION:
case COMMAND_PING:
case COMMAND_STATS:
case COMMAND_COMMANDS:
/* These commands are accepted inside IDSESSION */
break;
default:
/* these commands are not recognized inside an IDSESSION */
conn_reply_error(conn, "Command invalid inside IDSESSION.");
logg("$SESSION: command is not valid inside IDSESSION: %d\n", cmd);
conn->group = NULL;
return 1;
}
switch (cmd) {
case COMMAND_FILDES:
case COMMAND_SCAN:
case COMMAND_END:
case COMMAND_INSTREAM:
case COMMAND_INSTREAMSCAN:
case COMMAND_VERSION:
case COMMAND_PING:
case COMMAND_STATS:
case COMMAND_COMMANDS:
/* These commands are accepted inside IDSESSION */
break;
default:
/* these commands are not recognized inside an IDSESSION */
conn_reply_error(conn, "Command invalid inside IDSESSION.");
logg("$SESSION: command is not valid inside IDSESSION: %d\n", cmd);
conn->group = NULL;
return 1;
}
}
switch (cmd) {
case COMMAND_SHUTDOWN:
pthread_mutex_lock(&exit_mutex);
progexit = 1;
pthread_mutex_unlock(&exit_mutex);
return 1;
case COMMAND_RELOAD:
pthread_mutex_lock(&reload_mutex);
reload = 1;
pthread_mutex_unlock(&reload_mutex);
mdprintf(desc, "RELOADING%c", term);
/* we set reload flag, and we'll reload before closing the
case COMMAND_SHUTDOWN:
pthread_mutex_lock(&exit_mutex);
progexit = 1;
pthread_mutex_unlock(&exit_mutex);
return 1;
case COMMAND_RELOAD:
pthread_mutex_lock(&reload_mutex);
reload = 1;
pthread_mutex_unlock(&reload_mutex);
mdprintf(desc, "RELOADING%c", term);
/* we set reload flag, and we'll reload before closing the
* connection */
return 1;
case COMMAND_PING:
if (conn->group)
mdprintf(desc, "%u: PONG%c", conn->id, term);
else
mdprintf(desc, "PONG%c", term);
return conn->group ? 0 : 1;
case COMMAND_VERSION:
{
if (conn->group)
mdprintf(desc, "%u: ", conn->id);
print_ver(desc, conn->term, engine);
return conn->group ? 0 : 1;
}
case COMMAND_COMMANDS:
{
if (conn->group)
mdprintf(desc, "%u: ", conn->id);
print_commands(desc, conn->term, engine);
return conn->group ? 0 : 1;
}
case COMMAND_DETSTATSCLEAR:
{
/* TODO: tell client this command has been removed */
return 1;
}
case COMMAND_DETSTATS:
{
/* TODO: tell client this command has been removed */
return 1;
}
case COMMAND_INSTREAM:
{
int rc = cli_gentempfd(optget(conn->opts, "TemporaryDirectory")->strarg, &conn->filename, &conn->scanfd);
if (rc != CL_SUCCESS)
return rc;
conn->quota = optget(conn->opts, "StreamMaxLength")->numarg;
conn->mode = MODE_STREAM;
return 0;
}
case COMMAND_STREAM:
case COMMAND_MULTISCAN:
case COMMAND_CONTSCAN:
case COMMAND_STATS:
case COMMAND_FILDES:
case COMMAND_SCAN:
case COMMAND_INSTREAMSCAN:
case COMMAND_ALLMATCHSCAN:
return dispatch_command(conn, cmd, argument);
case COMMAND_IDSESSION:
conn->group = thrmgr_group_new();
if (!conn->group)
return CL_EMEM;
return 0;
case COMMAND_END:
if (!conn->group) {
/* end without idsession? */
conn_reply_single(conn, NULL, "UNKNOWN COMMAND");
return 1;
}
/* need to close connection if we were last in group */
return 1;
/*case COMMAND_UNKNOWN:*/
default:
conn_reply_single(conn, NULL, "UNKNOWN COMMAND");
return 1;
return 1;
case COMMAND_PING:
if (conn->group)
mdprintf(desc, "%u: PONG%c", conn->id, term);
else
mdprintf(desc, "PONG%c", term);
return conn->group ? 0 : 1;
case COMMAND_VERSION: {
if (conn->group)
mdprintf(desc, "%u: ", conn->id);
print_ver(desc, conn->term, engine);
return conn->group ? 0 : 1;
}
case COMMAND_COMMANDS: {
if (conn->group)
mdprintf(desc, "%u: ", conn->id);
print_commands(desc, conn->term, engine);
return conn->group ? 0 : 1;
}
case COMMAND_DETSTATSCLEAR: {
/* TODO: tell client this command has been removed */
return 1;
}
case COMMAND_DETSTATS: {
/* TODO: tell client this command has been removed */
return 1;
}
case COMMAND_INSTREAM: {
int rc = cli_gentempfd(optget(conn->opts, "TemporaryDirectory")->strarg, &conn->filename, &conn->scanfd);
if (rc != CL_SUCCESS)
return rc;
conn->quota = optget(conn->opts, "StreamMaxLength")->numarg;
conn->mode = MODE_STREAM;
return 0;
}
case COMMAND_STREAM:
case COMMAND_MULTISCAN:
case COMMAND_CONTSCAN:
case COMMAND_STATS:
case COMMAND_FILDES:
case COMMAND_SCAN:
case COMMAND_INSTREAMSCAN:
case COMMAND_ALLMATCHSCAN:
return dispatch_command(conn, cmd, argument);
case COMMAND_IDSESSION:
conn->group = thrmgr_group_new();
if (!conn->group)
return CL_EMEM;
return 0;
case COMMAND_END:
if (!conn->group) {
/* end without idsession? */
conn_reply_single(conn, NULL, "UNKNOWN COMMAND");
return 1;
}
/* need to close connection if we were last in group */
return 1;
/*case COMMAND_UNKNOWN:*/
default:
conn_reply_single(conn, NULL, "UNKNOWN COMMAND");
return 1;
}
}

View file

@ -22,7 +22,6 @@
#ifndef __SESSION_H
#define __SESSION_H
#define CMD1 "SCAN"
/* #define CMD2 "RAWSCAN" */
#define CMD3 "QUIT" /* deprecated */
@ -52,7 +51,7 @@
#include "others.h"
enum commands {
COMMAND_UNKNOWN = 0,
COMMAND_UNKNOWN = 0,
COMMAND_SHUTDOWN = 1,
COMMAND_RELOAD,
COMMAND_END,

View file

@ -29,7 +29,7 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifndef _WIN32
#ifndef _WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@ -57,44 +57,34 @@ int tcpserver(int **lsockets, unsigned int *nlsockets, char *ipaddr, const struc
char *estr, port[10];
int yes = 1;
int res;
unsigned int i=0;
int num_fd;
unsigned int i = 0;
int num_fd;
sockets = *lsockets;
num_fd = sd_listen_fds(0);
if (num_fd > 2)
{
if (num_fd > 2) {
logg("!TCP: Received more than two file descriptors from systemd.\n");
return -1;
}
else if (num_fd > 0)
{
} else if (num_fd > 0) {
/* use socket passed by systemd */
int i;
for(i = 0; i < num_fd; i += 1)
{
for (i = 0; i < num_fd; i += 1) {
sockfd = SD_LISTEN_FDS_START + i;
if (sd_is_socket(sockfd, AF_INET, SOCK_STREAM, 1) == 1)
{
if (sd_is_socket(sockfd, AF_INET, SOCK_STREAM, 1) == 1) {
/* correct socket */
logg("#TCP: Received AF_INET SOCK_STREAM socket from systemd.\n");
break;
}
else if (sd_is_socket(sockfd, AF_INET6, SOCK_STREAM, 1) == 1)
{
} else if (sd_is_socket(sockfd, AF_INET6, SOCK_STREAM, 1) == 1) {
/* correct socket */
logg("#TCP: Received AF_INET6 SOCK_STREAM socket from systemd.\n");
break;
}
else
{
} else {
/* wrong socket */
sockfd = -2;
}
}
if (sockfd == -2)
{
if (sockfd == -2) {
logg("#TCP: No tcp AF_INET/AF_INET6 SOCK_STREAM socket received from systemd.\n");
return -2;
}
@ -115,9 +105,9 @@ int tcpserver(int **lsockets, unsigned int *nlsockets, char *ipaddr, const struc
snprintf(port, sizeof(port), "%lld", optget(opts, "TCPSocket")->numarg);
memset(&hints, 0x00, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
hints.ai_flags = AI_PASSIVE;
#ifdef AI_ADDRCONFIG
hints.ai_flags |= AI_ADDRCONFIG;
@ -131,7 +121,7 @@ int tcpserver(int **lsockets, unsigned int *nlsockets, char *ipaddr, const struc
for (p = info; p != NULL; p = p->ai_next, i++) {
t = realloc(sockets, sizeof(int) * (*nlsockets + 1));
if (!(t)) {
for (i=0; i < *nlsockets; i++)
for (i = 0; i < *nlsockets; i++)
close(sockets[i]);
return -1;
@ -144,7 +134,7 @@ int tcpserver(int **lsockets, unsigned int *nlsockets, char *ipaddr, const struc
continue;
}
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &yes, sizeof(yes)) == -1) {
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)) == -1) {
logg("!TCP: setsocktopt(SO_REUSEADDR) error: %s\n", strerror(errno));
}
@ -158,20 +148,20 @@ int tcpserver(int **lsockets, unsigned int *nlsockets, char *ipaddr, const struc
#ifdef HAVE_GETNAMEINFO
if ((res = getnameinfo(p->ai_addr, p->ai_addrlen, host, sizeof(host),
serv, sizeof(serv), NI_NUMERICHOST|NI_NUMERICSERV))) {
serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV))) {
logg("!TCP: getnameinfo failed: %s\n", gai_strerror(res));
host[0] = '\0';
serv[0] = '\0';
}
#else
if (ipaddr) {
strncpy(host, ipaddr, sizeof(host));
host[sizeof(host)-1] = '\0';
} else
host[0] = '\0';
if (ipaddr) {
strncpy(host, ipaddr, sizeof(host));
host[sizeof(host) - 1] = '\0';
} else
host[0] = '\0';
snprintf(serv, sizeof(serv), "%u", (unsigned int)(optget(opts, "TCPSocket")->numarg));
#endif
if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
estr = strerror(errno);
logg("!TCP: Cannot bind to [%s]:%s: %s\n", host, serv, estr);
closesocket(sockfd);
@ -183,7 +173,7 @@ int tcpserver(int **lsockets, unsigned int *nlsockets, char *ipaddr, const struc
backlog = optget(opts, "MaxConnectionQueueLength")->numarg;
logg("#TCP: Setting connection queue length to %d\n", backlog);
if(listen(sockfd, backlog) == -1) {
if (listen(sockfd, backlog) == -1) {
estr = strerror(errno);
logg("!TCP: Cannot listen on [%s]:%s: %s\n", host, serv, estr);
closesocket(sockfd);

File diff suppressed because it is too large Load diff

View file

@ -30,65 +30,65 @@
#endif
typedef struct work_item_tag {
struct work_item_tag *next;
void *data;
struct timeval time_queued;
struct work_item_tag *next;
void *data;
struct timeval time_queued;
} work_item_t;
typedef struct work_queue_tag {
work_item_t *head;
work_item_t *tail;
int item_count;
int popped;
work_item_t *head;
work_item_t *tail;
int item_count;
int popped;
} work_queue_t;
typedef enum {
POOL_INVALID,
POOL_VALID,
POOL_EXIT
POOL_INVALID,
POOL_VALID,
POOL_EXIT
} pool_state_t;
struct task_desc {
const char *filename;
const char *command;
struct timeval tv;
struct task_desc *prv;
struct task_desc *nxt;
const struct cl_engine *engine;
const char *filename;
const char *command;
struct timeval tv;
struct task_desc *prv;
struct task_desc *nxt;
const struct cl_engine *engine;
};
typedef struct threadpool_tag {
pthread_mutex_t pool_mutex;
pthread_cond_t pool_cond;
pthread_attr_t pool_attr;
pthread_mutex_t pool_mutex;
pthread_cond_t pool_cond;
pthread_attr_t pool_attr;
pthread_cond_t idle_cond;
pthread_cond_t queueable_single_cond;
pthread_cond_t queueable_bulk_cond;
pthread_cond_t idle_cond;
pthread_cond_t queueable_single_cond;
pthread_cond_t queueable_bulk_cond;
pool_state_t state;
int thr_max;
int queue_max;
int thr_alive;
int thr_idle;
int thr_multiscan;
int idle_timeout;
struct task_desc *tasks;
pool_state_t state;
int thr_max;
int queue_max;
int thr_alive;
int thr_idle;
int thr_multiscan;
int idle_timeout;
struct task_desc *tasks;
void (*handler)(void *);
void (*handler)(void *);
work_queue_t *bulk_queue;
work_queue_t *single_queue;
work_queue_t *bulk_queue;
work_queue_t *single_queue;
} threadpool_t;
typedef struct jobgroup {
pthread_mutex_t mutex;
pthread_cond_t only;
unsigned jobs;
unsigned exit_ok;
unsigned exit_error;
unsigned exit_total;
int force_exit;
unsigned jobs;
unsigned exit_ok;
unsigned exit_error;
unsigned exit_total;
int force_exit;
} jobgroup_t;
enum thrmgr_exit {
@ -107,7 +107,7 @@ int thrmgr_group_need_terminate(jobgroup_t *group);
void thrmgr_group_terminate(jobgroup_t *group);
jobgroup_t *thrmgr_group_new(void);
int thrmgr_printstats(int outfd, char term);
void thrmgr_setactivetask(const char *filename, const char* command);
void thrmgr_setactivetask(const char *filename, const char *command);
void thrmgr_setactiveengine(const struct cl_engine *engine);
#endif

View file

@ -52,87 +52,86 @@ struct optstruct *clamdopts = NULL;
static void print_server_version(const struct optstruct *opt)
{
if(get_clamd_version(opt)) {
/* can't get version from server, fallback */
printf("ClamAV %s\n", get_version());
if (get_clamd_version(opt)) {
/* can't get version from server, fallback */
printf("ClamAV %s\n", get_version());
}
}
int main(int argc, char **argv)
{
int ds, dms, ret, infected = 0, err = 0;
struct timeval t1, t2;
time_t starttime;
struct optstruct *opts;
const struct optstruct *opt;
int ds, dms, ret, infected = 0, err = 0;
struct timeval t1, t2;
time_t starttime;
struct optstruct *opts;
const struct optstruct *opt;
#ifndef _WIN32
struct sigaction sigact;
struct sigaction sigact;
#endif
if((opts = optparse(NULL, argc, argv, 1, OPT_CLAMDSCAN, OPT_CLAMSCAN, NULL)) == NULL) {
mprintf("!Can't parse command line options\n");
return 2;
if ((opts = optparse(NULL, argc, argv, 1, OPT_CLAMDSCAN, OPT_CLAMSCAN, NULL)) == NULL) {
mprintf("!Can't parse command line options\n");
return 2;
}
if((clamdopts = optparse(optget(opts, "config-file")->strarg, 0, NULL, 1, OPT_CLAMD, 0, NULL)) == NULL) {
logg("!Can't parse clamd configuration file %s\n", optget(opts, "config-file")->strarg);
return 2;
if ((clamdopts = optparse(optget(opts, "config-file")->strarg, 0, NULL, 1, OPT_CLAMD, 0, NULL)) == NULL) {
logg("!Can't parse clamd configuration file %s\n", optget(opts, "config-file")->strarg);
return 2;
}
if(optget(opts, "verbose")->enabled) {
mprintf_verbose = 1;
logg_verbose = 1;
if (optget(opts, "verbose")->enabled) {
mprintf_verbose = 1;
logg_verbose = 1;
}
if(optget(opts, "quiet")->enabled)
mprintf_quiet = 1;
if (optget(opts, "quiet")->enabled)
mprintf_quiet = 1;
if(optget(opts, "stdout")->enabled)
mprintf_stdout = 1;
if (optget(opts, "stdout")->enabled)
mprintf_stdout = 1;
if(optget(opts, "version")->enabled) {
print_server_version(opts);
optfree(opts);
optfree(clamdopts);
exit(0);
if (optget(opts, "version")->enabled) {
print_server_version(opts);
optfree(opts);
optfree(clamdopts);
exit(0);
}
if(optget(opts, "help")->enabled) {
optfree(opts);
optfree(clamdopts);
help();
if (optget(opts, "help")->enabled) {
optfree(opts);
optfree(clamdopts);
help();
}
if(optget(opts, "infected")->enabled)
printinfected = 1;
if (optget(opts, "infected")->enabled)
printinfected = 1;
/* initialize logger */
if((opt = optget(opts, "log"))->enabled) {
logg_file = opt->strarg;
if(logg("--------------------------------------\n")) {
mprintf("!Problem with internal logger.\n");
optfree(opts);
optfree(clamdopts);
exit(2);
}
if ((opt = optget(opts, "log"))->enabled) {
logg_file = opt->strarg;
if (logg("--------------------------------------\n")) {
mprintf("!Problem with internal logger.\n");
optfree(opts);
optfree(clamdopts);
exit(2);
}
} else
logg_file = NULL;
logg_file = NULL;
if(optget(opts, "reload")->enabled) {
ret = reload_clamd_database(opts);
optfree(opts);
optfree(clamdopts);
logg_close();
exit(ret);
if (optget(opts, "reload")->enabled) {
ret = reload_clamd_database(opts);
optfree(opts);
optfree(clamdopts);
logg_close();
exit(ret);
}
if(actsetup(opts)) {
optfree(opts);
optfree(clamdopts);
logg_close();
exit(2);
if (actsetup(opts)) {
optfree(opts);
optfree(clamdopts);
logg_close();
exit(2);
}
#ifndef _WIN32
@ -152,23 +151,23 @@ int main(int argc, char **argv)
optfree(clamdopts);
/* TODO: Implement STATUS in clamd */
if(!optget(opts, "no-summary")->enabled) {
gettimeofday(&t2, NULL);
ds = t2.tv_sec - t1.tv_sec;
dms = t2.tv_usec - t1.tv_usec;
ds -= (dms < 0) ? (1):(0);
dms += (dms < 0) ? (1000000):(0);
logg("\n----------- SCAN SUMMARY -----------\n");
logg("Infected files: %d\n", infected);
if(err)
logg("Total errors: %d\n", err);
if(notremoved) {
logg("Not removed: %d\n", notremoved);
}
if(notmoved) {
logg("Not moved: %d\n", notmoved);
}
logg("Time: %d.%3.3d sec (%d m %d s)\n", ds, dms/1000, ds/60, ds%60);
if (!optget(opts, "no-summary")->enabled) {
gettimeofday(&t2, NULL);
ds = t2.tv_sec - t1.tv_sec;
dms = t2.tv_usec - t1.tv_usec;
ds -= (dms < 0) ? (1) : (0);
dms += (dms < 0) ? (1000000) : (0);
logg("\n----------- SCAN SUMMARY -----------\n");
logg("Infected files: %d\n", infected);
if (err)
logg("Total errors: %d\n", err);
if (notremoved) {
logg("Not removed: %d\n", notremoved);
}
if (notmoved) {
logg("Not moved: %d\n", notmoved);
}
logg("Time: %d.%3.3d sec (%d m %d s)\n", ds, dms / 1000, ds / 60, ds % 60);
}
logg_close();

View file

@ -25,7 +25,7 @@
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
@ -74,7 +74,8 @@ extern struct optstruct *clamdopts;
/* Inits the communication layer
* Returns 0 if clamd is local, non zero if clamd is remote */
static int isremote(const struct optstruct *opts) {
static int isremote(const struct optstruct *opts)
{
int s, ret;
const struct optstruct *opt;
char *ipaddr, port[10];
@ -84,15 +85,15 @@ static int isremote(const struct optstruct *opts) {
UNUSEDPARAM(opts);
#ifndef _WIN32
if((opt = optget(clamdopts, "LocalSocket"))->enabled) {
if ((opt = optget(clamdopts, "LocalSocket"))->enabled) {
memset((void *)&nixsock, 0, sizeof(nixsock));
nixsock.sun_family = AF_UNIX;
strncpy(nixsock.sun_path, opt->strarg, sizeof(nixsock.sun_path));
nixsock.sun_path[sizeof(nixsock.sun_path)-1]='\0';
nixsock.sun_path[sizeof(nixsock.sun_path) - 1] = '\0';
return 0;
}
#endif
if(!(opt = optget(clamdopts, "TCPSocket"))->enabled)
if (!(opt = optget(clamdopts, "TCPSocket"))->enabled)
return 0;
snprintf(port, sizeof(port), "%lld", optget(clamdopts, "TCPSocket")->numarg);
@ -104,9 +105,9 @@ static int isremote(const struct optstruct *opts) {
ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg);
memset(&hints, 0x00, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
hints.ai_flags = AI_PASSIVE;
if ((res = getaddrinfo(ipaddr, port, &hints, &info))) {
logg("!Can't lookup clamd hostname: %s\n", gai_strerror(res));
@ -115,20 +116,20 @@ static int isremote(const struct optstruct *opts) {
}
for (p = info; p != NULL; p = p->ai_next) {
if((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
if ((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
logg("isremote: socket() returning: %s.\n", strerror(errno));
continue;
}
switch (p->ai_family) {
case AF_INET:
((struct sockaddr_in *)(p->ai_addr))->sin_port = htons(INADDR_ANY);
break;
case AF_INET6:
((struct sockaddr_in6 *)(p->ai_addr))->sin6_port = htons(INADDR_ANY);
break;
default:
break;
case AF_INET:
((struct sockaddr_in *)(p->ai_addr))->sin_port = htons(INADDR_ANY);
break;
case AF_INET6:
((struct sockaddr_in6 *)(p->ai_addr))->sin6_port = htons(INADDR_ANY);
break;
default:
break;
}
ret = bind(s, p->ai_addr, p->ai_addrlen);
@ -159,34 +160,34 @@ static int isremote(const struct optstruct *opts) {
return 0;
}
/* Turns a relative path into an absolute one
* Returns a pointer to the path (which must be
* freed by the caller) or NULL on error */
static char *makeabs(const char *basepath) {
static char *makeabs(const char *basepath)
{
int namelen;
char *ret;
if(!(ret = malloc(PATH_MAX + 1))) {
logg("^Can't make room for fullpath.\n");
return NULL;
if (!(ret = malloc(PATH_MAX + 1))) {
logg("^Can't make room for fullpath.\n");
return NULL;
}
if(!cli_is_abspath(basepath)) {
if(!getcwd(ret, PATH_MAX)) {
logg("^Can't get absolute pathname of current working directory.\n");
free(ret);
return NULL;
}
if (!cli_is_abspath(basepath)) {
if (!getcwd(ret, PATH_MAX)) {
logg("^Can't get absolute pathname of current working directory.\n");
free(ret);
return NULL;
}
#ifdef _WIN32
if(*basepath == '\\') {
namelen = 2;
basepath++;
} else
if (*basepath == '\\') {
namelen = 2;
basepath++;
} else
#endif
namelen = strlen(ret);
snprintf(&ret[namelen], PATH_MAX - namelen, PATHSEP"%s", basepath);
namelen = strlen(ret);
snprintf(&ret[namelen], PATH_MAX - namelen, PATHSEP "%s", basepath);
} else {
strncpy(ret, basepath, PATH_MAX);
strncpy(ret, basepath, PATH_MAX);
}
ret[PATH_MAX] = '\0';
return ret;
@ -194,41 +195,42 @@ static char *makeabs(const char *basepath) {
/* Recursively scans a path with the given scantype
* Returns non zero for serious errors, zero otherwise */
static int client_scan(const char *file, int scantype, int *infected, int *err, int maxlevel, int session, int flags) {
static int client_scan(const char *file, int scantype, int *infected, int *err, int maxlevel, int session, int flags)
{
int ret;
char *fullpath = makeabs(file);
if(!fullpath)
return 0;
if (!fullpath)
return 0;
if (!session)
ret = serial_client_scan(fullpath, scantype, infected, err, maxlevel, flags);
ret = serial_client_scan(fullpath, scantype, infected, err, maxlevel, flags);
else
ret = parallel_client_scan(fullpath, scantype, infected, err, maxlevel, flags);
ret = parallel_client_scan(fullpath, scantype, infected, err, maxlevel, flags);
free(fullpath);
return ret;
}
int get_clamd_version(const struct optstruct *opts)
{
char *buff;
int len, sockd;
struct RCVLN rcv;
char *buff;
int len, sockd;
struct RCVLN rcv;
isremote(opts);
if((sockd = dconnect()) < 0) return 2;
if ((sockd = dconnect()) < 0) return 2;
recvlninit(&rcv, sockd);
if(sendln(sockd, "zVERSION", 9)) {
closesocket(sockd);
return 2;
if (sendln(sockd, "zVERSION", 9)) {
closesocket(sockd);
return 2;
}
while((len = recvln(&rcv, &buff, NULL))) {
if(len == -1) {
logg("!Error occurred while receiving version information.\n");
break;
}
printf("%s\n", buff);
while ((len = recvln(&rcv, &buff, NULL))) {
if (len == -1) {
logg("!Error occurred while receiving version information.\n");
break;
}
printf("%s\n", buff);
}
closesocket(sockd);
@ -237,23 +239,23 @@ int get_clamd_version(const struct optstruct *opts)
int reload_clamd_database(const struct optstruct *opts)
{
char *buff;
int len, sockd;
struct RCVLN rcv;
char *buff;
int len, sockd;
struct RCVLN rcv;
isremote(opts);
if((sockd = dconnect()) < 0) return 2;
if ((sockd = dconnect()) < 0) return 2;
recvlninit(&rcv, sockd);
if(sendln(sockd, "zRELOAD", 8)) {
closesocket(sockd);
return 2;
if (sendln(sockd, "zRELOAD", 8)) {
closesocket(sockd);
return 2;
}
if(!(len = recvln(&rcv, &buff, NULL)) || len < 10 || memcmp(buff, "RELOADING", 9)) {
logg("!Clamd did not reload the database\n");
closesocket(sockd);
return 2;
if (!(len = recvln(&rcv, &buff, NULL)) || len < 10 || memcmp(buff, "RELOADING", 9)) {
logg("!Clamd did not reload the database\n");
closesocket(sockd);
return 2;
}
closesocket(sockd);
return 0;
@ -261,68 +263,70 @@ int reload_clamd_database(const struct optstruct *opts)
int client(const struct optstruct *opts, int *infected, int *err)
{
int remote, scantype, session = 0, errors = 0, scandash = 0, maxrec, flags = 0;
const char *fname;
int remote, scantype, session = 0, errors = 0, scandash = 0, maxrec, flags = 0;
const char *fname;
scandash = (opts->filename && opts->filename[0] && !strcmp(opts->filename[0], "-") && !optget(opts, "file-list")->enabled && !opts->filename[1]);
remote = isremote(opts) | optget(opts, "stream")->enabled;
remote = isremote(opts) | optget(opts, "stream")->enabled;
#ifdef HAVE_FD_PASSING
if(!remote && optget(clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled || scandash)) {
scantype = FILDES;
session = optget(opts, "multiscan")->enabled;
if (!remote && optget(clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled || scandash)) {
scantype = FILDES;
session = optget(opts, "multiscan")->enabled;
} else
#endif
if(remote || scandash) {
scantype = STREAM;
session = optget(opts, "multiscan")->enabled;
}
else if(optget(opts, "multiscan")->enabled) scantype = MULTI;
else if(optget(opts, "allmatch")->enabled) scantype = ALLMATCH;
else scantype = CONT;
if (remote || scandash) {
scantype = STREAM;
session = optget(opts, "multiscan")->enabled;
} else if (optget(opts, "multiscan")->enabled)
scantype = MULTI;
else if (optget(opts, "allmatch")->enabled)
scantype = ALLMATCH;
else
scantype = CONT;
maxrec = optget(clamdopts, "MaxDirectoryRecursion")->numarg;
maxrec = optget(clamdopts, "MaxDirectoryRecursion")->numarg;
maxstream = optget(clamdopts, "StreamMaxLength")->numarg;
if (optget(clamdopts, "FollowDirectorySymlinks")->enabled)
flags |= CLI_FTW_FOLLOW_DIR_SYMLINK;
flags |= CLI_FTW_FOLLOW_DIR_SYMLINK;
if (optget(clamdopts, "FollowFileSymlinks")->enabled)
flags |= CLI_FTW_FOLLOW_FILE_SYMLINK;
flags |= CLI_FTW_FOLLOW_FILE_SYMLINK;
flags |= CLI_FTW_TRIM_SLASHES;
*infected = 0;
if(scandash) {
int sockd, ret;
STATBUF sb;
if(FSTAT(0, &sb) < 0) {
logg("client.c: fstat failed for file name \"%s\", with %s\n.",
opts->filename[0], strerror(errno));
return 2;
}
if((sb.st_mode & S_IFMT) != S_IFREG) scantype = STREAM;
if((sockd = dconnect()) >= 0 && (ret = dsresult(sockd, scantype, NULL, &ret, NULL)) >= 0)
*infected = ret;
else
errors = 1;
if(sockd >= 0) closesocket(sockd);
} else if(opts->filename || optget(opts, "file-list")->enabled) {
if(opts->filename && optget(opts, "file-list")->enabled)
logg("^Only scanning files from --file-list (files passed at cmdline are ignored)\n");
if (scandash) {
int sockd, ret;
STATBUF sb;
if (FSTAT(0, &sb) < 0) {
logg("client.c: fstat failed for file name \"%s\", with %s\n.",
opts->filename[0], strerror(errno));
return 2;
}
if ((sb.st_mode & S_IFMT) != S_IFREG) scantype = STREAM;
if ((sockd = dconnect()) >= 0 && (ret = dsresult(sockd, scantype, NULL, &ret, NULL)) >= 0)
*infected = ret;
else
errors = 1;
if (sockd >= 0) closesocket(sockd);
} else if (opts->filename || optget(opts, "file-list")->enabled) {
if (opts->filename && optget(opts, "file-list")->enabled)
logg("^Only scanning files from --file-list (files passed at cmdline are ignored)\n");
while((fname = filelist(opts, NULL))) {
if(!strcmp(fname, "-")) {
logg("!Scanning from standard input requires \"-\" to be the only file argument\n");
continue;
}
errors += client_scan(fname, scantype, infected, err, maxrec, session, flags);
/* this may be too strict
while ((fname = filelist(opts, NULL))) {
if (!strcmp(fname, "-")) {
logg("!Scanning from standard input requires \"-\" to be the only file argument\n");
continue;
}
errors += client_scan(fname, scantype, infected, err, maxrec, session, flags);
/* this may be too strict
if(errors >= 10) {
logg("!Too many errors\n");
break;
}
*/
}
}
} else {
errors = client_scan("", scantype, infected, err, maxrec, session, flags);
errors = client_scan("", scantype, infected, err, maxrec, session, flags);
}
return *infected ? 1 : (errors ? 2 : 0);
}

View file

@ -69,11 +69,12 @@ extern struct optstruct *clamdopts;
extern struct sockaddr_un nixsock;
#endif
static const char *scancmd[] = { "CONTSCAN", "MULTISCAN", "INSTREAM", "FILDES", "ALLMATCHSCAN" };
static const char *scancmd[] = {"CONTSCAN", "MULTISCAN", "INSTREAM", "FILDES", "ALLMATCHSCAN"};
/* Connects to clamd
* Returns a FD or -1 on error */
int dconnect() {
int dconnect()
{
int sockd, res;
const struct optstruct *opt;
struct addrinfo hints, *info, *p;
@ -104,7 +105,7 @@ int dconnect() {
ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg);
memset(&hints, 0x00, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((res = getaddrinfo(ipaddr, port, &hints, &info))) {
@ -114,12 +115,12 @@ int dconnect() {
}
for (p = info; p != NULL; p = p->ai_next) {
if((sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
if ((sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
logg("!Can't create the socket: %s\n", strerror(errno));
continue;
}
if(connect(sockd, p->ai_addr, p->ai_addrlen) < 0) {
if (connect(sockd, p->ai_addr, p->ai_addrlen) < 0) {
logg("!Could not connect to clamd on %s: %s\n", opt->strarg, strerror(errno));
closesocket(sockd);
continue;
@ -139,42 +140,44 @@ int dconnect() {
/* Issues an INSTREAM command to clamd and streams the given file
* Returns >0 on success, 0 soft fail, -1 hard fail */
static int send_stream(int sockd, const char *filename) {
uint32_t buf[BUFSIZ/sizeof(uint32_t)];
static int send_stream(int sockd, const char *filename)
{
uint32_t buf[BUFSIZ / sizeof(uint32_t)];
int fd, len;
unsigned long int todo = maxstream;
if(filename) {
if((fd = safe_open(filename, O_RDONLY | O_BINARY))<0) {
logg("~%s: Access denied. ERROR\n", filename);
return 0;
}
} else fd = 0;
if (filename) {
if ((fd = safe_open(filename, O_RDONLY | O_BINARY)) < 0) {
logg("~%s: Access denied. ERROR\n", filename);
return 0;
}
} else
fd = 0;
if(sendln(sockd, "zINSTREAM", 10)) {
close(fd);
return -1;
if (sendln(sockd, "zINSTREAM", 10)) {
close(fd);
return -1;
}
while((len = read(fd, &buf[1], sizeof(buf) - sizeof(uint32_t))) > 0) {
if((unsigned int)len > todo) len = todo;
buf[0] = htonl(len);
if(sendln(sockd, (const char *)buf, len+sizeof(uint32_t))) {
close(fd);
return -1;
}
todo -= len;
if(!todo) {
len = 0;
break;
}
while ((len = read(fd, &buf[1], sizeof(buf) - sizeof(uint32_t))) > 0) {
if ((unsigned int)len > todo) len = todo;
buf[0] = htonl(len);
if (sendln(sockd, (const char *)buf, len + sizeof(uint32_t))) {
close(fd);
return -1;
}
todo -= len;
if (!todo) {
len = 0;
break;
}
}
close(fd);
if(len) {
logg("!Failed to read from %s.\n", filename ? filename : "STDIN");
return 0;
if (len) {
logg("!Failed to read from %s.\n", filename ? filename : "STDIN");
return 0;
}
*buf=0;
*buf = 0;
sendln(sockd, (const char *)buf, 4);
return 1;
}
@ -182,41 +185,43 @@ static int send_stream(int sockd, const char *filename) {
#ifdef HAVE_FD_PASSING
/* Issues a FILDES command and pass a FD to clamd
* Returns >0 on success, 0 soft fail, -1 hard fail */
static int send_fdpass(int sockd, const char *filename) {
static int send_fdpass(int sockd, const char *filename)
{
struct iovec iov[1];
struct msghdr msg;
struct cmsghdr *cmsg;
unsigned char fdbuf[CMSG_SPACE(sizeof(int))];
char dummy[]="";
char dummy[] = "";
int fd;
if(filename) {
if((fd = open(filename, O_RDONLY))<0) {
logg("~%s: Access denied. ERROR\n", filename);
return 0;
}
} else fd = 0;
if(sendln(sockd, "zFILDES", 8)) {
close(fd);
return -1;
if (filename) {
if ((fd = open(filename, O_RDONLY)) < 0) {
logg("~%s: Access denied. ERROR\n", filename);
return 0;
}
} else
fd = 0;
if (sendln(sockd, "zFILDES", 8)) {
close(fd);
return -1;
}
iov[0].iov_base = dummy;
iov[0].iov_len = 1;
iov[0].iov_len = 1;
memset(&msg, 0, sizeof(msg));
msg.msg_control = fdbuf;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_controllen = CMSG_LEN(sizeof(int));
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
msg.msg_control = fdbuf;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_controllen = CMSG_LEN(sizeof(int));
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = fd;
if(sendmsg(sockd, &msg, 0) == -1) {
logg("!FD send failed: %s\n", strerror(errno));
close(fd);
return -1;
if (sendmsg(sockd, &msg, 0) == -1) {
logg("!FD send failed: %s\n", strerror(errno));
close(fd);
return -1;
}
close(fd);
return 1;
@ -226,17 +231,17 @@ static int send_fdpass(int sockd, const char *filename) {
/* 0: scan, 1: skip */
static int chkpath(const char *path)
{
const struct optstruct *opt;
const struct optstruct *opt;
if((opt = optget(clamdopts, "ExcludePath"))->enabled) {
while(opt) {
if(match_regex(path, opt->strarg) == 1) {
if ((opt = optget(clamdopts, "ExcludePath"))->enabled) {
while (opt) {
if (match_regex(path, opt->strarg) == 1) {
if (printinfected != 1)
logg("~%s: Excluded\n", path);
return 1;
}
opt = opt->nextarg;
}
return 1;
}
opt = opt->nextarg;
}
}
return 0;
}
@ -251,83 +256,83 @@ static int ftw_chkpath(const char *path, struct cli_ftw_cbdata *data)
* This is used only in non IDSESSION mode
* Returns the number of infected files or -1 on error
* NOTE: filename may be NULL for STREAM scantype. */
int dsresult(int sockd, int scantype, const char *filename, int *printok, int *errors) {
int dsresult(int sockd, int scantype, const char *filename, int *printok, int *errors)
{
int infected = 0, len = 0, beenthere = 0;
char *bol, *eol;
struct RCVLN rcv;
STATBUF sb;
if(filename && chkpath(filename))
return 0;
if (filename && chkpath(filename))
return 0;
recvlninit(&rcv, sockd);
switch(scantype) {
case MULTI:
case CONT:
case ALLMATCH:
if (!filename) {
logg("Filename cannot be NULL for MULTISCAN or CONTSCAN.\n");
return -1;
}
len = strlen(filename) + strlen(scancmd[scantype]) + 3;
if (!(bol = malloc(len))) {
logg("!Cannot allocate a command buffer: %s\n", strerror(errno));
return -1;
}
sprintf(bol, "z%s %s", scancmd[scantype], filename);
if(sendln(sockd, bol, len)) {
free(bol);
return -1;
}
free(bol);
break;
switch (scantype) {
case MULTI:
case CONT:
case ALLMATCH:
if (!filename) {
logg("Filename cannot be NULL for MULTISCAN or CONTSCAN.\n");
return -1;
}
len = strlen(filename) + strlen(scancmd[scantype]) + 3;
if (!(bol = malloc(len))) {
logg("!Cannot allocate a command buffer: %s\n", strerror(errno));
return -1;
}
sprintf(bol, "z%s %s", scancmd[scantype], filename);
if (sendln(sockd, bol, len)) {
free(bol);
return -1;
}
free(bol);
break;
case STREAM:
/* NULL filename safe in send_stream() */
len = send_stream(sockd, filename);
break;
case STREAM:
/* NULL filename safe in send_stream() */
len = send_stream(sockd, filename);
break;
#ifdef HAVE_FD_PASSING
case FILDES:
/* NULL filename safe in send_fdpass() */
len = send_fdpass(sockd, filename);
break;
case FILDES:
/* NULL filename safe in send_fdpass() */
len = send_fdpass(sockd, filename);
break;
#endif
}
if(len <=0) {
*printok = 0;
if(errors)
(*errors)++;
return len;
if (len <= 0) {
*printok = 0;
if (errors)
(*errors)++;
return len;
}
while((len = recvln(&rcv, &bol, &eol))) {
if(len == -1) return -1;
beenthere = 1;
if(!filename) logg("~%s\n", bol);
if(len > 7) {
char *colon = strrchr(bol, ':');
if(colon && colon[1] != ' ') {
char *br;
*colon = 0;
br = strrchr(bol, '(');
if(br)
*br = 0;
colon = strrchr(bol, ':');
}
if(!colon) {
char * unkco = "UNKNOWN COMMAND";
if (!strncmp(bol, unkco, sizeof(unkco) - 1))
logg("clamd replied \"UNKNOWN COMMAND\". Command was %s\n",
(scantype < 0 || scantype > MAX_SCANTYPE) ? "unidentified" :
scancmd[scantype]);
else
logg("Failed to parse reply: \"%s\"\n", bol);
return -1;
} else if(!memcmp(eol - 7, " FOUND", 6)) {
static char last_filename[PATH_MAX+1] = {'\0'};
*(eol - 7) = 0;
*printok = 0;
while ((len = recvln(&rcv, &bol, &eol))) {
if (len == -1) return -1;
beenthere = 1;
if (!filename) logg("~%s\n", bol);
if (len > 7) {
char *colon = strrchr(bol, ':');
if (colon && colon[1] != ' ') {
char *br;
*colon = 0;
br = strrchr(bol, '(');
if (br)
*br = 0;
colon = strrchr(bol, ':');
}
if (!colon) {
char *unkco = "UNKNOWN COMMAND";
if (!strncmp(bol, unkco, sizeof(unkco) - 1))
logg("clamd replied \"UNKNOWN COMMAND\". Command was %s\n",
(scantype < 0 || scantype > MAX_SCANTYPE) ? "unidentified" : scancmd[scantype]);
else
logg("Failed to parse reply: \"%s\"\n", bol);
return -1;
} else if (!memcmp(eol - 7, " FOUND", 6)) {
static char last_filename[PATH_MAX + 1] = {'\0'};
*(eol - 7) = 0;
*printok = 0;
if (scantype != ALLMATCH) {
infected++;
} else {
@ -337,44 +342,44 @@ int dsresult(int sockd, int scantype, const char *filename, int *printok, int *e
last_filename[PATH_MAX] = '\0';
}
}
if(filename) {
if(scantype >= STREAM) {
logg("~%s%s FOUND\n", filename, colon);
if(action) action(filename);
} else {
logg("~%s FOUND\n", bol);
*colon = '\0';
if(action)
action(bol);
}
}
} else if(!memcmp(eol-7, " ERROR", 6)) {
if(errors)
(*errors)++;
*printok = 0;
if(filename) {
if(scantype >= STREAM)
logg("~%s%s\n", filename, colon);
else
logg("~%s\n", bol);
}
}
}
if (filename) {
if (scantype >= STREAM) {
logg("~%s%s FOUND\n", filename, colon);
if (action) action(filename);
} else {
logg("~%s FOUND\n", bol);
*colon = '\0';
if (action)
action(bol);
}
}
} else if (!memcmp(eol - 7, " ERROR", 6)) {
if (errors)
(*errors)++;
*printok = 0;
if (filename) {
if (scantype >= STREAM)
logg("~%s%s\n", filename, colon);
else
logg("~%s\n", bol);
}
}
}
}
if(!beenthere) {
if (!beenthere) {
if (!filename) {
logg("STDIN: noreply from clamd\n.");
return -1;
}
if(CLAMSTAT(filename, &sb) == -1) {
logg("~%s: stat() failed with %s, clamd may not be responding\n",
filename, strerror(errno));
return -1;
}
if(!S_ISDIR(sb.st_mode)) {
logg("~%s: no reply from clamd\n", filename);
return -1;
}
logg("STDIN: noreply from clamd\n.");
return -1;
}
if (CLAMSTAT(filename, &sb) == -1) {
logg("~%s: stat() failed with %s, clamd may not be responding\n",
filename, strerror(errno));
return -1;
}
if (!S_ISDIR(sb.st_mode)) {
logg("~%s: no reply from clamd\n", filename);
return -1;
}
}
return infected;
}
@ -390,85 +395,87 @@ struct client_serial_data {
/* FTW callback for scanning in non IDSESSION mode
* Returns SUCCESS or BREAK on success, CL_EXXX on error */
static int serial_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) {
static int serial_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data)
{
struct client_serial_data *c = (struct client_serial_data *)data->data;
int sockd, ret;
const char *f = filename;
UNUSEDPARAM(sb);
if(chkpath(path))
return CL_SUCCESS;
if (chkpath(path))
return CL_SUCCESS;
c->files++;
switch(reason) {
case error_stat:
logg("!Can't access file %s\n", path);
c->errors++;
return CL_SUCCESS;
case error_mem:
logg("!Memory allocation failed in ftw\n");
c->errors++;
return CL_EMEM;
case warning_skipped_dir:
logg("^Directory recursion limit reached\n");
case warning_skipped_link:
return CL_SUCCESS;
case warning_skipped_special:
logg("^%s: Not supported file type\n", path);
c->errors++;
return CL_SUCCESS;
case visit_directory_toplev:
if(c->scantype >= STREAM)
return CL_SUCCESS;
f = path;
filename = NULL;
case visit_file:
break;
switch (reason) {
case error_stat:
logg("!Can't access file %s\n", path);
c->errors++;
return CL_SUCCESS;
case error_mem:
logg("!Memory allocation failed in ftw\n");
c->errors++;
return CL_EMEM;
case warning_skipped_dir:
logg("^Directory recursion limit reached\n");
case warning_skipped_link:
return CL_SUCCESS;
case warning_skipped_special:
logg("^%s: Not supported file type\n", path);
c->errors++;
return CL_SUCCESS;
case visit_directory_toplev:
if (c->scantype >= STREAM)
return CL_SUCCESS;
f = path;
filename = NULL;
case visit_file:
break;
}
if((sockd = dconnect()) < 0) {
if(filename) free(filename);
c->errors++;
return CL_EOPEN;
if ((sockd = dconnect()) < 0) {
if (filename) free(filename);
c->errors++;
return CL_EOPEN;
}
ret = dsresult(sockd, c->scantype, f, &c->printok, &c->errors);
if(filename) free(filename);
if (filename) free(filename);
closesocket(sockd);
if(ret < 0) {
c->errors++;
return CL_EOPEN;
if (ret < 0) {
c->errors++;
return CL_EOPEN;
}
c->infected += ret;
if(reason == visit_directory_toplev)
return CL_BREAK;
if (reason == visit_directory_toplev)
return CL_BREAK;
return CL_SUCCESS;
}
/* Non-IDSESSION handler
* Returns non zero for serious errors, zero otherwise */
int serial_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags) {
int serial_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags)
{
struct cli_ftw_cbdata data;
struct client_serial_data cdata;
int ftw;
cdata.infected = 0;
cdata.files = 0;
cdata.errors = 0;
cdata.printok = printinfected^1;
cdata.files = 0;
cdata.errors = 0;
cdata.printok = printinfected ^ 1;
cdata.scantype = scantype;
data.data = &cdata;
data.data = &cdata;
ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, serial_callback, &data, ftw_chkpath);
*infected += cdata.infected;
*err += cdata.errors;
if(!cdata.errors && (ftw == CL_SUCCESS || ftw == CL_BREAK)) {
if(cdata.printok)
logg("~%s: OK\n", file);
return 0;
} else if(!cdata.files) {
logg("~%s: No files scanned\n", file);
return 0;
if (!cdata.errors && (ftw == CL_SUCCESS || ftw == CL_BREAK)) {
if (cdata.printok)
logg("~%s: OK\n", file);
return 0;
} else if (!cdata.files) {
logg("~%s: No files scanned\n", file);
return 0;
}
return 1;
}
@ -483,16 +490,17 @@ struct client_parallel_data {
int lastid;
int printok;
struct SCANID {
unsigned int id;
const char *file;
struct SCANID *next;
} *ids;
unsigned int id;
const char *file;
struct SCANID *next;
} * ids;
};
/* Sends a proper scan request to clamd and parses its replies
* This is used only in IDSESSION mode
* Returns 0 on success, 1 on hard failures, 2 on len == 0 (bb#1717) */
static int dspresult(struct client_parallel_data *c) {
static int dspresult(struct client_parallel_data *c)
{
const char *filename;
char *bol, *eol;
unsigned int rid;
@ -502,170 +510,173 @@ static int dspresult(struct client_parallel_data *c) {
recvlninit(&rcv, c->sockd);
do {
len = recvln(&rcv, &bol, &eol);
if(len < 0) return 1;
if(!len) return 2;
if((rid = atoi(bol))) {
id = &c->ids;
while(*id) {
if((*id)->id == rid) break;
id = &((*id)->next);
}
if(!*id) id = NULL;
}
if(!id) {
logg("!Bogus session id from clamd\n");
return 1;
}
filename = (*id)->file;
if(len > 7) {
char *colon = strrchr(bol, ':');
if(!colon) {
logg("!Failed to parse reply\n");
free((void *)filename);
return 1;
} else if(!memcmp(eol - 7, " FOUND", 6)) {
c->infected++;
c->printok = 0;
logg("~%s%s\n", filename, colon);
if(action) action(filename);
} else if(!memcmp(eol-7, " ERROR", 6)) {
c->errors++;
c->printok = 0;
logg("~%s%s\n", filename, colon);
}
}
free((void *)filename);
bol = (char *)*id;
*id = (*id)->next;
free(bol);
} while(rcv.cur != rcv.buf); /* clamd sends whole lines, so, on partial lines, we just assume
len = recvln(&rcv, &bol, &eol);
if (len < 0) return 1;
if (!len) return 2;
if ((rid = atoi(bol))) {
id = &c->ids;
while (*id) {
if ((*id)->id == rid) break;
id = &((*id)->next);
}
if (!*id) id = NULL;
}
if (!id) {
logg("!Bogus session id from clamd\n");
return 1;
}
filename = (*id)->file;
if (len > 7) {
char *colon = strrchr(bol, ':');
if (!colon) {
logg("!Failed to parse reply\n");
free((void *)filename);
return 1;
} else if (!memcmp(eol - 7, " FOUND", 6)) {
c->infected++;
c->printok = 0;
logg("~%s%s\n", filename, colon);
if (action) action(filename);
} else if (!memcmp(eol - 7, " ERROR", 6)) {
c->errors++;
c->printok = 0;
logg("~%s%s\n", filename, colon);
}
}
free((void *)filename);
bol = (char *)*id;
*id = (*id)->next;
free(bol);
} while (rcv.cur != rcv.buf); /* clamd sends whole lines, so, on partial lines, we just assume
more data can be recv()'d with close to zero latency */
return 0;
}
/* FTW callback for scanning in IDSESSION mode
* Returns SUCCESS on success, CL_EXXX or BREAK on error */
static int parallel_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) {
static int parallel_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data)
{
struct client_parallel_data *c = (struct client_parallel_data *)data->data;
struct SCANID *cid;
int res = CL_CLEAN;
UNUSEDPARAM(sb);
if(chkpath(path))
return CL_SUCCESS;
if (chkpath(path))
return CL_SUCCESS;
c->files++;
switch(reason) {
case error_stat:
logg("!Can't access file %s\n", path);
c->errors++;
return CL_SUCCESS;
case error_mem:
logg("!Memory allocation failed in ftw\n");
c->errors++;
return CL_EMEM;
case warning_skipped_dir:
logg("^Directory recursion limit reached\n");
return CL_SUCCESS;
case warning_skipped_special:
logg("^%s: Not supported file type\n", path);
c->errors++;
case warning_skipped_link:
case visit_directory_toplev:
return CL_SUCCESS;
case visit_file:
break;
switch (reason) {
case error_stat:
logg("!Can't access file %s\n", path);
c->errors++;
return CL_SUCCESS;
case error_mem:
logg("!Memory allocation failed in ftw\n");
c->errors++;
return CL_EMEM;
case warning_skipped_dir:
logg("^Directory recursion limit reached\n");
return CL_SUCCESS;
case warning_skipped_special:
logg("^%s: Not supported file type\n", path);
c->errors++;
case warning_skipped_link:
case visit_directory_toplev:
return CL_SUCCESS;
case visit_file:
break;
}
while(1) {
/* consume all the available input to let some of the clamd
while (1) {
/* consume all the available input to let some of the clamd
* threads blocked on send() to be dead.
* by doing so we shouldn't deadlock on the next recv() */
fd_set rfds, wfds;
FD_ZERO(&rfds);
FD_SET(c->sockd, &rfds);
FD_ZERO(&wfds);
FD_SET(c->sockd, &wfds);
if(select(c->sockd + 1, &rfds, &wfds, NULL, NULL) < 0) {
if(errno == EINTR) continue;
free(filename);
logg("!select() failed during session: %s\n", strerror(errno));
return CL_BREAK;
}
if(FD_ISSET(c->sockd, &rfds)) {
if(dspresult(c)) {
free(filename);
return CL_BREAK;
} else continue;
}
if(FD_ISSET(c->sockd, &wfds)) break;
fd_set rfds, wfds;
FD_ZERO(&rfds);
FD_SET(c->sockd, &rfds);
FD_ZERO(&wfds);
FD_SET(c->sockd, &wfds);
if (select(c->sockd + 1, &rfds, &wfds, NULL, NULL) < 0) {
if (errno == EINTR) continue;
free(filename);
logg("!select() failed during session: %s\n", strerror(errno));
return CL_BREAK;
}
if (FD_ISSET(c->sockd, &rfds)) {
if (dspresult(c)) {
free(filename);
return CL_BREAK;
} else
continue;
}
if (FD_ISSET(c->sockd, &wfds)) break;
}
cid = (struct SCANID *)malloc(sizeof(struct SCANID));
if(!cid) {
free(filename);
logg("!Failed to allocate scanid entry: %s\n", strerror(errno));
return CL_BREAK;
if (!cid) {
free(filename);
logg("!Failed to allocate scanid entry: %s\n", strerror(errno));
return CL_BREAK;
}
cid->id = ++c->lastid;
cid->id = ++c->lastid;
cid->file = filename;
cid->next = c->ids;
c->ids = cid;
c->ids = cid;
switch(c->scantype) {
switch (c->scantype) {
#ifdef HAVE_FD_PASSING
case FILDES:
res = send_fdpass(c->sockd, filename);
break;
case FILDES:
res = send_fdpass(c->sockd, filename);
break;
#endif
case STREAM:
res = send_stream(c->sockd, filename);
break;
case STREAM:
res = send_stream(c->sockd, filename);
break;
}
if(res <= 0) {
c->printok = 0;
c->errors++;
c->ids = cid->next;
c->lastid--;
free(cid);
free(filename);
return res ? CL_BREAK : CL_SUCCESS;
if (res <= 0) {
c->printok = 0;
c->errors++;
c->ids = cid->next;
c->lastid--;
free(cid);
free(filename);
return res ? CL_BREAK : CL_SUCCESS;
}
return CL_SUCCESS;
}
/* IDSESSION handler
* Returns non zero for serious errors, zero otherwise */
int parallel_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags) {
int parallel_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags)
{
struct cli_ftw_cbdata data;
struct client_parallel_data cdata;
int ftw;
if((cdata.sockd = dconnect()) < 0)
return 1;
if ((cdata.sockd = dconnect()) < 0)
return 1;
if(sendln(cdata.sockd, "zIDSESSION", 11)) {
closesocket(cdata.sockd);
return 1;
if (sendln(cdata.sockd, "zIDSESSION", 11)) {
closesocket(cdata.sockd);
return 1;
}
cdata.infected = 0;
cdata.files = 0;
cdata.errors = 0;
cdata.files = 0;
cdata.errors = 0;
cdata.scantype = scantype;
cdata.lastid = 0;
cdata.ids = NULL;
cdata.printok = printinfected^1;
data.data = &cdata;
cdata.lastid = 0;
cdata.ids = NULL;
cdata.printok = printinfected ^ 1;
data.data = &cdata;
ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, parallel_callback, &data, ftw_chkpath);
if(ftw != CL_SUCCESS) {
*err += cdata.errors;
*infected += cdata.infected;
closesocket(cdata.sockd);
return 1;
if (ftw != CL_SUCCESS) {
*err += cdata.errors;
*infected += cdata.infected;
closesocket(cdata.sockd);
return 1;
}
sendln(cdata.sockd, "zEND", 5);
@ -675,17 +686,17 @@ int parallel_client_scan(char *file, int scantype, int *infected, int *err, int
*infected += cdata.infected;
*err += cdata.errors;
if(cdata.ids) {
logg("!Clamd closed the connection before scanning all files.\n");
return 1;
if (cdata.ids) {
logg("!Clamd closed the connection before scanning all files.\n");
return 1;
}
if(cdata.errors)
return 1;
if (cdata.errors)
return 1;
if(!cdata.files)
return 0;
if (!cdata.files)
return 0;
if(cdata.printok)
logg("~%s: OK\n", file);
if (cdata.printok)
logg("~%s: OK\n", file);
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -28,7 +28,7 @@
#include <string.h>
#include <signal.h>
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifndef _WIN32
@ -59,17 +59,17 @@ short printinfected = 0, printclean = 1;
int main(int argc, char **argv)
{
int ds, dms, ret;
double mb, rmb;
struct timeval t1, t2;
int ds, dms, ret;
double mb, rmb;
struct timeval t1, t2;
#ifndef _WIN32
sigset_t sigset;
sigset_t sigset;
#endif
struct optstruct *opts;
const struct optstruct *opt;
struct optstruct *opts;
const struct optstruct *opt;
if (check_flevel())
exit(2);
exit(2);
#if !defined(_WIN32) && !defined(C_BEOS)
sigemptyset(&sigset);
@ -79,79 +79,77 @@ int main(int argc, char **argv)
cl_initialize_crypto();
if((opts = optparse(NULL, argc, argv, 1, OPT_CLAMSCAN, 0, NULL)) == NULL) {
mprintf("!Can't parse command line options\n");
return 2;
if ((opts = optparse(NULL, argc, argv, 1, OPT_CLAMSCAN, 0, NULL)) == NULL) {
mprintf("!Can't parse command line options\n");
return 2;
}
if(optget(opts, "verbose")->enabled) {
mprintf_verbose = 1;
logg_verbose = 1;
if (optget(opts, "verbose")->enabled) {
mprintf_verbose = 1;
logg_verbose = 1;
}
if(optget(opts, "quiet")->enabled)
mprintf_quiet = 1;
if (optget(opts, "quiet")->enabled)
mprintf_quiet = 1;
if(optget(opts, "stdout")->enabled)
mprintf_stdout = 1;
if (optget(opts, "stdout")->enabled)
mprintf_stdout = 1;
if(optget(opts, "debug")->enabled) {
if (optget(opts, "debug")->enabled) {
#if defined(C_LINUX)
/* njh@bandsman.co.uk: create a dump if needed */
struct rlimit rlim;
/* 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");
rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_CORE, &rlim) < 0)
perror("setrlimit");
#endif
cl_debug(); /* enable debug messages */
cl_debug(); /* enable debug messages */
}
if (optget(opts, "gen-mdb")->enabled) {
cl_always_gen_section_hash();
}
if(optget(opts, "version")->enabled) {
print_version(optget(opts, "database")->strarg);
optfree(opts);
return 0;
if (optget(opts, "version")->enabled) {
print_version(optget(opts, "database")->strarg);
optfree(opts);
return 0;
}
if(optget(opts, "help")->enabled) {
optfree(opts);
help();
return 0;
if (optget(opts, "help")->enabled) {
optfree(opts);
help();
return 0;
}
if(optget(opts, "recursive")->enabled)
recursion = 1;
if (optget(opts, "recursive")->enabled)
recursion = 1;
if(optget(opts, "infected")->enabled)
printinfected = 1;
if (optget(opts, "infected")->enabled)
printinfected = 1;
if(optget(opts, "suppress-ok-results")->enabled)
printclean = 0;
if (optget(opts, "suppress-ok-results")->enabled)
printclean = 0;
if(optget(opts, "bell")->enabled)
bell = 1;
if (optget(opts, "bell")->enabled)
bell = 1;
/* initialize logger */
if((opt = optget(opts, "log"))->enabled) {
logg_file = opt->strarg;
if(logg("#\n-------------------------------------------------------------------------------\n\n")) {
mprintf("!Problem with internal logger.\n");
optfree(opts);
return 2;
}
if ((opt = optget(opts, "log"))->enabled) {
logg_file = opt->strarg;
if (logg("#\n-------------------------------------------------------------------------------\n\n")) {
mprintf("!Problem with internal logger.\n");
optfree(opts);
return 2;
}
} else
logg_file = NULL;
logg_file = NULL;
if(actsetup(opts)) {
optfree(opts);
logg_close();
exit(2);
if (actsetup(opts)) {
optfree(opts);
logg_close();
exit(2);
}
memset(&info, 0, sizeof(struct s_info));
@ -160,32 +158,32 @@ int main(int argc, char **argv)
ret = scanmanager(opts);
if(!optget(opts, "no-summary")->enabled) {
gettimeofday(&t2, NULL);
if (!optget(opts, "no-summary")->enabled) {
gettimeofday(&t2, NULL);
ds = t2.tv_sec - t1.tv_sec;
dms = t2.tv_usec - t1.tv_usec;
ds -= (dms < 0) ? (1):(0);
dms += (dms < 0) ? (1000000):(0);
logg("\n----------- SCAN SUMMARY -----------\n");
logg("Known viruses: %u\n", info.sigs);
logg("Engine version: %s\n", get_version());
logg("Scanned directories: %u\n", info.dirs);
logg("Scanned files: %u\n", info.files);
logg("Infected files: %u\n", info.ifiles);
if(info.errors)
logg("Total errors: %u\n", info.errors);
if(notremoved) {
logg("Not removed: %u\n", notremoved);
}
if(notmoved) {
logg("Not %s: %u\n", optget(opts, "copy")->enabled ? "moved" : "copied", notmoved);
}
mb = info.blocks * (CL_COUNT_PRECISION / 1024) / 1024.0;
logg("Data scanned: %2.2lf MB\n", mb);
rmb = info.rblocks * (CL_COUNT_PRECISION / 1024) / 1024.0;
logg("Data read: %2.2lf MB (ratio %.2f:1)\n", rmb, info.rblocks ? (double)info.blocks/(double)info.rblocks : 0);
logg("Time: %u.%3.3u sec (%u m %u s)\n", ds, dms/1000, ds/60, ds%60);
ds = t2.tv_sec - t1.tv_sec;
dms = t2.tv_usec - t1.tv_usec;
ds -= (dms < 0) ? (1) : (0);
dms += (dms < 0) ? (1000000) : (0);
logg("\n----------- SCAN SUMMARY -----------\n");
logg("Known viruses: %u\n", info.sigs);
logg("Engine version: %s\n", get_version());
logg("Scanned directories: %u\n", info.dirs);
logg("Scanned files: %u\n", info.files);
logg("Infected files: %u\n", info.ifiles);
if (info.errors)
logg("Total errors: %u\n", info.errors);
if (notremoved) {
logg("Not removed: %u\n", notremoved);
}
if (notmoved) {
logg("Not %s: %u\n", optget(opts, "copy")->enabled ? "moved" : "copied", notmoved);
}
mb = info.blocks * (CL_COUNT_PRECISION / 1024) / 1024.0;
logg("Data scanned: %2.2lf MB\n", mb);
rmb = info.rblocks * (CL_COUNT_PRECISION / 1024) / 1024.0;
logg("Data read: %2.2lf MB (ratio %.2f:1)\n", rmb, info.rblocks ? (double)info.blocks / (double)info.rblocks : 0);
logg("Time: %u.%3.3u sec (%u m %u s)\n", ds, dms / 1000, ds / 60, ds % 60);
}
optfree(opts);

View file

@ -23,13 +23,13 @@
#define __GLOBAL_H
struct s_info {
unsigned int sigs; /* number of signatures */
unsigned int dirs; /* number of scanned directories */
unsigned int files; /* number of scanned files */
unsigned int ifiles; /* number of infected files */
unsigned int errors; /* number of errors */
unsigned long int blocks; /* number of *scanned* 16kb blocks */
unsigned long int rblocks; /* number of *read* 16kb blocks */
unsigned int sigs; /* number of signatures */
unsigned int dirs; /* number of scanned directories */
unsigned int files; /* number of scanned files */
unsigned int ifiles; /* number of infected files */
unsigned int errors; /* number of errors */
unsigned long int blocks; /* number of *scanned* 16kb blocks */
unsigned long int rblocks; /* number of *read* 16kb blocks */
};
extern struct s_info info;

File diff suppressed because it is too large Load diff

View file

@ -18,13 +18,13 @@ void version(void);
typedef struct _header_data {
int len;
char * cfduid;
char * session;
char *cfduid;
char *session;
} header_data;
typedef struct _write_data {
int len;
char * str;
char *str;
} write_data;
void usage(char *name)
@ -56,11 +56,11 @@ void version(void)
size_t header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
{
int len = size*nmemb;
int len = size * nmemb;
char *sp, *ep, *mem;
header_data *hd = (header_data *) userdata;
header_data *hd = (header_data *)userdata;
const char *set_cookie = "Set-Cookie:";
int clen = strlen(set_cookie);
int clen = strlen(set_cookie);
if (len > clen) {
if (strncmp(ptr, set_cookie, clen))
@ -71,13 +71,13 @@ size_t header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
fprintf(stderr, "header_cb(): malformed cookie\n");
return 0;
}
mem = malloc(ep-sp+1);
mem = malloc(ep - sp + 1);
if (mem == NULL) {
fprintf(stderr, "header_cb(): malloc failed\n");
return 0;
}
memcpy(mem, sp, ep-sp);
mem[ep-sp] = '\0';
memcpy(mem, sp, ep - sp);
mem[ep - sp] = '\0';
if (!strncmp(mem, "__cfduid", 8))
hd->cfduid = mem;
else if (!strncmp(mem, "_clamav-net_session", strlen("_clamav-net_session")))
@ -90,19 +90,19 @@ size_t header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
{
int len = size*nmemb;
char * str;
write_data *wd = (write_data *) userdata;
int len = size * nmemb;
char *str;
write_data *wd = (write_data *)userdata;
if (len) {
str = realloc(wd->str, wd->len + len + 1);
if (str == NULL) {
fprintf (stderr, "write_cb() realloc failure\n");
fprintf(stderr, "write_cb() realloc failure\n");
return 0;
}
memcpy(str + wd->len, ptr, len);
str[wd->len + len] = '\0';
wd->str = str;
wd->str = str;
wd->len += len;
}
return len;
@ -115,10 +115,10 @@ size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
* @param key The Key
* @return const char* The Value on Success, NULL on Failure.
*/
const char* presigned_get_string(json_object * ps_json_obj, char * key)
const char *presigned_get_string(json_object *ps_json_obj, char *key)
{
json_object * json_obj = NULL;
const char * json_str = NULL;
json_object *json_obj = NULL;
const char *json_str = NULL;
if (json_object_object_get_ex(ps_json_obj, key, &json_obj)) {
json_str = json_object_get_string(json_obj);
@ -133,27 +133,27 @@ const char* presigned_get_string(json_object * ps_json_obj, char * key)
int main(int argc, char *argv[])
{
int status = 1;
int status = 1;
CURL *clam_curl = NULL, *aws_curl = NULL;
CURLcode res;
int ch;
struct curl_httppost *post=NULL, *last=NULL;
struct curl_httppost *post = NULL, *last = NULL;
struct curl_slist *slist = NULL;
char *name=NULL, *email=NULL, *filename=NULL;
int setURL=0, fromStream=0;
const char * json_str;
write_data wd = {0, NULL};
header_data hd_malware = {0, NULL, NULL};
char *name = NULL, *email = NULL, *filename = NULL;
int setURL = 0, fromStream = 0;
const char *json_str;
write_data wd = {0, NULL};
header_data hd_malware = {0, NULL, NULL};
header_data hd_presigned = {0, NULL, NULL};
json_object * ps_json_obj = NULL;
json_object * json_obj = NULL;
int malware = 0;
int len = 0;
char * submissionID = NULL;
char * fpvname = NULL;
json_object *ps_json_obj = NULL;
json_object *json_obj = NULL;
int malware = 0;
int len = 0;
char *submissionID = NULL;
char *fpvname = NULL;
char *sp, *ep, *str;
char * authenticity_token = NULL;
char * urlp;
char *authenticity_token = NULL;
char *urlp;
curl_global_init(CURL_GLOBAL_ALL);
@ -182,7 +182,7 @@ int main(int argc, char *argv[])
case 'n':
if (setURL)
usage(argv[0]);
malware = 1;
malware = 1;
filename = optarg;
break;
case 'V':
@ -208,10 +208,9 @@ int main(int argc, char *argv[])
fprintf(stderr, "ERROR: Unable to read stream\n");
goto cleanup;
}
fromStream=1;
fromStream = 1;
}
/*** The GET malware|fp ***/
if (malware == 1)
urlp = "https://www.clamav.net/reports/malware";
@ -225,39 +224,38 @@ int main(int argc, char *argv[])
curl_easy_setopt(clam_curl, CURLOPT_HEADERFUNCTION, header_cb);
res = curl_easy_perform(clam_curl);
if (res != CURLE_OK) {
fprintf(stderr, "Error in GET %s: %s\n", urlp , curl_easy_strerror(res));
fprintf(stderr, "Error in GET %s: %s\n", urlp, curl_easy_strerror(res));
goto cleanup;
}
if (wd.str != NULL) {
sp = strstr(wd.str, "name=\"authenticity_token\"");
if (sp == NULL) {
fprintf (stderr, "Authenticity token element not found.\n");
fprintf(stderr, "Authenticity token element not found.\n");
goto cleanup;
}
sp = strstr(sp, "value=");
if (sp == NULL) {
fprintf (stderr, "Authenticity token value not found.\n");
fprintf(stderr, "Authenticity token value not found.\n");
goto cleanup;
}
sp += 7;
ep = strchr(sp, '"');
if (ep == NULL) {
fprintf (stderr, "Authenticity token malformed.\n");
fprintf(stderr, "Authenticity token malformed.\n");
goto cleanup;
}
authenticity_token = malloc(ep-sp+1);
authenticity_token = malloc(ep - sp + 1);
if (authenticity_token == NULL) {
fprintf (stderr, "no memory for authenticity token.\n");
fprintf(stderr, "no memory for authenticity token.\n");
goto cleanup;
}
memcpy(authenticity_token, sp, ep-sp);
authenticity_token[ep-sp] = '\0';
free (wd.str);
memcpy(authenticity_token, sp, ep - sp);
authenticity_token[ep - sp] = '\0';
free(wd.str);
wd.str = NULL;
}
wd.len = 0;
urlp = NULL;
urlp = NULL;
/*** The GET presigned ***/
if (malware == 1)
@ -267,7 +265,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(clam_curl, CURLOPT_HTTPGET, 1);
if (NULL == hd_malware.cfduid || NULL == hd_malware.session) {
fprintf (stderr, "invalid cfduid and/or session id values provided by clamav.net/presigned. Unable to continue submission.");
fprintf(stderr, "invalid cfduid and/or session id values provided by clamav.net/presigned. Unable to continue submission.");
goto cleanup;
}
@ -300,7 +298,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(clam_curl, CURLOPT_HTTPHEADER, slist);
curl_easy_setopt(clam_curl, CURLOPT_HEADERDATA, &hd_presigned);
curl_easy_setopt(clam_curl, CURLOPT_HEADERFUNCTION, header_cb);
if (malware ==1)
if (malware == 1)
curl_easy_setopt(clam_curl, CURLOPT_REFERER, "https://www.clamav.net/reports/malware");
else
curl_easy_setopt(clam_curl, CURLOPT_REFERER, "https://www.clamav.net/reports/fp");
@ -313,7 +311,6 @@ int main(int argc, char *argv[])
curl_slist_free_all(slist);
slist = NULL;
/*** The POST to AWS ***/
ps_json_obj = json_tokener_parse(wd.str);
if (ps_json_obj == NULL) {
@ -336,19 +333,19 @@ int main(int argc, char *argv[])
fprintf(stderr, "Error: malformed 'key' string in GET presigned response (missing '-'.\n");
goto cleanup;
}
submissionID = malloc(ep-sp+1);
submissionID = malloc(ep - sp + 1);
if (submissionID == NULL) {
fprintf(stderr, "Error: malloc submissionID.\n");
goto cleanup;
}
memcpy(submissionID, sp, ep-sp);
submissionID[ep-sp] = '\0';
aws_curl = curl_easy_init();
memcpy(submissionID, sp, ep - sp);
submissionID[ep - sp] = '\0';
aws_curl = curl_easy_init();
if (!(aws_curl)) {
fprintf(stderr, "ERROR: Could not initialize libcurl POST presigned\n");
goto cleanup;
}
submissionID[ep-sp] = '\0';
submissionID[ep - sp] = '\0';
curl_formadd(&post, &last, CURLFORM_COPYNAME, "key", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END);
json_str = presigned_get_string(ps_json_obj, "acl");
@ -424,11 +421,10 @@ int main(int argc, char *argv[])
wd.str = NULL;
wd.len = 0;
/*** The POST submit to clamav.net ***/
slist = curl_slist_append(slist, "Expect:");
len = strlen(hd_malware.cfduid) + strlen(hd_malware.session) + 3;
str = malloc(len);
len = strlen(hd_malware.cfduid) + strlen(hd_malware.session) + 3;
str = malloc(len);
if (str == NULL) {
fprintf(stderr, "No memory for POST submit cookies.\n");
goto cleanup;
@ -443,14 +439,14 @@ int main(int argc, char *argv[])
curl_formadd(&post, &last, CURLFORM_COPYNAME, "utf8", CURLFORM_COPYCONTENTS, "\x27\x13", CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_COPYNAME, "authenticity_token", CURLFORM_COPYCONTENTS, authenticity_token, CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_COPYNAME, "submissionID", CURLFORM_COPYCONTENTS, submissionID, CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_COPYNAME, "type", CURLFORM_COPYCONTENTS, malware?"malware":"fp", CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_COPYNAME, "type", CURLFORM_COPYCONTENTS, malware ? "malware" : "fp", CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_COPYNAME, "sendername", CURLFORM_COPYCONTENTS, name, CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_COPYNAME, "email", CURLFORM_COPYCONTENTS, email, CURLFORM_END);
if (malware == 0) {
curl_formadd(&post, &last, CURLFORM_COPYNAME, "virusname", CURLFORM_COPYCONTENTS, fpvname, CURLFORM_END);
} else {
if (malware == 1)
curl_formadd(&post, &last, CURLFORM_COPYNAME, "shareSample", CURLFORM_COPYCONTENTS, "on", CURLFORM_END);
if (malware == 1)
curl_formadd(&post, &last, CURLFORM_COPYNAME, "shareSample", CURLFORM_COPYCONTENTS, "on", CURLFORM_END);
}
curl_formadd(&post, &last, CURLFORM_COPYNAME, "description", CURLFORM_COPYCONTENTS, "clamsubmit", CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_COPYNAME, "notify", CURLFORM_COPYCONTENTS, "on", CURLFORM_END);
@ -466,7 +462,7 @@ int main(int argc, char *argv[])
} else {
long response_code;
curl_easy_getinfo(clam_curl, CURLINFO_RESPONSE_CODE, &response_code);
if (response_code/100 == 3) {
if (response_code / 100 == 3) {
curl_easy_getinfo(clam_curl, CURLINFO_REDIRECT_URL, &urlp);
if (urlp == NULL) {
fprintf(stderr, "POST submit Location URL is NULL.\n");
@ -475,19 +471,15 @@ int main(int argc, char *argv[])
sp = strstr(urlp, "/reports/");
if (sp == NULL) {
fprintf(stderr, "POST submit Location URL is malformed.\n");
}
else if (!strcmp(sp, "/reports/success")) {
} else if (!strcmp(sp, "/reports/success")) {
fprintf(stdout, "Submission success!\n");
status = 0;
}
else if (!strcmp(sp, "/reports/failure")) {
} else if (!strcmp(sp, "/reports/failure")) {
fprintf(stdout, "Submission failed\n");
}
else {
} else {
fprintf(stdout, "Unknown submission status %s\n", sp);
}
}
else {
} else {
fprintf(stderr, "Unexpected POST submit response code: %li\n", response_code);
}
}
@ -541,7 +533,6 @@ cleanup:
return status;
}
char *read_stream(void)
{
char *filename;
@ -562,7 +553,7 @@ char *read_stream(void)
while (!feof(stdin)) {
nwritten = 0;
nread = fread(buf, 1, sizeof(buf), stdin);
nread = fread(buf, 1, sizeof(buf), stdin);
if (nread == 0) {
fclose(fp);
remove(filename);

View file

@ -39,71 +39,71 @@
int main(int argc, char **argv)
{
int fd, ret;
unsigned long int size = 0;
unsigned int sigs = 0;
long double mb;
const char *virname;
int fd, ret;
unsigned long int size = 0;
unsigned int sigs = 0;
long double mb;
const char *virname;
const char *filename;
struct cl_engine *engine;
struct cl_engine *engine;
struct cl_scan_options options;
if(argc != 2) {
printf("Usage: %s file\n", argv[0]);
return 2;
if (argc != 2) {
printf("Usage: %s file\n", argv[0]);
return 2;
}
filename = argv[1];
if((fd = open(argv[1], O_RDONLY)) == -1) {
printf("Can't open file %s\n", argv[1]);
return 2;
if ((fd = open(argv[1], O_RDONLY)) == -1) {
printf("Can't open file %s\n", argv[1]);
return 2;
}
if((ret = cl_init(CL_INIT_DEFAULT)) != CL_SUCCESS) {
printf("Can't initialize libclamav: %s\n", cl_strerror(ret));
return 2;
if ((ret = cl_init(CL_INIT_DEFAULT)) != CL_SUCCESS) {
printf("Can't initialize libclamav: %s\n", cl_strerror(ret));
return 2;
}
if(!(engine = cl_engine_new())) {
printf("Can't create new engine\n");
return 2;
if (!(engine = cl_engine_new())) {
printf("Can't create new engine\n");
return 2;
}
/* load all available databases from default directory */
if((ret = cl_load(cl_retdbdir(), engine, &sigs, CL_DB_STDOPT)) != CL_SUCCESS) {
printf("cl_load: %s\n", cl_strerror(ret));
close(fd);
if ((ret = cl_load(cl_retdbdir(), engine, &sigs, CL_DB_STDOPT)) != CL_SUCCESS) {
printf("cl_load: %s\n", cl_strerror(ret));
close(fd);
cl_engine_free(engine);
return 2;
return 2;
}
printf("Loaded %u signatures.\n", sigs);
/* build engine */
if((ret = cl_engine_compile(engine)) != CL_SUCCESS) {
printf("Database initialization error: %s\n", cl_strerror(ret));
if ((ret = cl_engine_compile(engine)) != CL_SUCCESS) {
printf("Database initialization error: %s\n", cl_strerror(ret));
cl_engine_free(engine);
close(fd);
return 2;
close(fd);
return 2;
}
/* scan file descriptor */
memset(&options, 0, sizeof(struct cl_scan_options));
options.parse |= ~0; /* enable all parsers */
options.parse |= ~0; /* enable all parsers */
options.general |= CL_SCAN_GENERAL_HEURISTICS; /* enable heuristic alert options */
if((ret = cl_scandesc(fd, filename, &virname, &size, engine, &options)) == CL_VIRUS) {
printf("Virus detected: %s\n", virname);
if ((ret = cl_scandesc(fd, filename, &virname, &size, engine, &options)) == CL_VIRUS) {
printf("Virus detected: %s\n", virname);
} else {
if(ret == CL_CLEAN) {
printf("No virus detected.\n");
} else {
printf("Error: %s\n", cl_strerror(ret));
cl_engine_free(engine);
close(fd);
return 2;
}
if (ret == CL_CLEAN) {
printf("No virus detected.\n");
} else {
printf("Error: %s\n", cl_strerror(ret));
cl_engine_free(engine);
close(fd);
return 2;
}
}
close(fd);

View file

@ -13,7 +13,7 @@ FUNCTIONALITY_LEVEL_MIN(FUNC_LEVEL_098_7)
#define STR_MAXLEN 256
int entrypoint ()
int entrypoint()
{
int i;
int32_t type, obj, objarr, objit, arrlen, strlen;
@ -26,7 +26,7 @@ int entrypoint ()
/* acquire array of internal contained objects */
objarr = json_get_object("ContainedObjects", 16, 0);
type = json_get_type(objarr);
type = json_get_type(objarr);
/* debug print uint (no '\n' or prepended message */
debug_print_uint(type);
@ -49,18 +49,18 @@ int entrypoint ()
type = json_get_type(obj);
if (type == JSON_TYPE_STRING) {
/* acquire string length, note +1 is for the NULL terminator */
strlen = json_get_string_length(obj)+1;
strlen = json_get_string_length(obj) + 1;
/* prevent buffer overflow */
if (strlen > STR_MAXLEN)
strlen = STR_MAXLEN;
/* acquire string data, note strlen includes NULL terminator */
if (json_get_string(str, strlen, obj)) {
/* debug print str (with '\n' and prepended message */
debug_print_str(str,strlen);
debug_print_str(str, strlen);
/* check the contained object's type */
if (strlen == 14 && !memcmp(str, "CL_TYPE_MSEXE", 14)) {
//if (!strcmp(str, strlen, "CL_TYPE_MSEXE", strlen)) {
//if (!strcmp(str, strlen, "CL_TYPE_MSEXE", strlen)) {
/* alert for submission */
foundVirus("EmbedPE");
return 0;

View file

@ -15,7 +15,7 @@ FUNCTIONALITY_LEVEL_MIN(FUNC_LEVEL_098_7)
#define STR_MAXLEN 256
int entrypoint ()
int entrypoint()
{
int32_t objid, type, strlen;
char str[STR_MAXLEN];
@ -37,7 +37,7 @@ int entrypoint ()
}
/* acquire string length, note +1 is for the NULL terminator */
strlen = json_get_string_length(objid)+1;
strlen = json_get_string_length(objid) + 1;
/* prevent buffer overflow */
if (strlen > STR_MAXLEN)
strlen = STR_MAXLEN;
@ -45,7 +45,7 @@ int entrypoint ()
/* acquire string data, note strlen includes NULL terminator */
if (json_get_string(str, strlen, objid)) {
/* debug print str (with '\n' and prepended message */
debug_print_str(str,strlen);
debug_print_str(str, strlen);
/* check the contained object's filetype */
if (strlen == 14 && !memcmp(str, "CL_TYPE_MSEXE", 14)) {

View file

@ -13,7 +13,7 @@ FUNCTIONALITY_LEVEL_MIN(FUNC_LEVEL_098_7)
#define STR_MAXLEN 256
int entrypoint ()
int entrypoint()
{
int32_t type, obj, strlen;
char str[STR_MAXLEN];
@ -31,14 +31,14 @@ int entrypoint ()
type = json_get_type(obj);
if (type == JSON_TYPE_STRING) {
/* acquire string length, note +1 is for the NULL terminator */
strlen = json_get_string_length(obj)+1;
strlen = json_get_string_length(obj) + 1;
/* prevent buffer overflow */
if (strlen > STR_MAXLEN)
strlen = STR_MAXLEN;
/* acquire string data, note strlen includes NULL terminator */
if (json_get_string(str, strlen, obj)) {
/* debug print str (with '\n' and prepended message */
debug_print_str(str,strlen);
debug_print_str(str, strlen);
/* check the contained object's type */
if (!(strlen == 12) || !memcmp(str, "CL_TYPE_PDF", 12)) {

View file

@ -24,7 +24,7 @@ bool logical_trigger(void)
#define STR_MAXLEN 256
int entrypoint ()
int entrypoint()
{
int i;
int32_t type, obj, objarr, objit, arrlen, strlen;
@ -37,7 +37,7 @@ int entrypoint ()
/* acquire array of internal contained objects */
objarr = json_get_object("ContainedObjects", 16, 0);
type = json_get_type(objarr);
type = json_get_type(objarr);
/* debug print uint (no '\n' or prepended message */
debug_print_uint(type);
@ -60,18 +60,18 @@ int entrypoint ()
type = json_get_type(obj);
if (type == JSON_TYPE_STRING) {
/* acquire string length, note +1 is for the NULL terminator */
strlen = json_get_string_length(obj)+1;
strlen = json_get_string_length(obj) + 1;
/* prevent buffer overflow */
if (strlen > STR_MAXLEN)
strlen = STR_MAXLEN;
/* acquire string data, note strlen includes NULL terminator */
if (json_get_string(str, strlen, obj)) {
/* debug print str (with '\n' and prepended message */
debug_print_str(str,strlen);
debug_print_str(str, strlen);
/* check the contained object's type */
if (strlen == 14 && !memcmp(str, "CL_TYPE_MSEXE", 14)) {
//if (!strcmp(str, strlen, "CL_TYPE_MSEXE", strlen)) {
//if (!strcmp(str, strlen, "CL_TYPE_MSEXE", strlen)) {
/* alert for submission */
foundVirus("EmbedPE");
return 0;

View file

@ -26,7 +26,7 @@ bool logical_trigger(void)
#define STR_MAXLEN 256
int entrypoint ()
int entrypoint()
{
int32_t objid, type, strlen;
char str[STR_MAXLEN];
@ -48,7 +48,7 @@ int entrypoint ()
}
/* acquire string length, note +1 is for the NULL terminator */
strlen = json_get_string_length(objid)+1;
strlen = json_get_string_length(objid) + 1;
/* prevent buffer overflow */
if (strlen > STR_MAXLEN)
strlen = STR_MAXLEN;
@ -56,7 +56,7 @@ int entrypoint ()
/* acquire string data, note strlen includes NULL terminator */
if (json_get_string(str, strlen, objid)) {
/* debug print str (with '\n' and prepended message */
debug_print_str(str,strlen);
debug_print_str(str, strlen);
/* check the contained object's filetype */
if (strlen == 14 && !memcmp(str, "CL_TYPE_MSEXE", 14)) {

View file

@ -27,7 +27,7 @@ bool logical_trigger(void)
#define STR_MAXLEN 256
int entrypoint ()
int entrypoint()
{
foundVirus("Submit");
return 0;

View file

@ -27,7 +27,7 @@ bool logical_trigger(void)
#define STR_MAXLEN 256
int entrypoint ()
int entrypoint()
{
int32_t i, root = 0, embedded = 0;
int32_t type, obj, strlen, objarr, objit, arrlen;
@ -46,14 +46,14 @@ int entrypoint ()
type = json_get_type(obj);
if (type == JSON_TYPE_STRING) {
/* acquire string length, note +1 is for the NULL terminator */
strlen = json_get_string_length(obj)+1;
strlen = json_get_string_length(obj) + 1;
/* prevent buffer overflow */
if (strlen > STR_MAXLEN)
strlen = STR_MAXLEN;
/* acquire string data, note strlen includes NULL terminator */
if (json_get_string(str, strlen, obj)) {
/* debug print str (with '\n' and prepended message */
debug_print_str(str,strlen);
debug_print_str(str, strlen);
/* check the contained object's type */
if (strlen == 14 && !memcmp(str, "CL_TYPE_MSEXE", 14)) {
@ -97,14 +97,14 @@ int entrypoint ()
type = json_get_type(obj);
if (type == JSON_TYPE_STRING) {
/* acquire string length, note +1 is for the NULL terminator */
strlen = json_get_string_length(obj)+1;
strlen = json_get_string_length(obj) + 1;
/* prevent buffer overflow */
if (strlen > STR_MAXLEN)
strlen = STR_MAXLEN;
/* acquire string data, note strlen includes NULL terminator */
if (json_get_string(str, strlen, obj)) {
/* debug print str (with '\n' and prepended message */
debug_print_str(str,strlen);
debug_print_str(str, strlen);
/* check the contained object's type */
if (strlen == 14 && !memcmp(str, "CL_TYPE_MSEXE", 14)) {
@ -122,11 +122,9 @@ int entrypoint ()
if (root && embedded) {
foundVirus("RootEmbedded");
}
else if (root) {
} else if (root) {
foundVirus("Root");
}
else if (embedded) {
} else if (embedded) {
foundVirus("Embedded");
}

View file

@ -22,7 +22,7 @@ bool logical_trigger(void)
return matches(Signatures.sig1);
}
int entrypoint ()
int entrypoint()
{
return 0;
}

View file

@ -13,7 +13,7 @@ FUNCTIONALITY_LEVEL_MIN(FUNC_LEVEL_098_7)
#define STR_MAXLEN 256
int entrypoint ()
int entrypoint()
{
int32_t i, root = 0, embedded = 0;
int32_t type, obj, strlen, objarr, objit, arrlen;
@ -32,14 +32,14 @@ int entrypoint ()
type = json_get_type(obj);
if (type == JSON_TYPE_STRING) {
/* acquire string length, note +1 is for the NULL terminator */
strlen = json_get_string_length(obj)+1;
strlen = json_get_string_length(obj) + 1;
/* prevent buffer overflow */
if (strlen > STR_MAXLEN)
strlen = STR_MAXLEN;
/* acquire string data, note strlen includes NULL terminator */
if (json_get_string(str, strlen, obj)) {
/* debug print str (with '\n' and prepended message */
debug_print_str(str,strlen);
debug_print_str(str, strlen);
/* check the contained object's type */
if (strlen == 14 && !memcmp(str, "CL_TYPE_MSEXE", 14)) {
@ -83,14 +83,14 @@ int entrypoint ()
type = json_get_type(obj);
if (type == JSON_TYPE_STRING) {
/* acquire string length, note +1 is for the NULL terminator */
strlen = json_get_string_length(obj)+1;
strlen = json_get_string_length(obj) + 1;
/* prevent buffer overflow */
if (strlen > STR_MAXLEN)
strlen = STR_MAXLEN;
/* acquire string data, note strlen includes NULL terminator */
if (json_get_string(str, strlen, obj)) {
/* debug print str (with '\n' and prepended message */
debug_print_str(str,strlen);
debug_print_str(str, strlen);
/* check the contained object's type */
if (strlen == 14 && !memcmp(str, "CL_TYPE_MSEXE", 14)) {
@ -108,11 +108,9 @@ int entrypoint ()
if (root && embedded) {
foundVirus("RootEmbedded");
}
else if (root) {
} else if (root) {
foundVirus("Root");
}
else if (embedded) {
} else if (embedded) {
foundVirus("Embedded");
}

View file

@ -11,7 +11,7 @@ PRECLASS_HOOK_DECLARE
/* PRECLASS_HOOK_DECLARE will require FUNC_LEVEL_098_7 = 80 */
FUNCTIONALITY_LEVEL_MIN(FUNC_LEVEL_098_7)
int entrypoint ()
int entrypoint()
{
return 0;
}

View file

@ -36,128 +36,111 @@
#include "shared/output.h"
#ifndef PACKETSZ
#define PACKETSZ 512
#endif
char *
dnsquery (const char *domain, int qtype, unsigned int *ttl)
dnsquery(const char *domain, int qtype, unsigned int *ttl)
{
unsigned char answer[PACKETSZ], *answend, *pt;
char *txt, host[128];
int len, type;
unsigned int cttl, size, txtlen = 0;
if (ttl)
*ttl = 0;
if (res_init () < 0)
{
logg ("^res_init failed\n");
if (res_init() < 0) {
logg("^res_init failed\n");
return NULL;
}
logg ("*Querying %s\n", domain);
logg("*Querying %s\n", domain);
memset (answer, 0, PACKETSZ);
if ((len = res_query (domain, C_IN, qtype, answer, PACKETSZ)) < 0
|| len > PACKETSZ)
{
memset(answer, 0, PACKETSZ);
if ((len = res_query(domain, C_IN, qtype, answer, PACKETSZ)) < 0 || len > PACKETSZ) {
#ifdef FRESHCLAM_DNS_FIX
/* The DNS server in the SpeedTouch Alcatel 510 modem can't
* handle a TXT-query, but it can resolve an ANY-query to a
* TXT-record, so we try an ANY-query now. The thing we try
* to resolve normally only has a TXT-record anyway.
*/
memset (answer, 0, PACKETSZ);
memset(answer, 0, PACKETSZ);
if (qtype == T_TXT)
qtype = T_ANY;
if ((len = res_query (domain, C_IN, qtype, answer, PACKETSZ)) < 0)
{
logg ("%cCan't query %s\n",
(qtype == T_TXT || qtype == T_ANY) ? '^' : '*', domain);
if ((len = res_query(domain, C_IN, qtype, answer, PACKETSZ)) < 0) {
logg("%cCan't query %s\n",
(qtype == T_TXT || qtype == T_ANY) ? '^' : '*', domain);
return NULL;
}
#else
logg ("%cCan't query %s\n", (qtype == T_TXT) ? '^' : '*', domain);
logg("%cCan't query %s\n", (qtype == T_TXT) ? '^' : '*', domain);
return NULL;
#endif
}
if (qtype != T_TXT && qtype != T_ANY)
{
if (qtype != T_TXT && qtype != T_ANY) {
if (ttl)
*ttl = 2;
return NULL;
}
answend = answer + len;
pt = answer + sizeof (HEADER);
pt = answer + sizeof(HEADER);
if ((len = dn_expand (answer, answend, pt, host, sizeof (host))) < 0)
{
logg ("^dn_expand failed\n");
if ((len = dn_expand(answer, answend, pt, host, sizeof(host))) < 0) {
logg("^dn_expand failed\n");
return NULL;
}
pt += len;
if (pt > answend - 4)
{
logg ("^Bad (too short) DNS reply\n");
if (pt > answend - 4) {
logg("^Bad (too short) DNS reply\n");
return NULL;
}
GETSHORT (type, pt);
if (type != qtype)
{
logg ("^Broken DNS reply.\n");
GETSHORT(type, pt);
if (type != qtype) {
logg("^Broken DNS reply.\n");
return NULL;
}
pt += INT16SZ; /* class */
pt += INT16SZ; /* class */
size = 0;
do
{ /* recurse through CNAME rr's */
do { /* recurse through CNAME rr's */
pt += size;
if ((len = dn_expand (answer, answend, pt, host, sizeof (host))) < 0)
{
logg ("^second dn_expand failed\n");
if ((len = dn_expand(answer, answend, pt, host, sizeof(host))) < 0) {
logg("^second dn_expand failed\n");
return NULL;
}
pt += len;
if (pt > answend - 10)
{
logg ("^Bad (too short) DNS reply\n");
if (pt > answend - 10) {
logg("^Bad (too short) DNS reply\n");
return NULL;
}
GETSHORT (type, pt);
pt += INT16SZ; /* class */
GETLONG (cttl, pt);
GETSHORT (size, pt);
if (pt + size < answer || pt + size > answend)
{
logg ("^DNS rr overflow\n");
GETSHORT(type, pt);
pt += INT16SZ; /* class */
GETLONG(cttl, pt);
GETSHORT(size, pt);
if (pt + size < answer || pt + size > answend) {
logg("^DNS rr overflow\n");
return NULL;
}
}
while (type == T_CNAME);
} while (type == T_CNAME);
if (type != T_TXT)
{
logg ("^Not a TXT record\n");
if (type != T_TXT) {
logg("^Not a TXT record\n");
return NULL;
}
if (!size || (txtlen = *pt) >= size || !txtlen)
{
logg ("^Broken TXT record (txtlen = %d, size = %d)\n", txtlen, size);
if (!size || (txtlen = *pt) >= size || !txtlen) {
logg("^Broken TXT record (txtlen = %d, size = %d)\n", txtlen, size);
return NULL;
}
if (!(txt = (char *) malloc (txtlen + 1)))
if (!(txt = (char *)malloc(txtlen + 1)))
return NULL;
memcpy (txt, pt + 1, txtlen);
memcpy(txt, pt + 1, txtlen);
txt[txtlen] = 0;
if (ttl)
*ttl = cttl;
@ -168,10 +151,10 @@ dnsquery (const char *domain, int qtype, unsigned int *ttl)
#else
char *
dnsquery (const char *domain, int qtype, unsigned int *ttl)
dnsquery(const char *domain, int qtype, unsigned int *ttl)
{
if (ttl)
*ttl = 1; /* ttl of 1 combined with a NULL return distinguishes a failed lookup from DNS queries not being available */
*ttl = 1; /* ttl of 1 combined with a NULL return distinguishes a failed lookup from DNS queries not being available */
return NULL;
}

View file

@ -32,6 +32,6 @@
#include <resolv.h>
#endif
char *dnsquery (const char *domain, int qtype, unsigned int *ttl);
char *dnsquery(const char *domain, int qtype, unsigned int *ttl);
#endif

View file

@ -23,7 +23,7 @@
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
@ -37,52 +37,43 @@
int active_children;
void
execute (const char *type, const char *text, const struct optstruct *opts)
void execute(const char *type, const char *text, const struct optstruct *opts)
{
int ret;
if (!optget (opts, "daemon")->enabled)
{
if (sscanf (text, "EXIT_%d", &ret) == 1)
{
logg ("*%s: EXIT_%d\n", type, ret);
exit (ret);
if (!optget(opts, "daemon")->enabled) {
if (sscanf(text, "EXIT_%d", &ret) == 1) {
logg("*%s: EXIT_%d\n", type, ret);
exit(ret);
}
if (system (text) == -1)
logg ("%s: system(%s) failed\n", type, text);
if (system(text) == -1)
logg("%s: system(%s) failed\n", type, text);
return;
}
#ifdef _WIN32
if (spawnlp (_P_NOWAIT, text, text, NULL) == -1)
{
logg ("^%s: couldn't execute \"%s\".\n", type, text);
if (spawnlp(_P_NOWAIT, text, text, NULL) == -1) {
logg("^%s: couldn't execute \"%s\".\n", type, text);
return;
}
#else
if (active_children < MAX_CHILDREN)
{
if (active_children < MAX_CHILDREN) {
pid_t pid;
switch (pid = fork ())
{
case 0:
if (-1 == system (text))
{
logg ("^%s: couldn't execute \"%s\".\n", type, text);
}
exit (0);
case -1:
logg ("^%s::fork() failed, %s.\n", type, strerror (errno));
break;
default:
active_children++;
switch (pid = fork()) {
case 0:
if (-1 == system(text)) {
logg("^%s: couldn't execute \"%s\".\n", type, text);
}
exit(0);
case -1:
logg("^%s::fork() failed, %s.\n", type, strerror(errno));
break;
default:
active_children++;
}
}
else
{
logg ("^%s: already %d processes active.\n", type, active_children);
} else {
logg("^%s: already %d processes active.\n", type, active_children);
}
#endif
}

View file

@ -17,13 +17,12 @@
* MA 02110-1301, USA.
*/
#ifndef __EXECUTE_H
#define __EXECUTE_H
#include "shared/optparser.h"
void execute (const char *type, const char *text,
const struct optstruct *opts);
void execute(const char *type, const char *text,
const struct optstruct *opts);
#endif

View file

@ -22,7 +22,7 @@
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
@ -30,12 +30,12 @@
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#ifndef _WIN32
#ifndef _WIN32
#include <sys/wait.h>
#endif
#include <sys/stat.h>
#include <fcntl.h>
#ifdef HAVE_PWD_H
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_GRP_H
@ -66,7 +66,7 @@ extern int active_children;
static short foreground = -1;
char updtmpdir[512], dbdir[512];
int sigchld_wait = 1;
int sigchld_wait = 1;
const char *pidfile = NULL;
char hostid[37];
@ -74,74 +74,70 @@ char *get_hostid(void *cbdata);
int is_valid_hostid(void);
static void
sighandler (int sig)
sighandler(int sig)
{
switch (sig)
{
#ifdef SIGCHLD
case SIGCHLD:
if (sigchld_wait)
waitpid (-1, NULL, WNOHANG);
active_children--;
break;
switch (sig) {
#ifdef SIGCHLD
case SIGCHLD:
if (sigchld_wait)
waitpid(-1, NULL, WNOHANG);
active_children--;
break;
#endif
#ifdef SIGPIPE
case SIGPIPE:
/* no action, app will get EPIPE */
break;
case SIGPIPE:
/* no action, app will get EPIPE */
break;
#endif
#ifdef SIGALRM
case SIGALRM:
terminate = -1;
break;
#ifdef SIGALRM
case SIGALRM:
terminate = -1;
break;
#endif
#ifdef SIGUSR1
case SIGUSR1:
terminate = -1;
break;
#ifdef SIGUSR1
case SIGUSR1:
terminate = -1;
break;
#endif
#ifdef SIGHUP
case SIGHUP:
terminate = -2;
break;
#ifdef SIGHUP
case SIGHUP:
terminate = -2;
break;
#endif
default:
if (*updtmpdir)
cli_rmdirs (updtmpdir);
if (pidfile)
unlink (pidfile);
logg ("Update process terminated\n");
exit (0);
default:
if (*updtmpdir)
cli_rmdirs(updtmpdir);
if (pidfile)
unlink(pidfile);
logg("Update process terminated\n");
exit(0);
}
return;
}
static void
writepid (const char *pidfile)
writepid(const char *pidfile)
{
FILE *fd;
int old_umask;
old_umask = umask (0006);
if ((fd = fopen (pidfile, "w")) == NULL)
{
logg ("!Can't save PID to file %s: %s\n", pidfile, strerror (errno));
old_umask = umask(0006);
if ((fd = fopen(pidfile, "w")) == NULL) {
logg("!Can't save PID to file %s: %s\n", pidfile, strerror(errno));
} else {
fprintf(fd, "%d\n", (int)getpid());
fclose(fd);
}
else
{
fprintf (fd, "%d\n", (int) getpid ());
fclose (fd);
}
umask (old_umask);
umask(old_umask);
}
static void
help (void)
help(void)
{
mprintf_stdout = 1;
@ -180,11 +176,11 @@ help (void)
mprintf(" --on-outdated-execute=COMMAND Execute COMMAND when software is outdated\n");
mprintf(" --list-mirrors Print mirrors from mirrors.dat\n");
mprintf(" --update-db=DBNAME Only update database DBNAME\n");
mprintf ("\n");
mprintf("\n");
}
static int
download (const struct optstruct *opts, const char *cfgfile)
download(const struct optstruct *opts, const char *cfgfile)
{
time_t currtime;
int ret = 0, attempt = 1, maxattempts = 0;
@ -194,47 +190,35 @@ download (const struct optstruct *opts, const char *cfgfile)
logg("ClamAV update process started at %s", ctime(&currtime));
logg("*Using IPv6 aware code\n");
maxattempts = optget (opts, "MaxAttempts")->numarg;
logg ("*Max retries == %d\n", maxattempts);
maxattempts = optget(opts, "MaxAttempts")->numarg;
logg("*Max retries == %d\n", maxattempts);
if (!(opt = optget (opts, "DatabaseMirror"))->enabled)
{
logg ("^You must specify at least one database mirror in %s\n",
cfgfile);
if (!(opt = optget(opts, "DatabaseMirror"))->enabled) {
logg("^You must specify at least one database mirror in %s\n",
cfgfile);
return FCE_CONFIG;
}
else
{
while (opt)
{
ret = downloadmanager (opts, opt->strarg, attempt);
} else {
while (opt) {
ret = downloadmanager(opts, opt->strarg, attempt);
#ifndef _WIN32
alarm (0);
alarm(0);
#endif
if (ret == FCE_CONNECTION || ret == FCE_BADCVD
|| ret == FCE_FAILEDGET || ret == FCE_MIRRORNOTSYNC)
{
if (attempt < maxattempts)
{
logg ("Trying again in 5 secs...\n");
if (ret == FCE_CONNECTION || ret == FCE_BADCVD || ret == FCE_FAILEDGET || ret == FCE_MIRRORNOTSYNC) {
if (attempt < maxattempts) {
logg("Trying again in 5 secs...\n");
attempt++;
sleep (5);
sleep(5);
continue;
}
else
{
logg ("Giving up on %s...\n", opt->strarg);
opt = (struct optstruct *) opt->nextarg;
if (!opt)
{
logg ("Update failed. Your network may be down or none of the mirrors listed in %s is working. Check https://www.clamav.net/documents/official-mirror-faq for possible reasons.\n", cfgfile);
} else {
logg("Giving up on %s...\n", opt->strarg);
opt = (struct optstruct *)opt->nextarg;
if (!opt) {
logg("Update failed. Your network may be down or none of the mirrors listed in %s is working. Check https://www.clamav.net/documents/official-mirror-faq for possible reasons.\n", cfgfile);
}
attempt = 1;
}
}
else
{
} else {
return ret;
}
}
@ -244,35 +228,33 @@ download (const struct optstruct *opts, const char *cfgfile)
}
static void
msg_callback (enum cl_msg severity, const char *fullmsg, const char *msg,
void *ctx)
msg_callback(enum cl_msg severity, const char *fullmsg, const char *msg,
void *ctx)
{
UNUSEDPARAM(fullmsg);
UNUSEDPARAM(ctx);
switch (severity)
{
case CL_MSG_ERROR:
logg ("^[LibClamAV] %s", msg);
break;
case CL_MSG_WARN:
logg ("~[LibClamAV] %s", msg);
break;
default:
logg ("*[LibClamAV] %s", msg);
break;
switch (severity) {
case CL_MSG_ERROR:
logg("^[LibClamAV] %s", msg);
break;
case CL_MSG_WARN:
logg("~[LibClamAV] %s", msg);
break;
default:
logg("*[LibClamAV] %s", msg);
break;
}
}
int
main (int argc, char **argv)
int main(int argc, char **argv)
{
int ret = FCE_CONNECTION, retcl;
const char *cfgfile, *arg = NULL;
char *pt;
struct optstruct *opts;
const struct optstruct *opt;
#ifndef _WIN32
#ifndef _WIN32
struct sigaction sigact;
struct sigaction oldact;
#endif
@ -282,85 +264,73 @@ main (int argc, char **argv)
#endif
STATBUF statbuf;
struct mirdat mdat;
int j;
int j;
if (check_flevel ())
exit (FCE_INIT);
if (check_flevel())
exit(FCE_INIT);
if ((retcl = cl_init (CL_INIT_DEFAULT)))
{
mprintf ("!Can't initialize libclamav: %s\n", cl_strerror (retcl));
if ((retcl = cl_init(CL_INIT_DEFAULT))) {
mprintf("!Can't initialize libclamav: %s\n", cl_strerror(retcl));
return FCE_INIT;
}
if ((opts =
optparse (NULL, argc, argv, 1, OPT_FRESHCLAM, 0, NULL)) == NULL)
{
mprintf ("!Can't parse command line options\n");
optparse(NULL, argc, argv, 1, OPT_FRESHCLAM, 0, NULL)) == NULL) {
mprintf("!Can't parse command line options\n");
return FCE_INIT;
}
if (optget (opts, "help")->enabled)
{
help ();
optfree (opts);
if (optget(opts, "help")->enabled) {
help();
optfree(opts);
return FC_SUCCESS;
}
/* check foreground option from command line to override config file */
for(j = 0; j < argc; j += 1)
{
if ((memcmp(argv[j], "--foreground", 12) == 0) || (memcmp(argv[j], "-F", 2) == 0))
{
for (j = 0; j < argc; j += 1) {
if ((memcmp(argv[j], "--foreground", 12) == 0) || (memcmp(argv[j], "-F", 2) == 0)) {
/* found */
break;
}
}
if (j < argc) {
if(optget(opts, "Foreground")->enabled) {
foreground = 1;
}
else {
foreground = 0;
}
}
if (j < argc) {
if (optget(opts, "Foreground")->enabled) {
foreground = 1;
} else {
foreground = 0;
}
}
/* parse the config file */
cfgfile = optget (opts, "config-file")->strarg;
pt = strdup (cfgfile);
cfgfile = optget(opts, "config-file")->strarg;
pt = strdup(cfgfile);
if ((opts =
optparse (cfgfile, 0, NULL, 1, OPT_FRESHCLAM, 0, opts)) == NULL)
{
fprintf (stderr, "ERROR: Can't open/parse the config file %s\n", pt);
free (pt);
optparse(cfgfile, 0, NULL, 1, OPT_FRESHCLAM, 0, opts)) == NULL) {
fprintf(stderr, "ERROR: Can't open/parse the config file %s\n", pt);
free(pt);
return FCE_INIT;
}
free (pt);
free(pt);
if (optget (opts, "version")->enabled)
{
print_version (optget (opts, "DatabaseDirectory")->strarg);
optfree (opts);
if (optget(opts, "version")->enabled) {
print_version(optget(opts, "DatabaseDirectory")->strarg);
optfree(opts);
return FC_SUCCESS;
}
if (optget (opts, "HTTPProxyPassword")->enabled)
{
if (CLAMSTAT (cfgfile, &statbuf) == -1)
{
logg ("^Can't stat %s (critical error)\n", cfgfile);
optfree (opts);
if (optget(opts, "HTTPProxyPassword")->enabled) {
if (CLAMSTAT(cfgfile, &statbuf) == -1) {
logg("^Can't stat %s (critical error)\n", cfgfile);
optfree(opts);
return FCE_CONFIG;
}
#ifndef _WIN32
if (statbuf.
st_mode & (S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH |
S_IXOTH))
{
logg ("^Insecure permissions (for HTTPProxyPassword): %s must have no more than 0700 permissions.\n", cfgfile);
optfree (opts);
if (statbuf.st_mode & (S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH |
S_IXOTH)) {
logg("^Insecure permissions (for HTTPProxyPassword): %s must have no more than 0700 permissions.\n", cfgfile);
optfree(opts);
return FCE_CONFIG;
}
#endif
@ -368,42 +338,38 @@ main (int argc, char **argv)
#ifdef HAVE_PWD_H
/* freshclam shouldn't work with root privileges */
dbowner = optget (opts, "DatabaseOwner")->strarg;
dbowner = optget(opts, "DatabaseOwner")->strarg;
if (!geteuid ())
{
if ((user = getpwnam (dbowner)) == NULL)
{
logg ("^Can't get information about user %s.\n", dbowner);
optfree (opts);
if (!geteuid()) {
if ((user = getpwnam(dbowner)) == NULL) {
logg("^Can't get information about user %s.\n", dbowner);
optfree(opts);
return FCE_USERINFO;
}
#ifdef HAVE_INITGROUPS
if (initgroups(dbowner, user->pw_gid)) {
logg ("^initgroups() failed.\n");
optfree (opts);
return FCE_USERORGROUP;
}
if (initgroups(dbowner, user->pw_gid)) {
logg("^initgroups() failed.\n");
optfree(opts);
return FCE_USERORGROUP;
}
#elif HAVE_SETGROUPS
if (setgroups(1, &user->pw_gid)) {
logg ("^setgroups() failed.\n");
optfree (opts);
return FCE_USERORGROUP;
}
if (setgroups(1, &user->pw_gid)) {
logg("^setgroups() failed.\n");
optfree(opts);
return FCE_USERORGROUP;
}
#endif
if (setgid (user->pw_gid))
{
logg ("^setgid(%d) failed.\n", (int) user->pw_gid);
optfree (opts);
if (setgid(user->pw_gid)) {
logg("^setgid(%d) failed.\n", (int)user->pw_gid);
optfree(opts);
return FCE_USERORGROUP;
}
if (setuid (user->pw_uid))
{
logg ("^setuid(%d) failed.\n", (int) user->pw_uid);
optfree (opts);
if (setuid(user->pw_uid)) {
logg("^setuid(%d) failed.\n", (int)user->pw_uid);
optfree(opts);
return FCE_USERORGROUP;
}
}
@ -411,202 +377,175 @@ main (int argc, char **argv)
/* initialize some important variables */
if (optget (opts, "Debug")->enabled || optget (opts, "debug")->enabled)
cl_debug ();
if (optget(opts, "Debug")->enabled || optget(opts, "debug")->enabled)
cl_debug();
if (optget (opts, "verbose")->enabled)
if (optget(opts, "verbose")->enabled)
mprintf_verbose = 1;
if (optget (opts, "quiet")->enabled)
if (optget(opts, "quiet")->enabled)
mprintf_quiet = 1;
if (optget (opts, "no-warnings")->enabled)
{
if (optget(opts, "no-warnings")->enabled) {
mprintf_nowarn = 1;
logg_nowarn = 1;
logg_nowarn = 1;
}
if (optget (opts, "stdout")->enabled)
if (optget(opts, "stdout")->enabled)
mprintf_stdout = 1;
if (optget (opts, "show-progress")->enabled)
if (optget(opts, "show-progress")->enabled)
mprintf_progress = 1;
/* initialize logger */
logg_verbose = mprintf_verbose ? 1 : optget (opts, "LogVerbose")->enabled;
logg_time = optget (opts, "LogTime")->enabled;
logg_size = optget (opts, "LogFileMaxSize")->numarg;
logg_verbose = mprintf_verbose ? 1 : optget(opts, "LogVerbose")->enabled;
logg_time = optget(opts, "LogTime")->enabled;
logg_size = optget(opts, "LogFileMaxSize")->numarg;
if (logg_size)
logg_rotate = optget(opts, "LogRotate")->enabled;
if ((opt = optget (opts, "UpdateLogFile"))->enabled)
{
if ((opt = optget(opts, "UpdateLogFile"))->enabled) {
logg_file = opt->strarg;
if (logg ("#--------------------------------------\n"))
{
mprintf ("!Problem with internal logger (UpdateLogFile = %s).\n",
logg_file);
optfree (opts);
if (logg("#--------------------------------------\n")) {
mprintf("!Problem with internal logger (UpdateLogFile = %s).\n",
logg_file);
optfree(opts);
return FCE_LOGGING;
}
}
else
} else
logg_file = NULL;
#if defined(USE_SYSLOG) && !defined(C_AIX)
if (optget (opts, "LogSyslog")->enabled)
{
if (optget(opts, "LogSyslog")->enabled) {
int fac = LOG_LOCAL6;
if ((opt = optget (opts, "LogFacility"))->enabled)
{
if ((fac = logg_facility (opt->strarg)) == -1)
{
mprintf ("!LogFacility: %s: No such facility.\n",
opt->strarg);
optfree (opts);
if ((opt = optget(opts, "LogFacility"))->enabled) {
if ((fac = logg_facility(opt->strarg)) == -1) {
mprintf("!LogFacility: %s: No such facility.\n",
opt->strarg);
optfree(opts);
return FCE_LOGGING;
}
}
openlog ("freshclam", LOG_PID, fac);
openlog("freshclam", LOG_PID, fac);
logg_syslog = 1;
}
#endif
cl_set_clcb_msg (msg_callback);
cl_set_clcb_msg(msg_callback);
/* change the current working directory */
if (chdir (optget (opts, "DatabaseDirectory")->strarg))
{
logg ("!Can't change dir to %s\n",
optget (opts, "DatabaseDirectory")->strarg);
optfree (opts);
if (chdir(optget(opts, "DatabaseDirectory")->strarg)) {
logg("!Can't change dir to %s\n",
optget(opts, "DatabaseDirectory")->strarg);
optfree(opts);
return FCE_DIRECTORY;
}
else
{
if (!getcwd (dbdir, sizeof (dbdir)))
{
logg ("!getcwd() failed\n");
optfree (opts);
} else {
if (!getcwd(dbdir, sizeof(dbdir))) {
logg("!getcwd() failed\n");
optfree(opts);
return FCE_DIRECTORY;
}
logg ("*Current working dir is %s\n", dbdir);
logg("*Current working dir is %s\n", dbdir);
}
if (optget (opts, "list-mirrors")->enabled)
{
if (mirman_read("mirrors.dat", &mdat, 1) != FC_SUCCESS)
{
printf ("Can't read mirrors.dat\n");
optfree (opts);
if (optget(opts, "list-mirrors")->enabled) {
if (mirman_read("mirrors.dat", &mdat, 1) != FC_SUCCESS) {
printf("Can't read mirrors.dat\n");
optfree(opts);
return FCE_FILE;
}
mirman_list (&mdat);
mirman_free (&mdat);
optfree (opts);
mirman_list(&mdat);
mirman_free(&mdat);
optfree(opts);
return FC_SUCCESS;
}
if ((opt = optget (opts, "PrivateMirror"))->enabled)
{
if ((opt = optget(opts, "PrivateMirror"))->enabled) {
struct optstruct *dbm, *opth;
dbm = (struct optstruct *) optget (opts, "DatabaseMirror");
dbm = (struct optstruct *)optget(opts, "DatabaseMirror");
dbm->active = dbm->enabled = 1;
do
{
if (cli_strbcasestr (opt->strarg, ".clamav.net"))
{
logg ("!PrivateMirror: *.clamav.net is not allowed in this mode\n");
optfree (opts);
do {
if (cli_strbcasestr(opt->strarg, ".clamav.net")) {
logg("!PrivateMirror: *.clamav.net is not allowed in this mode\n");
optfree(opts);
return FCE_PRIVATEMIRROR;
}
if (dbm->strarg)
free (dbm->strarg);
dbm->strarg = strdup (opt->strarg);
if (!dbm->strarg)
{
logg ("!strdup() failed\n");
optfree (opts);
free(dbm->strarg);
dbm->strarg = strdup(opt->strarg);
if (!dbm->strarg) {
logg("!strdup() failed\n");
optfree(opts);
return FCE_MEM;
}
if (!dbm->nextarg)
{
if (!dbm->nextarg) {
dbm->nextarg =
(struct optstruct *) calloc (1,
sizeof (struct optstruct));
if (!dbm->nextarg)
{
logg ("!calloc() failed\n");
optfree (opts);
(struct optstruct *)calloc(1,
sizeof(struct optstruct));
if (!dbm->nextarg) {
logg("!calloc() failed\n");
optfree(opts);
return FCE_MEM;
}
}
opth = dbm;
dbm = dbm->nextarg;
}
while ((opt = opt->nextarg));
dbm = dbm->nextarg;
} while ((opt = opt->nextarg));
opth->nextarg = NULL;
while (dbm)
{
free (dbm->name);
free (dbm->cmd);
free (dbm->strarg);
while (dbm) {
free(dbm->name);
free(dbm->cmd);
free(dbm->strarg);
opth = dbm;
dbm = dbm->nextarg;
free (opth);
dbm = dbm->nextarg;
free(opth);
}
/* disable DNS db checks */
opth = (struct optstruct *) optget (opts, "no-dns");
opth = (struct optstruct *)optget(opts, "no-dns");
opth->active = opth->enabled = 1;
/* disable scripted updates */
opth = (struct optstruct *) optget (opts, "ScriptedUpdates");
opth = (struct optstruct *)optget(opts, "ScriptedUpdates");
opth->active = opth->enabled = 0;
}
*updtmpdir = 0;
#ifdef _WIN32
signal (SIGINT, sighandler);
signal(SIGINT, sighandler);
#else
memset (&sigact, 0, sizeof (struct sigaction));
memset(&sigact, 0, sizeof(struct sigaction));
sigact.sa_handler = sighandler;
sigaction (SIGINT, &sigact, NULL);
sigaction (SIGPIPE, &sigact, NULL);
sigaction(SIGINT, &sigact, NULL);
sigaction(SIGPIPE, &sigact, NULL);
#endif
if (optget (opts, "daemon")->enabled)
{
if (optget(opts, "daemon")->enabled) {
int bigsleep, checks;
#ifndef _WIN32
#ifndef _WIN32
time_t now, wakeup;
sigaction (SIGTERM, &sigact, NULL);
sigaction (SIGHUP, &sigact, NULL);
sigaction (SIGCHLD, &sigact, NULL);
sigaction(SIGTERM, &sigact, NULL);
sigaction(SIGHUP, &sigact, NULL);
sigaction(SIGCHLD, &sigact, NULL);
#endif
checks = optget (opts, "Checks")->numarg;
checks = optget(opts, "Checks")->numarg;
if (checks <= 0)
{
logg ("^Number of checks must be a positive integer.\n");
optfree (opts);
if (checks <= 0) {
logg("^Number of checks must be a positive integer.\n");
optfree(opts);
return FCE_CHECKS;
}
if (!optget (opts, "DNSDatabaseInfo")->enabled
|| optget (opts, "no-dns")->enabled)
{
if (checks > 50)
{
logg ("^Number of checks must be between 1 and 50.\n");
optfree (opts);
if (!optget(opts, "DNSDatabaseInfo")->enabled || optget(opts, "no-dns")->enabled) {
if (checks > 50) {
logg("^Number of checks must be between 1 and 50.\n");
optfree(opts);
return FCE_CHECKS;
}
}
@ -615,116 +554,97 @@ main (int argc, char **argv)
#ifndef _WIN32
/* fork into background */
if (foreground == -1)
{
if (optget(opts, "Foreground")->enabled)
{
if (foreground == -1) {
if (optget(opts, "Foreground")->enabled) {
foreground = 1;
}
else
{
} else {
foreground = 0;
}
}
if(foreground == 0)
{
if (daemonize () == -1)
{
logg ("!daemonize() failed\n");
optfree (opts);
if (foreground == 0) {
if (daemonize() == -1) {
logg("!daemonize() failed\n");
optfree(opts);
return FCE_FAILEDUPDATE;
}
mprintf_disabled = 1;
}
#endif
if ((opt = optget (opts, "PidFile"))->enabled)
{
if ((opt = optget(opts, "PidFile"))->enabled) {
pidfile = opt->strarg;
writepid (pidfile);
writepid(pidfile);
}
active_children = 0;
logg ("#freshclam daemon %s (OS: " TARGET_OS_TYPE ", ARCH: "
TARGET_ARCH_TYPE ", CPU: " TARGET_CPU_TYPE ")\n",
get_version ());
logg("#freshclam daemon %s (OS: " TARGET_OS_TYPE ", ARCH: " TARGET_ARCH_TYPE ", CPU: " TARGET_CPU_TYPE ")\n",
get_version());
while (!terminate)
{
ret = download (opts, cfgfile);
while (!terminate) {
ret = download(opts, cfgfile);
if (ret > 1)
{
if ((opt = optget (opts, "OnErrorExecute"))->enabled)
if (ret > 1) {
if ((opt = optget(opts, "OnErrorExecute"))->enabled)
arg = opt->strarg;
if (arg)
execute ("OnErrorExecute", arg, opts);
execute("OnErrorExecute", arg, opts);
arg = NULL;
}
logg ("#--------------------------------------\n");
#ifdef SIGALRM
sigaction (SIGALRM, &sigact, &oldact);
logg("#--------------------------------------\n");
#ifdef SIGALRM
sigaction(SIGALRM, &sigact, &oldact);
#endif
#ifdef SIGUSR1
sigaction (SIGUSR1, &sigact, &oldact);
#ifdef SIGUSR1
sigaction(SIGUSR1, &sigact, &oldact);
#endif
#ifdef _WIN32
sleep (bigsleep);
#ifdef _WIN32
sleep(bigsleep);
#else
time (&wakeup);
time(&wakeup);
wakeup += bigsleep;
alarm (bigsleep);
do
{
pause ();
time (&now);
}
while (!terminate && now < wakeup);
alarm(bigsleep);
do {
pause();
time(&now);
} while (!terminate && now < wakeup);
if (terminate == -1)
{
logg ("Received signal: wake up\n");
if (terminate == -1) {
logg("Received signal: wake up\n");
terminate = 0;
}
else if (terminate == -2)
{
logg ("Received signal: re-opening log file\n");
} else if (terminate == -2) {
logg("Received signal: re-opening log file\n");
terminate = 0;
logg_close ();
logg_close();
}
#endif
#ifdef SIGALRM
sigaction (SIGALRM, &oldact, NULL);
#ifdef SIGALRM
sigaction(SIGALRM, &oldact, NULL);
#endif
#ifdef SIGUSR1
sigaction (SIGUSR1, &oldact, NULL);
#ifdef SIGUSR1
sigaction(SIGUSR1, &oldact, NULL);
#endif
}
}
else
{
ret = download (opts, cfgfile);
} else {
ret = download(opts, cfgfile);
}
if (ret > 1)
{
if ((opt = optget (opts, "OnErrorExecute"))->enabled)
execute ("OnErrorExecute", opt->strarg, opts);
if (ret > 1) {
if ((opt = optget(opts, "OnErrorExecute"))->enabled)
execute("OnErrorExecute", opt->strarg, opts);
}
if (pidfile)
{
unlink (pidfile);
if (pidfile) {
unlink(pidfile);
}
optfree (opts);
optfree(opts);
cl_cleanup_crypto();
@ -738,8 +658,8 @@ int is_valid_hostid(void)
if (strlen(hostid) != 36)
return 0;
count=0;
for (i=0; i < 36; i++)
count = 0;
for (i = 0; i < 36; i++)
if (hostid[i] == '-')
count++;

View file

@ -21,33 +21,33 @@
#define __FRESHCLAMCODES_H
typedef enum fc_error_tag {
FC_SUCCESS = 0,
FC_UPTODATE = 1,
FC_SUCCESS = 0,
FC_UPTODATE = 1,
FCE_INIT = 40,
FCE_CHECKS = 41,
FCE_PRIVATEMIRROR = 45,
FCE_INIT = 40,
FCE_CHECKS = 41,
FCE_PRIVATEMIRROR = 45,
FCE_DIRECTORY = 50,
FCE_CONNECTION = 52,
FCE_EMPTYFILE = 53,
FCE_BADCVD = 54,
FCE_FILE = 55,
/* TESTFAIL is also 55, consider moving to new value */
FCE_TESTFAIL = 55,
FCE_CONFIG = 56,
FCE_DBDIRACCESS = 57,
FCE_FAILEDGET = 58,
FCE_MIRRORNOTSYNC = 59,
FCE_DIRECTORY = 50,
FCE_CONNECTION = 52,
FCE_EMPTYFILE = 53,
FCE_BADCVD = 54,
FCE_FILE = 55,
/* TESTFAIL is also 55, consider moving to new value */
FCE_TESTFAIL = 55,
FCE_CONFIG = 56,
FCE_DBDIRACCESS = 57,
FCE_FAILEDGET = 58,
FCE_MIRRORNOTSYNC = 59,
FCE_USERINFO = 60,
FCE_USERORGROUP = 61,
FCE_LOGGING = 62,
FCE_USERINFO = 60,
FCE_USERORGROUP = 61,
FCE_LOGGING = 62,
FCE_FAILEDUPDATE = 70,
FCE_MEM = 75,
FCE_ARG = 76,
FCE_OPEN = 77
FCE_FAILEDUPDATE = 70,
FCE_MEM = 75,
FCE_ARG = 76,
FCE_OPEN = 77
} fc_error_t;
#endif

File diff suppressed because it is too large Load diff

View file

@ -20,12 +20,12 @@
#ifndef __MANAGER_H
#define __MANAGER_H
#define SUBMIT_MIN_ENTRIES 10
#define SUBMIT_MAX_ENTRIES 50
#define SUBMIT_MIN_ENTRIES 10
#define SUBMIT_MAX_ENTRIES 50
#include "shared/optparser.h"
int downloadmanager (const struct optstruct *opts, const char *hostname,
unsigned int attempt);
int downloadmanager(const struct optstruct *opts, const char *hostname,
unsigned int attempt);
#endif

View file

@ -46,19 +46,17 @@
#ifndef HAVE_GETADDRINFO
#ifndef AF_INET6
#define AF_INET6 0xbeef /* foo */
#define AF_INET6 0xbeef /* foo */
#endif
#endif
#define IGNORE_SHORT (3600) /* 1 hour */
#define IGNORE_LONG (6 * IGNORE_SHORT) /* 6 hours */
#define IGNORE_SHORT (3600) /* 1 hour */
#define IGNORE_LONG (6 * IGNORE_SHORT) /* 6 hours */
void
mirman_free(struct mirdat *mdat)
void mirman_free(struct mirdat *mdat)
{
if (mdat && mdat->num)
{
free (mdat->mirtab);
if (mdat && mdat->num) {
free(mdat->mirtab);
mdat->num = 0;
}
}
@ -68,49 +66,46 @@ fc_error_t mirman_read(const char *file, struct mirdat *mdat, uint8_t active)
struct mirdat_ip mip;
int fd, bread;
memset (mdat, 0, sizeof(struct mirdat));
memset(mdat, 0, sizeof(struct mirdat));
if (!(mdat->active = active))
return FC_SUCCESS;
if ((fd = open (file, O_RDONLY | O_BINARY)) == -1)
if ((fd = open(file, O_RDONLY | O_BINARY)) == -1)
return FCE_OPEN;
while ((bread = read (fd, &mip, sizeof(mip))) == sizeof(mip))
{
while ((bread = read(fd, &mip, sizeof(mip))) == sizeof(mip)) {
mdat->mirtab =
(struct mirdat_ip *) realloc (mdat->mirtab,
(mdat->num + 1) * sizeof(mip));
if (!mdat->mirtab)
{
(struct mirdat_ip *)realloc(mdat->mirtab,
(mdat->num + 1) * sizeof(mip));
if (!mdat->mirtab) {
logg("!Can't allocate memory for mdat->mirtab\n");
mirman_free (mdat);
close (fd);
mirman_free(mdat);
close(fd);
return FCE_MEM;
}
memcpy (&mdat->mirtab[mdat->num], &mip, sizeof(mip));
memcpy(&mdat->mirtab[mdat->num], &mip, sizeof(mip));
mdat->num++;
}
close (fd);
close(fd);
if (bread)
{
if (bread) {
logg("^Removing broken %s file.\n", file);
unlink (file);
mirman_free (mdat);
unlink(file);
mirman_free(mdat);
return FCE_FILE;
}
return FC_SUCCESS;
}
fc_error_t mirman_check(uint32_t * ip, int af, struct mirdat *mdat,
fc_error_t mirman_check(uint32_t *ip, int af, struct mirdat *mdat,
struct mirdat_ip **md, mir_status_t *mirror_status)
{
fc_error_t status = FC_SUCCESS;
unsigned int i;
unsigned int flevel = cl_retflevel ();
unsigned int flevel = cl_retflevel();
if (NULL == md || NULL == mdat || NULL == ip) {
logg("!mirman_check: Invalid arguments.\n");
@ -120,61 +115,50 @@ fc_error_t mirman_check(uint32_t * ip, int af, struct mirdat *mdat,
*md = NULL;
if (!mdat->active)
{
if (!mdat->active) {
*mirror_status = MIRROR_OK;
goto done;
}
for (i = 0; i < mdat->num; i++)
{
for (i = 0; i < mdat->num; i++) {
if ((af == AF_INET && mdat->mirtab[i].ip4 == *ip) ||
((af == AF_INET6) && (!memcmp (mdat->mirtab[i].ip6, ip, 4 * sizeof(uint32_t)))))
{
((af == AF_INET6) && (!memcmp(mdat->mirtab[i].ip6, ip, 4 * sizeof(uint32_t))))) {
/*
* Mirror found in mirror table.
*/
if (mdat->dbflevel && (mdat->dbflevel > flevel) && (mdat->dbflevel - flevel > 3))
{
if (mdat->dbflevel && (mdat->dbflevel > flevel) && (mdat->dbflevel - flevel > 3)) {
/* Functionality level of database is lower than
* level of the database we already have */
if (difftime(time(NULL), mdat->mirtab[i].atime) < (mdat->dbflevel - flevel) * 3600)
{
if (difftime(time(NULL), mdat->mirtab[i].atime) < (mdat->dbflevel - flevel) * 3600) {
*mirror_status = MIRROR_IGNORE__OUTDATED_VERSION;
goto done;
}
}
if ((mdat->mirtab[i].atime > 0) &&
(IGNORE_NO != mdat->mirtab[i].ignore))
{
(IGNORE_NO != mdat->mirtab[i].ignore)) {
/*
* Found, but the ignore flag is set.
*/
if (difftime(time(NULL), mdat->mirtab[i].atime) > IGNORE_LONG)
{
if (difftime(time(NULL), mdat->mirtab[i].atime) > IGNORE_LONG) {
/* Long-Ignore timeout expired,
* the mirror can be attempted again */
mdat->mirtab[i].ignore = IGNORE_NO;
}
else if ((mdat->mirtab[i].ignore == IGNORE_SHORTTERM) &&
(difftime(time(NULL), mdat->mirtab[i].atime) > IGNORE_SHORT))
{
} else if ((mdat->mirtab[i].ignore == IGNORE_SHORTTERM) &&
(difftime(time(NULL), mdat->mirtab[i].atime) > IGNORE_SHORT)) {
/* Mirror was only set to Short-Term ignore...
* the Short-Ignore timeout expired,
* the mirror can be attempted again */
mdat->mirtab[i].ignore = IGNORE_NO;
}
else
{
} else {
*mirror_status = MIRROR_IGNORE__PREV_ERRS;
goto done;
}
}
/* Mirror found, and is ok to try. */
*md = &mdat->mirtab[i];
*md = &mdat->mirtab[i];
*mirror_status = MIRROR_OK;
goto done;
}
@ -188,10 +172,10 @@ done:
return status;
}
fc_error_t mirman_update(uint32_t * ip, int af, struct mirdat *mdat, fc_error_t error)
fc_error_t mirman_update(uint32_t *ip, int af, struct mirdat *mdat, fc_error_t error)
{
fc_error_t status = FCE_ARG;
unsigned int i = 0;
fc_error_t status = FCE_ARG;
unsigned int i = 0;
struct mirdat_ip *mirror = NULL;
if (!mdat->active) {
@ -202,70 +186,56 @@ fc_error_t mirman_update(uint32_t * ip, int af, struct mirdat *mdat, fc_error_t
/*
* Attempt to find the ip in the mirror table.
*/
for (i = 0; i < mdat->num; i++)
{
for (i = 0; i < mdat->num; i++) {
if (((af == AF_INET) && (mdat->mirtab[i].ip4 == *ip)) ||
((af == AF_INET6) && (!memcmp(mdat->mirtab[i].ip6, ip, 4 * sizeof(uint32_t)))))
{
((af == AF_INET6) && (!memcmp(mdat->mirtab[i].ip6, ip, 4 * sizeof(uint32_t))))) {
mirror = &mdat->mirtab[i];
break;
}
}
if (NULL == mirror)
{
if (NULL == mirror) {
/*
* Allocate space in the mirror table for the new mirror IP
*/
mdat->mirtab =
(struct mirdat_ip *) realloc(mdat->mirtab,
(struct mirdat_ip *)realloc(mdat->mirtab,
(mdat->num + 1) * sizeof(struct mirdat_ip));
if (!mdat->mirtab)
{
if (!mdat->mirtab) {
logg("!Can't allocate memory for new element in mdat->mirtab\n");
return FCE_MEM;
}
memset (&mdat->mirtab[mdat->num], 0, sizeof(struct mirdat_ip));
if (af == AF_INET)
{
memset(&mdat->mirtab[mdat->num], 0, sizeof(struct mirdat_ip));
if (af == AF_INET) {
mdat->mirtab[mdat->num].ip4 = *ip;
}
else
{
} else {
mdat->mirtab[mdat->num].ip4 = 0;
memcpy (mdat->mirtab[mdat->num].ip6, ip, 4 * sizeof(uint32_t));
memcpy(mdat->mirtab[mdat->num].ip6, ip, 4 * sizeof(uint32_t));
}
mdat->mirtab[mdat->num].atime = 0;
mdat->mirtab[mdat->num].succ = 0;
mdat->mirtab[mdat->num].fail = 0;
mdat->mirtab[mdat->num].atime = 0;
mdat->mirtab[mdat->num].succ = 0;
mdat->mirtab[mdat->num].fail = 0;
mdat->mirtab[mdat->num].ignore = 0;
mirror = &mdat->mirtab[mdat->num];
mdat->num++;
}
mirror->atime = 0; /* will be updated in mirman_write() */
mirror->atime = 0; /* will be updated in mirman_write() */
if (FC_SUCCESS == error) {
mirror->succ++;
mirror->fail = 0;
}
else
{
} else {
mirror->succ = 0;
mirror->fail++;
}
if (mirror->fail >= 6)
{
if (mirror->fail >= 6) {
mirror->ignore = IGNORE_LONGTERM;
}
else if (mirror->fail >= 3)
{
} else if (mirror->fail >= 3) {
mirror->ignore = IGNORE_SHORTTERM;
}
else
{
} else {
mirror->ignore = IGNORE_NO;
}
@ -278,40 +248,39 @@ void mirman_list(const struct mirdat *mdat)
time_t tm;
char ip[46];
for (i = 0; i < mdat->num; i++)
{
for (i = 0; i < mdat->num; i++) {
printf("Mirror #%u\n", i + 1);
#ifdef HAVE_GETADDRINFO
if (mdat->mirtab[i].ip4)
printf("IP: %s\n",
inet_ntop(AF_INET, &mdat->mirtab[i].ip4, ip, sizeof(ip)));
inet_ntop(AF_INET, &mdat->mirtab[i].ip4, ip, sizeof(ip)));
else
printf("IP: %s\n",
inet_ntop(AF_INET6, mdat->mirtab[i].ip6, ip, sizeof(ip)));
inet_ntop(AF_INET6, mdat->mirtab[i].ip6, ip, sizeof(ip)));
#else
if (mdat->mirtab[i].ip4)
printf("IP: %s\n",
inet_ntoa(*(struct in_addr *)&mdat->mirtab[i].ip4));
inet_ntoa(*(struct in_addr *)&mdat->mirtab[i].ip4));
#endif
printf("Successes: %u\n", mdat->mirtab[i].succ);
printf("Failures: %u\n", mdat->mirtab[i].fail);
tm = mdat->mirtab[i].atime;
printf("Last access: %s", ctime((const time_t *) &tm));
printf("Last access: %s", ctime((const time_t *)&tm));
if (mdat->mirtab[i].ignore) {
time_t ignore_expires = tm + ((mdat->mirtab[i].ignore == IGNORE_LONGTERM) ? IGNORE_LONG
: IGNORE_SHORT);
double difference = difftime(ignore_expires, time(NULL));
double difference = difftime(ignore_expires, time(NULL));
if (difference > 0) {
uint32_t remaining = difference;
uint32_t seconds, minutes, hours;
seconds = remaining % 60;
seconds = remaining % 60;
remaining = remaining / 60;
minutes = remaining % 60;
minutes = remaining % 60;
remaining = remaining / 60;
hours = remaining % 60;
hours = remaining % 60;
printf("Ignore: Yes, %d hours %d minutes %d seconds remaining.\n",
hours, minutes, seconds);
hours, minutes, seconds);
} else {
printf("Ignore: No\n");
}
@ -332,27 +301,22 @@ void mirman_whitelist(struct mirdat *mdat, unsigned int mode)
return;
}
switch (mode)
{
case 1:
logg("*Whitelisting all blacklisted mirrors\n");
break;
case 2:
logg("*Whitelisting short-term blacklisted mirrors\n");
break;
default:
logg("!mirman_whitelist: Unexpected mode argument: %u\n", mode);
return;
switch (mode) {
case 1:
logg("*Whitelisting all blacklisted mirrors\n");
break;
case 2:
logg("*Whitelisting short-term blacklisted mirrors\n");
break;
default:
logg("!mirman_whitelist: Unexpected mode argument: %u\n", mode);
return;
}
for (i = 0; i < mdat->num; i++)
{
if (mode == 1)
{
for (i = 0; i < mdat->num; i++) {
if (mode == 1) {
mdat->mirtab[i].ignore = IGNORE_NO;
}
else if ((mode == 2) && (IGNORE_SHORTTERM == mdat->mirtab[i].ignore))
{
} else if ((mode == 2) && (IGNORE_SHORTTERM == mdat->mirtab[i].ignore)) {
mdat->mirtab[i].ignore = IGNORE_NO;
}
}
@ -373,18 +337,16 @@ fc_error_t mirman_write(const char *file, const char *dir, struct mirdat *mdat)
return FC_SUCCESS;
if ((fd =
open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600)) == -1)
{
open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600)) == -1) {
logg("!Can't open %s for writing\n", path);
return FCE_OPEN;
}
for (i = 0; i < mdat->num; i++)
if (!mdat->mirtab[i].atime)
mdat->mirtab[i].atime = (uint32_t) time(NULL);
mdat->mirtab[i].atime = (uint32_t)time(NULL);
if (write(fd, mdat->mirtab, mdat->num * sizeof(struct mirdat_ip)) == -1)
{
if (write(fd, mdat->mirtab, mdat->num * sizeof(struct mirdat_ip)) == -1) {
logg("!Can't write to %s\n", path);
close(fd);
return FCE_FILE;

View file

@ -23,37 +23,35 @@
#include "freshclamcodes.h"
typedef enum mir_status_tag {
MIRROR_OK=0,
MIRROR_OK = 0,
MIRROR_FAILURE,
MIRROR_IGNORE__PREV_ERRS,
MIRROR_IGNORE__OUTDATED_VERSION
} mir_status_t;
typedef enum mir_ignore_tag {
IGNORE_NO=0,
IGNORE_NO = 0,
IGNORE_LONGTERM,
IGNORE_SHORTTERM
} mir_ignore_t;
struct mirdat_ip
{
uint32_t ip4; /* IPv4 address */
time_t atime; /* last access time */
uint32_t succ; /* number of successful downloads from this ip */
uint32_t fail; /* number of failures */
uint8_t ignore; /* ignore flag */
uint32_t ip6[4]; /* IPv6 address */
char res[16]; /* reserved */
struct mirdat_ip {
uint32_t ip4; /* IPv4 address */
time_t atime; /* last access time */
uint32_t succ; /* number of successful downloads from this ip */
uint32_t fail; /* number of failures */
uint8_t ignore; /* ignore flag */
uint32_t ip6[4]; /* IPv6 address */
char res[16]; /* reserved */
};
struct mirdat
{
uint8_t active; /* 1 if active, 2 if disabled */
unsigned int num; /* number of mirrors */
uint32_t currip[4]; /* IP currently attempting */
uint32_t af; /* AF_INET or AF_INET6 for current IP */
uint32_t dbflevel; /* functionality level of current database */
struct mirdat_ip *mirtab; /* mirror table of known mirror IP addresses */
struct mirdat {
uint8_t active; /* 1 if active, 2 if disabled */
unsigned int num; /* number of mirrors */
uint32_t currip[4]; /* IP currently attempting */
uint32_t af; /* AF_INET or AF_INET6 for current IP */
uint32_t dbflevel; /* functionality level of current database */
struct mirdat_ip *mirtab; /* mirror table of known mirror IP addresses */
};
/**
@ -80,7 +78,7 @@ fc_error_t mirman_read(const char *file, struct mirdat *mdat, uint8_t active);
* MIRROR_IGNORE__OUTDATED_VERSION
* @return fc_error_t FC_SUCCESS or an FCE error code.
*/
fc_error_t mirman_check(uint32_t * ip, int af, struct mirdat *mdat,
fc_error_t mirman_check(uint32_t *ip, int af, struct mirdat *mdat,
struct mirdat_ip **md, mir_status_t *mirror_status);
/**
@ -92,7 +90,7 @@ fc_error_t mirman_check(uint32_t * ip, int af, struct mirdat *mdat,
* @param error FC_SUCCESS or an FCE error code.
* @return fc_error_t FC_SUCCESS or an FCE error code.
*/
fc_error_t mirman_update(uint32_t * ip, int af, struct mirdat *mdat, fc_error_t mirror_status);
fc_error_t mirman_update(uint32_t *ip, int af, struct mirdat *mdat, fc_error_t mirror_status);
/**
* @brief Print out the mirror info.

View file

@ -24,12 +24,12 @@
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <ctype.h>
#ifndef _WIN32
#ifndef _WIN32
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
@ -47,164 +47,153 @@
#ifdef SO_ERROR
#ifndef timercmp
#define timercmp(a, b, cmp) \
(((a)->tv_sec == (b)->tv_sec) \
? ((a)->tv_usec cmp (b)->tv_usec) \
: ((a)->tv_sec cmp (b)->tv_sec))
#define timercmp(a, b, cmp) \
(((a)->tv_sec == (b)->tv_sec) \
? ((a)->tv_usec cmp(b)->tv_usec) \
: ((a)->tv_sec cmp(b)->tv_sec))
#endif /* timercmp */
#ifndef timersub
#define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
#define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
#endif /* timersub */
#define NONBLOCK_SELECT_MAX_FAILURES 3
#define NONBLOCK_MAX_BOGUS_LOOPS 10
#undef NONBLOCK_DEBUG
#define NONBLOCK_MAX_BOGUS_LOOPS 10
#undef NONBLOCK_DEBUG
static int
connect_error (int sock)
connect_error(int sock)
{
int optval;
socklen_t optlen;
optlen = sizeof (optval);
getsockopt (sock, SOL_SOCKET, SO_ERROR, &optval, (socklen_t *)&optlen);
optlen = sizeof(optval);
getsockopt(sock, SOL_SOCKET, SO_ERROR, &optval, (socklen_t *)&optlen);
if (optval)
{
logg ("connect_error: getsockopt(SO_ERROR): fd=%d error=%d: %s\n",
sock, optval, strerror (optval));
if (optval) {
logg("connect_error: getsockopt(SO_ERROR): fd=%d error=%d: %s\n",
sock, optval, strerror(optval));
}
return optval ? -1 : 0;
}
static int
nonblock_connect (int sock, const struct sockaddr *addr, socklen_t addrlen,
int secs)
nonblock_connect(int sock, const struct sockaddr *addr, socklen_t addrlen,
int secs)
{
/* Max. of unexpected select() failures */
int select_failures = NONBLOCK_SELECT_MAX_FAILURES;
/* Max. of useless loops */
int bogus_loops = NONBLOCK_MAX_BOGUS_LOOPS;
struct timeval timeout; /* When we should time out */
int numfd; /* Highest fdset fd plus 1 */
struct timeval timeout; /* When we should time out */
int numfd; /* Highest fdset fd plus 1 */
/* Calculate into 'timeout' when we should time out */
gettimeofday (&timeout, 0);
gettimeofday(&timeout, 0);
timeout.tv_sec += secs;
/* Launch (possibly) non-blocking connect() request */
if (connect (sock, addr, addrlen))
{
if (connect(sock, addr, addrlen)) {
int e = errno;
#ifdef NONBLOCK_DEBUG
logg ("DEBUG nonblock_connect: connect(): fd=%d errno=%d: %s\n",
sock, e, strerror (e));
logg("DEBUG nonblock_connect: connect(): fd=%d errno=%d: %s\n",
sock, e, strerror(e));
#endif
switch (e)
{
case EALREADY:
case EINPROGRESS:
case EAGAIN:
break; /* wait for connection */
case EISCONN:
return 0; /* connected */
default:
logg ("nonblock_connect: connect(): fd=%d errno=%d: %s\n",
sock, e, strerror (e));
return -1; /* failed */
switch (e) {
case EALREADY:
case EINPROGRESS:
case EAGAIN:
break; /* wait for connection */
case EISCONN:
return 0; /* connected */
default:
logg("nonblock_connect: connect(): fd=%d errno=%d: %s\n",
sock, e, strerror(e));
return -1; /* failed */
}
}
else
{
return connect_error (sock);
} else {
return connect_error(sock);
}
numfd = sock + 1; /* Highest fdset fd plus 1 */
numfd = sock + 1; /* Highest fdset fd plus 1 */
for (;;)
{
for (;;) {
fd_set fds;
struct timeval now;
struct timeval wait;
int n;
/* Force timeout if we ran out of time */
gettimeofday (&now, 0);
if (timercmp (&now, &timeout, >))
{
logg ("nonblock_connect: connect timing out (%d secs)\n", secs);
break; /* failed */
gettimeofday(&now, 0);
if (timercmp(&now, &timeout, >)) {
logg("nonblock_connect: connect timing out (%d secs)\n", secs);
break; /* failed */
}
/* Calculate into 'wait' how long to wait */
timersub (&timeout, &now, &wait); /* wait = timeout - now */
timersub(&timeout, &now, &wait); /* wait = timeout - now */
/* Init fds with 'sock' as the only fd */
FD_ZERO (&fds);
FD_SET (sock, &fds);
FD_ZERO(&fds);
FD_SET(sock, &fds);
n = select (numfd, 0, &fds, 0, &wait);
if (n < 0)
{
logg ("nonblock_connect: select() failure %d: errno=%d: %s\n",
select_failures, errno, strerror (errno));
n = select(numfd, 0, &fds, 0, &wait);
if (n < 0) {
logg("nonblock_connect: select() failure %d: errno=%d: %s\n",
select_failures, errno, strerror(errno));
if (--select_failures >= 0)
continue; /* keep waiting */
break; /* failed */
continue; /* keep waiting */
break; /* failed */
}
#ifdef NONBLOCK_DEBUG
logg ("DEBUG nonblock_connect: select = %d\n", n);
logg("DEBUG nonblock_connect: select = %d\n", n);
#endif
if (n)
{
return connect_error (sock);
if (n) {
return connect_error(sock);
}
/* Select returned, but there is no work to do... */
if (--bogus_loops < 0)
{
logg ("nonblock_connect: giving up due to excessive bogus loops\n");
break; /* failed */
if (--bogus_loops < 0) {
logg("nonblock_connect: giving up due to excessive bogus loops\n");
break; /* failed */
}
} /* for loop: keep waiting */
} /* for loop: keep waiting */
return -1; /* failed */
return -1; /* failed */
}
static ssize_t
nonblock_recv (int sock, void *buf, size_t len, int flags, int secs)
nonblock_recv(int sock, void *buf, size_t len, int flags, int secs)
{
/* Max. of unexpected select() failures */
int select_failures = NONBLOCK_SELECT_MAX_FAILURES;
/* Max. of useless loops */
int bogus_loops = NONBLOCK_MAX_BOGUS_LOOPS;
struct timeval timeout; /* When we should time out */
int numfd; /* Highest fdset fd plus 1 */
struct timeval timeout; /* When we should time out */
int numfd; /* Highest fdset fd plus 1 */
/* Zero buffer to maintain sanity in case we're dealing with strings */
memset(buf, 0x00, len);
/* Calculate into 'timeout' when we should time out */
gettimeofday (&timeout, 0);
gettimeofday(&timeout, 0);
timeout.tv_sec += secs;
numfd = sock + 1; /* Highest fdset fd plus 1 */
numfd = sock + 1; /* Highest fdset fd plus 1 */
for (;;)
{
for (;;) {
fd_set fds;
struct timeval now;
struct timeval wait;
@ -212,32 +201,29 @@ nonblock_recv (int sock, void *buf, size_t len, int flags, int secs)
ssize_t recvd;
/* Force timeout if we ran out of time */
gettimeofday (&now, 0);
if (timercmp (&now, &timeout, >))
{
logg ("nonblock_recv: recv timing out (%d secs)\n", secs);
break; /* failed */
gettimeofday(&now, 0);
if (timercmp(&now, &timeout, >)) {
logg("nonblock_recv: recv timing out (%d secs)\n", secs);
break; /* failed */
}
/* Calculate into 'wait' how long to wait */
timersub (&timeout, &now, &wait); /* wait = timeout - now */
timersub(&timeout, &now, &wait); /* wait = timeout - now */
/* Init fds with 'sock' as the only fd */
FD_ZERO (&fds);
FD_SET (sock, &fds);
FD_ZERO(&fds);
FD_SET(sock, &fds);
n = select (numfd, &fds, 0, 0, &wait);
if (n < 0)
{
logg ("nonblock_recv: select() failure %d: errno=%d: %s\n",
select_failures, errno, strerror (errno));
n = select(numfd, &fds, 0, 0, &wait);
if (n < 0) {
logg("nonblock_recv: select() failure %d: errno=%d: %s\n",
select_failures, errno, strerror(errno));
if (--select_failures >= 0)
continue; /* keep waiting */
break; /* failed */
continue; /* keep waiting */
break; /* failed */
}
if (FD_ISSET(sock, &fds))
{
if (FD_ISSET(sock, &fds)) {
recvd = recv(sock, buf, len, flags);
if (recvd < 0) {
if (errno == EINTR)
@ -250,32 +236,28 @@ nonblock_recv (int sock, void *buf, size_t len, int flags, int secs)
}
/* Select returned, but there is no work to do... */
if (--bogus_loops < 0)
{
logg ("nonblock_recv: giving up due to excessive bogus loops\n");
break; /* failed */
if (--bogus_loops < 0) {
logg("nonblock_recv: giving up due to excessive bogus loops\n");
break; /* failed */
}
} /* for loop: keep waiting */
} /* for loop: keep waiting */
return -1; /* failed */
return -1; /* failed */
}
static long
nonblock_fcntl (int sock)
nonblock_fcntl(int sock)
{
#ifdef F_GETFL
long fcntl_flags; /* Save fcntl() flags */
#ifdef F_GETFL
long fcntl_flags; /* Save fcntl() flags */
fcntl_flags = fcntl (sock, F_GETFL, 0);
if (fcntl_flags == -1)
{
logg ("nonblock_fcntl: saving: fcntl(%d, F_GETFL): errno=%d: %s\n",
sock, errno, strerror (errno));
}
else if (fcntl (sock, F_SETFL, fcntl_flags | O_NONBLOCK))
{
logg ("nonblock_fcntl: fcntl(%d, F_SETFL, O_NONBLOCK): errno=%d: %s\n", sock, errno, strerror (errno));
fcntl_flags = fcntl(sock, F_GETFL, 0);
if (fcntl_flags == -1) {
logg("nonblock_fcntl: saving: fcntl(%d, F_GETFL): errno=%d: %s\n",
sock, errno, strerror(errno));
} else if (fcntl(sock, F_SETFL, fcntl_flags | O_NONBLOCK)) {
logg("nonblock_fcntl: fcntl(%d, F_SETFL, O_NONBLOCK): errno=%d: %s\n", sock, errno, strerror(errno));
}
return fcntl_flags;
@ -285,14 +267,12 @@ nonblock_fcntl (int sock)
}
static void
restore_fcntl (int sock, long fcntl_flags)
restore_fcntl(int sock, long fcntl_flags)
{
#ifdef F_SETFL
if (fcntl_flags != -1)
{
if (fcntl (sock, F_SETFL, fcntl_flags))
{
logg ("restore_fcntl: restoring: fcntl(%d, F_SETFL): errno=%d: %s\n", sock, errno, strerror (errno));
#ifdef F_SETFL
if (fcntl_flags != -1) {
if (fcntl(sock, F_SETFL, fcntl_flags)) {
logg("restore_fcntl: restoring: fcntl(%d, F_SETFL): errno=%d: %s\n", sock, errno, strerror(errno));
}
}
#endif
@ -301,20 +281,19 @@ restore_fcntl (int sock, long fcntl_flags)
/*
wait_connect(): wrapper for connect(), with explicit 'secs' timeout
*/
int
wait_connect (int sock, const struct sockaddr *addr, socklen_t addrlen,
int secs)
int wait_connect(int sock, const struct sockaddr *addr, socklen_t addrlen,
int secs)
{
long fcntl_flags; /* Save fcntl() flags */
long fcntl_flags; /* Save fcntl() flags */
int ret;
/* Temporarily set socket to non-blocking mode */
fcntl_flags = nonblock_fcntl (sock);
fcntl_flags = nonblock_fcntl(sock);
ret = nonblock_connect (sock, addr, addrlen, secs);
ret = nonblock_connect(sock, addr, addrlen, secs);
/* Restore socket's default blocking mode */
restore_fcntl (sock, fcntl_flags);
restore_fcntl(sock, fcntl_flags);
return ret;
}
@ -323,18 +302,18 @@ wait_connect (int sock, const struct sockaddr *addr, socklen_t addrlen,
wait_recv(): wrapper for recv(), with explicit 'secs' timeout
*/
ssize_t
wait_recv (int sock, void *buf, size_t len, int flags, int secs)
wait_recv(int sock, void *buf, size_t len, int flags, int secs)
{
long fcntl_flags; /* Save fcntl() flags */
long fcntl_flags; /* Save fcntl() flags */
int ret;
/* Temporarily set socket to non-blocking mode */
fcntl_flags = nonblock_fcntl (sock);
fcntl_flags = nonblock_fcntl(sock);
ret = nonblock_recv (sock, buf, len, flags, secs);
ret = nonblock_recv(sock, buf, len, flags, secs);
/* Restore socket's default blocking mode */
restore_fcntl (sock, fcntl_flags);
restore_fcntl(sock, fcntl_flags);
return ret;
}

View file

@ -24,19 +24,19 @@
#endif
#include <sys/types.h>
#ifndef _WIN32
#ifndef _WIN32
#include <sys/socket.h>
#endif
/*
wait_connect(): wrapper for connect(), with explicit 'secs' timeout
*/
int wait_connect (int sock, const struct sockaddr *addr, socklen_t addrlen,
int secs);
int wait_connect(int sock, const struct sockaddr *addr, socklen_t addrlen,
int secs);
/*
wait_recv(): wrapper for recv(), with explicit 'secs' timeout
*/
ssize_t wait_recv (int sock, void *buf, size_t len, int flags, int secs);
ssize_t wait_recv(int sock, void *buf, size_t len, int flags, int secs);
#endif /* NONBLOCK_H */

View file

@ -24,11 +24,11 @@
#ifdef BUILD_CLAMD
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/types.h>
#ifndef _WIN32
#ifndef _WIN32
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
@ -44,10 +44,9 @@
#include "notify.h"
int
clamd_connect (const char *cfgfile, const char *option)
int clamd_connect(const char *cfgfile, const char *option)
{
#ifndef _WIN32
#ifndef _WIN32
struct sockaddr_un server;
#endif
@ -59,83 +58,74 @@ clamd_connect (const char *cfgfile, const char *option)
const struct optstruct *opt;
int sockd;
if ((opts = optparse (cfgfile, 0, NULL, 1, OPT_CLAMD, 0, NULL)) == NULL)
{
logg ("!%s: Can't find or parse configuration file %s\n", option,
cfgfile);
if ((opts = optparse(cfgfile, 0, NULL, 1, OPT_CLAMD, 0, NULL)) == NULL) {
logg("!%s: Can't find or parse configuration file %s\n", option,
cfgfile);
return -11;
}
#ifndef _WIN32
if ((opt = optget (opts, "LocalSocket"))->enabled)
{
#ifndef _WIN32
if ((opt = optget(opts, "LocalSocket"))->enabled) {
memset(&server, 0x00, sizeof(server));
server.sun_family = AF_UNIX;
strncpy (server.sun_path, opt->strarg, sizeof (server.sun_path));
server.sun_path[sizeof (server.sun_path) - 1] = '\0';
strncpy(server.sun_path, opt->strarg, sizeof(server.sun_path));
server.sun_path[sizeof(server.sun_path) - 1] = '\0';
if ((sockd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
{
logg ("^Clamd was NOT notified: Can't create socket endpoint for %s: %s\n",
opt->strarg, strerror(errno));
optfree (opts);
if ((sockd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
logg("^Clamd was NOT notified: Can't create socket endpoint for %s: %s\n",
opt->strarg, strerror(errno));
optfree(opts);
return -1;
}
if (connect
(sockd, (struct sockaddr *) &server,
sizeof (struct sockaddr_un)) < 0)
{
logg ("^Clamd was NOT notified: Can't connect to clamd through %s: %s\n",
opt->strarg, strerror(errno));
closesocket (sockd);
optfree (opts);
if (connect(sockd, (struct sockaddr *)&server,
sizeof(struct sockaddr_un)) < 0) {
logg("^Clamd was NOT notified: Can't connect to clamd through %s: %s\n",
opt->strarg, strerror(errno));
closesocket(sockd);
optfree(opts);
return -11;
}
return sockd;
}
else
} else
#endif
if ((opt = optget (opts, "TCPSocket"))->enabled)
{
memset (&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC;
if ((opt = optget(opts, "TCPSocket"))->enabled) {
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
hints.ai_flags = AI_PASSIVE;
snprintf (port, sizeof (port), "%u", (unsigned int) opt->numarg);
snprintf(port, sizeof(port), "%u", (unsigned int)opt->numarg);
port[5] = 0;
opt = optget(opts, "TCPAddr");
while (opt) {
ret = getaddrinfo (opt->strarg, port, &hints, &res);
ret = getaddrinfo(opt->strarg, port, &hints, &res);
if (ret)
{
logg ("!%s: Can't resolve hostname %s (%s)\n", option,
opt->strarg ? opt->strarg : "",
(ret ==
EAI_SYSTEM) ? strerror (errno) : gai_strerror (ret));
if (ret) {
logg("!%s: Can't resolve hostname %s (%s)\n", option,
opt->strarg ? opt->strarg : "",
(ret ==
EAI_SYSTEM)
? strerror(errno)
: gai_strerror(ret));
opt = opt->nextarg;
continue;
}
for (p = res; p != NULL; p = p->ai_next) {
if ((sockd = socket (p->ai_family, p->ai_socktype, p->ai_protocol)) < 0)
{
logg ("!%s: Can't create TCP socket to connect to %s: %s\n",
option, opt->strarg ? opt->strarg : "localhost", strerror(errno));
if ((sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
logg("!%s: Can't create TCP socket to connect to %s: %s\n",
option, opt->strarg ? opt->strarg : "localhost", strerror(errno));
continue;
}
if (connect (sockd, p->ai_addr, p->ai_addrlen) == -1)
{
logg ("!%s: Can't connect to clamd on %s:%s: %s\n", option,
opt->strarg ? opt->strarg : "localhost", port, strerror(errno));
closesocket (sockd);
if (connect(sockd, p->ai_addr, p->ai_addrlen) == -1) {
logg("!%s: Can't connect to clamd on %s:%s: %s\n", option,
opt->strarg ? opt->strarg : "localhost", port, strerror(errno));
closesocket(sockd);
continue;
}
@ -145,51 +135,45 @@ clamd_connect (const char *cfgfile, const char *option)
return sockd;
}
freeaddrinfo (res);
freeaddrinfo(res);
opt = opt->nextarg;
}
}
else
{
logg ("!%s: No communication socket specified in %s\n", option,
cfgfile);
optfree (opts);
} else {
logg("!%s: No communication socket specified in %s\n", option,
cfgfile);
optfree(opts);
return 1;
}
optfree (opts);
optfree(opts);
return -1;
}
int
notify (const char *cfgfile)
int notify(const char *cfgfile)
{
char buff[20];
int sockd, bread;
if ((sockd = clamd_connect (cfgfile, "NotifyClamd")) < 0)
if ((sockd = clamd_connect(cfgfile, "NotifyClamd")) < 0)
return 1;
if (sendln (sockd, "RELOAD", 7) < 0)
{
logg ("!NotifyClamd: Could not write to clamd socket: %s\n", strerror(errno));
closesocket (sockd);
if (sendln(sockd, "RELOAD", 7) < 0) {
logg("!NotifyClamd: Could not write to clamd socket: %s\n", strerror(errno));
closesocket(sockd);
return 1;
}
memset (buff, 0, sizeof (buff));
if ((bread = recv (sockd, buff, sizeof (buff), 0)) > 0)
{
if (!strstr (buff, "RELOADING"))
{
logg ("!NotifyClamd: Unknown answer from clamd: '%s'\n", buff);
closesocket (sockd);
memset(buff, 0, sizeof(buff));
if ((bread = recv(sockd, buff, sizeof(buff), 0)) > 0) {
if (!strstr(buff, "RELOADING")) {
logg("!NotifyClamd: Unknown answer from clamd: '%s'\n", buff);
closesocket(sockd);
return -1;
}
}
closesocket (sockd);
logg ("Clamd successfully notified about the update.\n");
closesocket(sockd);
logg("Clamd successfully notified about the update.\n");
return 0;
}
#endif

View file

@ -19,7 +19,7 @@
#ifndef __NOTIFY_H
#define __NOTIFY_H
int notify (const char *cfgfile);
int clamd_connect (const char *cfgfile, const char *option);
int notify(const char *cfgfile);
int clamd_connect(const char *cfgfile, const char *option);
#endif

View file

@ -35,20 +35,20 @@
#include "7z/7zAlloc.h"
#include "7z/7zFile.h"
static ISzAlloc allocImp = {__lzma_wrap_alloc, __lzma_wrap_free}, allocTempImp = {__lzma_wrap_alloc, __lzma_wrap_free};
static ISzAlloc allocImp = { __lzma_wrap_alloc, __lzma_wrap_free}, allocTempImp = { __lzma_wrap_alloc, __lzma_wrap_free};
static SRes FileInStream_fmap_Read(void *pp, void *buf, size_t *size) {
static SRes FileInStream_fmap_Read(void *pp, void *buf, size_t *size)
{
CFileInStream *p = (CFileInStream *)pp;
int read_sz;
if (*size == 0)
return 0;
return 0;
read_sz = fmap_readn(p->file.fmap, buf, p->s.curpos, *size);
if(read_sz < 0) {
*size = 0;
return SZ_ERROR_READ;
if (read_sz < 0) {
*size = 0;
return SZ_ERROR_READ;
}
p->s.curpos += read_sz;
@ -57,29 +57,31 @@ static SRes FileInStream_fmap_Read(void *pp, void *buf, size_t *size) {
return SZ_OK;
}
static SRes FileInStream_fmap_Seek(void *pp, Int64 *pos, ESzSeek origin) {
static SRes FileInStream_fmap_Seek(void *pp, Int64 *pos, ESzSeek origin)
{
CFileInStream *p = (CFileInStream *)pp;
switch (origin) {
case SZ_SEEK_SET:
p->s.curpos = *pos;
break;
case SZ_SEEK_CUR:
p->s.curpos += *pos;
*pos = p->s.curpos;
break;
case SZ_SEEK_END:
p->s.curpos = p->file.fmap->len + *pos;
*pos = p->s.curpos;
break;
default:
return 1;
case SZ_SEEK_SET:
p->s.curpos = *pos;
break;
case SZ_SEEK_CUR:
p->s.curpos += *pos;
*pos = p->s.curpos;
break;
case SZ_SEEK_END:
p->s.curpos = p->file.fmap->len + *pos;
*pos = p->s.curpos;
break;
default:
return 1;
}
return 0;
}
#define UTFBUFSZ 256
int cli_7unz (cli_ctx *ctx, size_t offset) {
int cli_7unz(cli_ctx *ctx, size_t offset)
{
CFileInStream archiveStream;
CLookToRead lookStream;
CSzArEx db;
@ -87,137 +89,136 @@ int cli_7unz (cli_ctx *ctx, size_t offset) {
UInt16 utf16buf[UTFBUFSZ], *utf16name = utf16buf;
int namelen = UTFBUFSZ, found = CL_CLEAN;
Int64 begin_of_archive = offset;
UInt32 viruses_found = 0;
UInt32 viruses_found = 0;
/* Replacement for
FileInStream_CreateVTable(&archiveStream); */
archiveStream.s.Read = FileInStream_fmap_Read;
archiveStream.s.Seek = FileInStream_fmap_Seek;
archiveStream.s.curpos = 0;
archiveStream.s.Read = FileInStream_fmap_Read;
archiveStream.s.Seek = FileInStream_fmap_Seek;
archiveStream.s.curpos = 0;
archiveStream.file.fmap = *ctx->fmap;
LookToRead_CreateVTable(&lookStream, False);
if(archiveStream.s.Seek(&archiveStream.s, &begin_of_archive, SZ_SEEK_SET) != 0)
return CL_CLEAN;
if (archiveStream.s.Seek(&archiveStream.s, &begin_of_archive, SZ_SEEK_SET) != 0)
return CL_CLEAN;
lookStream.realStream = &archiveStream.s;
LookToRead_Init(&lookStream);
SzArEx_Init(&db);
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
if(res == SZ_ERROR_ENCRYPTED && SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) {
cli_dbgmsg("cli_7unz: Encrypted header found in archive.\n");
found = cli_append_virus(ctx, "Heuristics.Encrypted.7Zip");
} else if(res == SZ_OK) {
UInt32 i, blockIndex = 0xFFFFFFFF;
Byte *outBuffer = 0;
size_t outBufferSize = 0;
unsigned int encrypted = 0;
if (res == SZ_ERROR_ENCRYPTED && SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) {
cli_dbgmsg("cli_7unz: Encrypted header found in archive.\n");
found = cli_append_virus(ctx, "Heuristics.Encrypted.7Zip");
} else if (res == SZ_OK) {
UInt32 i, blockIndex = 0xFFFFFFFF;
Byte *outBuffer = 0;
size_t outBufferSize = 0;
unsigned int encrypted = 0;
for (i = 0; i < db.db.NumFiles; i++) {
size_t offset = 0;
size_t outSizeProcessed = 0;
const CSzFileItem *f = db.db.Files + i;
char *name;
size_t j;
int newnamelen, fd;
for (i = 0; i < db.db.NumFiles; i++) {
size_t offset = 0;
size_t outSizeProcessed = 0;
const CSzFileItem *f = db.db.Files + i;
char *name;
size_t j;
int newnamelen, fd;
if((found = cli_checklimits("7unz", ctx, 0, 0, 0)))
break;
if ((found = cli_checklimits("7unz", ctx, 0, 0, 0)))
break;
if (f->IsDir)
continue;
if (f->IsDir)
continue;
if(cli_checklimits("7unz", ctx, f->Size, 0, 0))
continue;
if (cli_checklimits("7unz", ctx, f->Size, 0, 0))
continue;
if (!db.FileNameOffsets)
newnamelen = 0; /* no filename */
else {
newnamelen = SzArEx_GetFileNameUtf16(&db, i, NULL);
if (newnamelen > namelen) {
if(namelen > UTFBUFSZ)
free(utf16name);
utf16name = cli_malloc(newnamelen*2);
if(!utf16name) {
found = CL_EMEM;
break;
}
namelen = newnamelen;
}
SzArEx_GetFileNameUtf16(&db, i, utf16name);
}
if (!db.FileNameOffsets)
newnamelen = 0; /* no filename */
else {
newnamelen = SzArEx_GetFileNameUtf16(&db, i, NULL);
if (newnamelen > namelen) {
if (namelen > UTFBUFSZ)
free(utf16name);
utf16name = cli_malloc(newnamelen * 2);
if (!utf16name) {
found = CL_EMEM;
break;
}
namelen = newnamelen;
}
SzArEx_GetFileNameUtf16(&db, i, utf16name);
}
name = (char *)utf16name;
for(j=0; j<(size_t)newnamelen; j++) /* FIXME */
name[j] = utf16name[j];
name[j] = 0;
cli_dbgmsg("cli_7unz: extracting %s\n", name);
name = (char *)utf16name;
for (j = 0; j < (size_t)newnamelen; j++) /* FIXME */
name[j] = utf16name[j];
name[j] = 0;
cli_dbgmsg("cli_7unz: extracting %s\n", name);
res = SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp);
if(res == SZ_ERROR_ENCRYPTED) {
encrypted = 1;
if(SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) {
cli_dbgmsg("cli_7unz: Encrypted files found in archive.\n");
found = cli_append_virus(ctx, "Heuristics.Encrypted.7Zip");
res = SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp);
if (res == SZ_ERROR_ENCRYPTED) {
encrypted = 1;
if (SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) {
cli_dbgmsg("cli_7unz: Encrypted files found in archive.\n");
found = cli_append_virus(ctx, "Heuristics.Encrypted.7Zip");
if (found != CL_CLEAN) {
if (found == CL_VIRUS) {
if (SCAN_ALLMATCHES)
viruses_found++;
} else
break;
}
}
}
if(cli_matchmeta(ctx, name, 0, f->Size, encrypted, i, f->CrcDefined ? f->Crc : 0, NULL)) {
found = CL_VIRUS;
viruses_found++;
if (!SCAN_ALLMATCHES)
break;
}
if (res != SZ_OK)
cli_dbgmsg("cli_unz: extraction failed with %d\n", res);
else {
if((found = cli_gentempfd(ctx->engine->tmpdir, &name, &fd)))
break;
}
}
}
if (cli_matchmeta(ctx, name, 0, f->Size, encrypted, i, f->CrcDefined ? f->Crc : 0, NULL)) {
found = CL_VIRUS;
viruses_found++;
if (!SCAN_ALLMATCHES)
break;
}
if (res != SZ_OK)
cli_dbgmsg("cli_unz: extraction failed with %d\n", res);
else {
if ((found = cli_gentempfd(ctx->engine->tmpdir, &name, &fd)))
break;
cli_dbgmsg("cli_7unz: Saving to %s\n", name);
if((size_t)cli_writen(fd, outBuffer + offset, outSizeProcessed) != outSizeProcessed)
found = CL_EWRITE;
else
if ((found = cli_magic_scandesc(fd, name, ctx)) == CL_VIRUS)
viruses_found++;
close(fd);
if(!ctx->engine->keeptmp && cli_unlink(name))
found = CL_EUNLINK;
cli_dbgmsg("cli_7unz: Saving to %s\n", name);
if ((size_t)cli_writen(fd, outBuffer + offset, outSizeProcessed) != outSizeProcessed)
found = CL_EWRITE;
else if ((found = cli_magic_scandesc(fd, name, ctx)) == CL_VIRUS)
viruses_found++;
close(fd);
if (!ctx->engine->keeptmp && cli_unlink(name))
found = CL_EUNLINK;
free(name);
if(found != CL_CLEAN)
if (!(SCAN_ALLMATCHES && found == CL_VIRUS))
break;
}
}
IAlloc_Free(&allocImp, outBuffer);
free(name);
if (found != CL_CLEAN)
if (!(SCAN_ALLMATCHES && found == CL_VIRUS))
break;
}
}
IAlloc_Free(&allocImp, outBuffer);
}
SzArEx_Free(&db, &allocImp);
if(namelen > UTFBUFSZ)
free(utf16name);
if (namelen > UTFBUFSZ)
free(utf16name);
if (res == SZ_OK)
cli_dbgmsg("cli_7unz: completed successfully\n");
cli_dbgmsg("cli_7unz: completed successfully\n");
else if (res == SZ_ERROR_UNSUPPORTED)
cli_dbgmsg("cli_7unz: unsupported\n");
cli_dbgmsg("cli_7unz: unsupported\n");
else if (res == SZ_ERROR_MEM)
cli_dbgmsg("cli_7unz: oom\n");
cli_dbgmsg("cli_7unz: oom\n");
else if (res == SZ_ERROR_CRC)
cli_dbgmsg("cli_7unz: crc mismatch\n");
cli_dbgmsg("cli_7unz: crc mismatch\n");
else if (res == SZ_ERROR_ENCRYPTED)
cli_dbgmsg("cli_7unz: encrypted\n");
cli_dbgmsg("cli_7unz: encrypted\n");
else
cli_dbgmsg("cli_7unz: error %d\n", res);
cli_dbgmsg("cli_7unz: error %d\n", res);
if (SCAN_ALLMATCHES && viruses_found)
return CL_VIRUS;
return CL_VIRUS;
return found;
}

View file

@ -28,6 +28,6 @@
#include "others.h"
int cli_7unz (cli_ctx *, size_t);
int cli_7unz(cli_ctx *, size_t);
#endif

View file

@ -37,9 +37,9 @@
/* #define DEBUG_ADC */
#ifdef DEBUG_ADC
# define adc_dbgmsg(...) cli_dbgmsg( __VA_ARGS__ )
#define adc_dbgmsg(...) cli_dbgmsg(__VA_ARGS__)
#else
# define adc_dbgmsg(...) ;
#define adc_dbgmsg(...) ;
#endif
/* Initialize values and collect buffer
@ -59,10 +59,10 @@ int adc_decompressInit(adc_stream *strm)
return ADC_MEM_ERROR;
}
strm->buffered = 0;
strm->state = ADC_STATE_GETTYPE;
strm->length = 0;
strm->offset = 0;
strm->curr = strm->buffer;
strm->state = ADC_STATE_GETTYPE;
strm->length = 0;
strm->offset = 0;
strm->curr = strm->buffer;
return ADC_OK;
}
@ -94,18 +94,17 @@ int adc_decompress(adc_stream *strm)
/* Exit if needs more in bytes and none available */
int needsInput;
switch (strm->state) {
case ADC_STATE_SHORTLOOK:
case ADC_STATE_LONGLOOK:
needsInput = 0;
break;
default:
needsInput = 1;
break;
case ADC_STATE_SHORTLOOK:
case ADC_STATE_LONGLOOK:
needsInput = 0;
break;
default:
needsInput = 1;
break;
}
if (needsInput && (strm->avail_in == 0)) {
break;
}
else {
} else {
didNothing = 0;
}
@ -117,36 +116,34 @@ int adc_decompress(adc_stream *strm)
strm->next_in++;
strm->avail_in--;
if (bData & 0x80) {
strm->state = ADC_STATE_RAWDATA;
strm->state = ADC_STATE_RAWDATA;
strm->offset = 0;
strm->length = (bData & 0x7F) + 1;
}
else if (bData & 0x40) {
strm->state = ADC_STATE_LONGOP2;
} else if (bData & 0x40) {
strm->state = ADC_STATE_LONGOP2;
strm->offset = 0;
strm->length = (bData & 0x3F) + 4;
}
else {
strm->state = ADC_STATE_SHORTOP;
} else {
strm->state = ADC_STATE_SHORTOP;
strm->offset = (bData & 0x3) * 0x100;
strm->length = ((bData & 0x3C) >> 2) + 3;
}
adc_dbgmsg("adc_decompress: GETTYPE bData %x state %u offset %u length %u\n",
bData, strm->state, strm->offset, strm->length);
break;
}
case ADC_STATE_LONGOP2: {
}
case ADC_STATE_LONGOP2: {
/* Grab first offset byte */
bData = *(strm->next_in);
strm->next_in++;
strm->avail_in--;
strm->offset = bData * 0x100;
strm->state = ADC_STATE_LONGOP1;
strm->state = ADC_STATE_LONGOP1;
adc_dbgmsg("adc_decompress: LONGOP2 bData %x state %u offset %u length %u\n",
bData, strm->state, strm->offset, strm->length);
break;
}
case ADC_STATE_LONGOP1: {
}
case ADC_STATE_LONGOP1: {
/* Grab second offset byte */
bData = *(strm->next_in);
strm->next_in++;
@ -156,8 +153,8 @@ int adc_decompress(adc_stream *strm)
adc_dbgmsg("adc_decompress: LONGOP1 bData %x state %u offset %u length %u\n",
bData, strm->state, strm->offset, strm->length);
break;
}
case ADC_STATE_SHORTOP: {
}
case ADC_STATE_SHORTOP: {
/* Grab offset byte */
bData = *(strm->next_in);
strm->next_in++;
@ -167,9 +164,9 @@ int adc_decompress(adc_stream *strm)
adc_dbgmsg("adc_decompress: SHORTOP bData %x state %u offset %u length %u\n",
bData, strm->state, strm->offset, strm->length);
break;
}
}
case ADC_STATE_RAWDATA: {
case ADC_STATE_RAWDATA: {
/* Grab data */
adc_dbgmsg("adc_decompress: RAWDATA offset %u length %u\n", strm->offset, strm->length);
while ((strm->avail_in > 0) && (strm->avail_out > 0) && (strm->length > 0)) {
@ -197,20 +194,19 @@ int adc_decompress(adc_stream *strm)
strm->state = ADC_STATE_GETTYPE;
}
break;
}
}
case ADC_STATE_SHORTLOOK:
case ADC_STATE_LONGLOOK: {
case ADC_STATE_SHORTLOOK:
case ADC_STATE_LONGLOOK: {
/* Copy data */
adc_dbgmsg("adc_decompress: LOOKBACK offset %u length %u avail_in %u avail_out %u\n",
strm->offset, strm->length, strm->avail_in, strm->avail_out);
strm->offset, strm->length, strm->avail_in, strm->avail_out);
while ((strm->avail_out > 0) && (strm->length > 0)) {
/* state validation first */
if (strm->offset > 0x10000) {
cli_dbgmsg("adc_decompress: bad LOOKBACK offset %u\n", strm->offset);
return ADC_DATA_ERROR;
}
else if ((strm->state == ADC_STATE_SHORTLOOK) && (strm->offset > 0x400)) {
} else if ((strm->state == ADC_STATE_SHORTLOOK) && (strm->offset > 0x400)) {
cli_dbgmsg("adc_decompress: bad LOOKBACK offset %u\n", strm->offset);
return ADC_DATA_ERROR;
}
@ -224,8 +220,7 @@ int adc_decompress(adc_stream *strm)
}
if (strm->curr >= (strm->buffer + strm->offset)) {
bData = *(uint8_t *)(strm->curr - strm->offset);
}
else {
} else {
bData = *(uint8_t *)(strm->curr + ADC_BUFF_SIZE - strm->offset);
}
/* store to output */
@ -254,15 +249,14 @@ int adc_decompress(adc_stream *strm)
return ADC_DATA_ERROR;
}
} /* end switch */
} /* end while */
} /* end while */
/* There really isn't a terminator, just end of data */
if (didNothing && strm->avail_out) {
if (strm->state == ADC_STATE_GETTYPE) {
/* Nothing left to do */
return ADC_STREAM_END;
}
else {
} else {
/* Ended mid phrase */
cli_dbgmsg("adc_decompress: stream ended mid-phrase, state %u\n", strm->state);
return ADC_DATA_ERROR;
@ -285,10 +279,9 @@ int adc_decompressEnd(adc_stream *strm)
free(strm->buffer);
}
strm->buffered = 0;
strm->state = ADC_STATE_UNINIT;
strm->length = 0;
strm->offset = 0;
strm->state = ADC_STATE_UNINIT;
strm->length = 0;
strm->offset = 0;
return ADC_OK;
}

View file

@ -44,21 +44,21 @@ typedef struct adc_stream adc_stream;
#define ADC_BUFF_SIZE 65536
#define ADC_MEM_ERROR -1
#define ADC_DATA_ERROR -2
#define ADC_IO_ERROR -3
#define ADC_OK 0
#define ADC_STREAM_END 1
#define ADC_MEM_ERROR -1
#define ADC_DATA_ERROR -2
#define ADC_IO_ERROR -3
#define ADC_OK 0
#define ADC_STREAM_END 1
enum adc_state {
ADC_STATE_UNINIT = 0,
ADC_STATE_GETTYPE = 1,
ADC_STATE_RAWDATA = 2,
ADC_STATE_SHORTOP = 3,
ADC_STATE_LONGOP2 = 4,
ADC_STATE_LONGOP1 = 5,
ADC_STATE_UNINIT = 0,
ADC_STATE_GETTYPE = 1,
ADC_STATE_RAWDATA = 2,
ADC_STATE_SHORTOP = 3,
ADC_STATE_LONGOP2 = 4,
ADC_STATE_LONGOP1 = 5,
ADC_STATE_SHORTLOOK = 6,
ADC_STATE_LONGLOOK = 7
ADC_STATE_LONGLOOK = 7
};
/* Compression phrases

View file

@ -40,9 +40,9 @@
//#define DEBUG_APM_PARSE
#ifdef DEBUG_APM_PARSE
# define apm_parsemsg(...) cli_dbgmsg( __VA_ARGS__)
#define apm_parsemsg(...) cli_dbgmsg(__VA_ARGS__)
#else
# define apm_parsemsg(...) ;
#define apm_parsemsg(...) ;
#endif
static int apm_prtn_intxn(cli_ctx *ctx, struct apm_partition_info *aptable, size_t sectorsize, int old_school);
@ -69,8 +69,8 @@ int cli_scanapm(cli_ctx *ctx)
}
/* convert driver description map big-endian to host */
ddm.signature = be16_to_host(ddm.signature);
ddm.blockSize = be16_to_host(ddm.blockSize);
ddm.signature = be16_to_host(ddm.signature);
ddm.blockSize = be16_to_host(ddm.blockSize);
ddm.blockCount = be32_to_host(ddm.blockCount);
/* check DDM signature */
@ -113,10 +113,10 @@ int cli_scanapm(cli_ctx *ctx)
}
/* convert partition table big endian to host */
aptable.signature = be16_to_host(aptable.signature);
aptable.signature = be16_to_host(aptable.signature);
aptable.numPartitions = be32_to_host(aptable.numPartitions);
aptable.pBlockStart = be32_to_host(aptable.pBlockStart);
aptable.pBlockCount = be32_to_host(aptable.pBlockCount);
aptable.pBlockStart = be32_to_host(aptable.pBlockStart);
aptable.pBlockCount = be32_to_host(aptable.pBlockCount);
/* check the partition entry signature */
if (aptable.signature != APM_SIGNATURE) {
@ -125,9 +125,9 @@ int cli_scanapm(cli_ctx *ctx)
}
/* check if partition table partition */
if (strncmp((char*)aptable.type, "Apple_Partition_Map", 32) &&
strncmp((char*)aptable.type, "Apple_partition_map", 32) &&
strncmp((char*)aptable.type, "Apple_patition_map", 32)){
if (strncmp((char *)aptable.type, "Apple_Partition_Map", 32) &&
strncmp((char *)aptable.type, "Apple_partition_map", 32) &&
strncmp((char *)aptable.type, "Apple_patition_map", 32)) {
cli_dbgmsg("cli_scanapm: Initial Apple Partition Map partition is not detected\n");
return CL_EFORMAT;
}
@ -145,8 +145,8 @@ int cli_scanapm(cli_ctx *ctx)
/* print debugging info on partition tables */
cli_dbgmsg("APM Partition Table:\n");
cli_dbgmsg("Name: %s\n", (char*)aptable.name);
cli_dbgmsg("Type: %s\n", (char*)aptable.type);
cli_dbgmsg("Name: %s\n", (char *)aptable.name);
cli_dbgmsg("Type: %s\n", (char *)aptable.type);
cli_dbgmsg("Signature: %x\n", aptable.signature);
cli_dbgmsg("Partition Count: %u\n", aptable.numPartitions);
cli_dbgmsg("Blocks: [%u, +%u), ([%lu, +%lu))\n",
@ -157,8 +157,7 @@ int cli_scanapm(cli_ctx *ctx)
/* check engine maxpartitions limit */
if (aptable.numPartitions < ctx->engine->maxpartitions) {
max_prtns = aptable.numPartitions;
}
else {
} else {
max_prtns = ctx->engine->maxpartitions;
}
@ -172,11 +171,11 @@ int cli_scanapm(cli_ctx *ctx)
}
/* convert partition entry big endian to host */
apentry.signature = be16_to_host(apentry.signature);
apentry.reserved = be16_to_host(apentry.reserved);
apentry.signature = be16_to_host(apentry.signature);
apentry.reserved = be16_to_host(apentry.reserved);
apentry.numPartitions = be32_to_host(apentry.numPartitions);
apentry.pBlockStart = be32_to_host(apentry.pBlockStart);
apentry.pBlockCount = be32_to_host(apentry.pBlockCount);
apentry.pBlockStart = be32_to_host(apentry.pBlockStart);
apentry.pBlockCount = be32_to_host(apentry.pBlockCount);
/* check the partition entry signature */
if (aptable.signature != APM_SIGNATURE) {
@ -185,39 +184,39 @@ int cli_scanapm(cli_ctx *ctx)
}
/* check if a out-of-order partition map */
if (!strncmp((char*)apentry.type, "Apple_Partition_Map", 32) ||
!strncmp((char*)apentry.type, "Apple_partition_map", 32) ||
!strncmp((char*)apentry.type, "Apple_patition_map", 32)) {
if (!strncmp((char *)apentry.type, "Apple_Partition_Map", 32) ||
!strncmp((char *)apentry.type, "Apple_partition_map", 32) ||
!strncmp((char *)apentry.type, "Apple_patition_map", 32)) {
cli_dbgmsg("cli_scanapm: Out of order Apple Partition Map partition\n");
continue;
}
partoff = apentry.pBlockStart * sectorsize;
partoff = apentry.pBlockStart * sectorsize;
partsize = apentry.pBlockCount * sectorsize;
/* re-calculate if old_school and aligned [512 * 4 => 2048] */
if (old_school && ((i % 4) == 0)) {
if (!strncmp((char*)apentry.type, "Apple_Driver", 32) ||
!strncmp((char*)apentry.type, "Apple_Driver43", 32) ||
!strncmp((char*)apentry.type, "Apple_Driver43_CD", 32) ||
!strncmp((char*)apentry.type, "Apple_Driver_ATA", 32) ||
!strncmp((char*)apentry.type, "Apple_Driver_ATAPI", 32) ||
!strncmp((char*)apentry.type, "Apple_Patches", 32)) {
if (!strncmp((char *)apentry.type, "Apple_Driver", 32) ||
!strncmp((char *)apentry.type, "Apple_Driver43", 32) ||
!strncmp((char *)apentry.type, "Apple_Driver43_CD", 32) ||
!strncmp((char *)apentry.type, "Apple_Driver_ATA", 32) ||
!strncmp((char *)apentry.type, "Apple_Driver_ATAPI", 32) ||
!strncmp((char *)apentry.type, "Apple_Patches", 32)) {
partsize = apentry.pBlockCount * 2048;
}
}
/* check if invalid partition */
if ((partoff == 0) || (partoff+partsize > maplen)) {
if ((partoff == 0) || (partoff + partsize > maplen)) {
cli_dbgmsg("cli_scanapm: Detected invalid Apple partition entry\n");
continue;
}
/* print debugging info on partition */
cli_dbgmsg("APM Partition Entry %u:\n", i);
cli_dbgmsg("Name: %s\n", (char*)apentry.name);
cli_dbgmsg("Type: %s\n", (char*)apentry.type);
cli_dbgmsg("Name: %s\n", (char *)apentry.name);
cli_dbgmsg("Type: %s\n", (char *)apentry.type);
cli_dbgmsg("Signature: %x\n", apentry.signature);
cli_dbgmsg("Partition Count: %u\n", apentry.numPartitions);
cli_dbgmsg("Blocks: [%u, +%u), ([%lu, +%lu))\n",
@ -248,15 +247,14 @@ static int apm_prtn_intxn(cli_ctx *ctx, struct apm_partition_info *aptable, size
int ret = CL_CLEAN, tmp = CL_CLEAN;
off_t pos;
uint32_t max_prtns = 0;
int virus_found = 0;
int virus_found = 0;
prtn_intxn_list_init(&prtncheck);
/* check engine maxpartitions limit */
if (aptable->numPartitions < ctx->engine->maxpartitions) {
max_prtns = aptable->numPartitions;
}
else {
} else {
max_prtns = ctx->engine->maxpartitions;
}
@ -274,12 +272,12 @@ static int apm_prtn_intxn(cli_ctx *ctx, struct apm_partition_info *aptable, size
apentry.pBlockCount = be32_to_host(apentry.pBlockCount);
/* re-calculate if old_school and aligned [512 * 4 => 2048] */
if (old_school && ((i % 4) == 0)) {
if (!strncmp((char*)apentry.type, "Apple_Driver", 32) ||
!strncmp((char*)apentry.type, "Apple_Driver43", 32) ||
!strncmp((char*)apentry.type, "Apple_Driver43_CD", 32) ||
!strncmp((char*)apentry.type, "Apple_Driver_ATA", 32) ||
!strncmp((char*)apentry.type, "Apple_Driver_ATAPI", 32) ||
!strncmp((char*)apentry.type, "Apple_Patches", 32)) {
if (!strncmp((char *)apentry.type, "Apple_Driver", 32) ||
!strncmp((char *)apentry.type, "Apple_Driver43", 32) ||
!strncmp((char *)apentry.type, "Apple_Driver43_CD", 32) ||
!strncmp((char *)apentry.type, "Apple_Driver_ATA", 32) ||
!strncmp((char *)apentry.type, "Apple_Driver_ATAPI", 32) ||
!strncmp((char *)apentry.type, "Apple_Patches", 32)) {
apentry.pBlockCount = apentry.pBlockCount * 4;
}
@ -288,11 +286,12 @@ static int apm_prtn_intxn(cli_ctx *ctx, struct apm_partition_info *aptable, size
tmp = prtn_intxn_list_check(&prtncheck, &pitxn, apentry.pBlockStart, apentry.pBlockCount);
if (tmp != CL_CLEAN) {
if (tmp == CL_VIRUS) {
apm_parsemsg("Name: %s\n", (char*)aptable.name);
apm_parsemsg("Type: %s\n", (char*)aptable.type);
apm_parsemsg("Name: %s\n", (char *)aptable.name);
apm_parsemsg("Type: %s\n", (char *)aptable.type);
cli_dbgmsg("cli_scanapm: detected intersection with partitions "
"[%u, %u]\n", pitxn, i);
"[%u, %u]\n",
pitxn, i);
ret = cli_append_virus(ctx, PRTN_INTXN_DETECTION);
if (ret == CL_VIRUS)
virus_found = 1;
@ -308,7 +307,7 @@ static int apm_prtn_intxn(cli_ctx *ctx, struct apm_partition_info *aptable, size
pos += sectorsize;
}
leave:
leave:
prtn_intxn_list_free(&prtncheck);
if (virus_found)
return CL_VIRUS;

View file

@ -38,12 +38,12 @@
#define APM_SIGNATURE 0x504D /* partition map signature ('PM') */
/* partition flags */
#define VALID 0x00000001
#define ALLOCATED 0x00000002
#define IN_USE 0x00000004
#define BOOTABLE 0x00000008
#define READABLE 0x00000010
#define WRITEABLE 0x00000020
#define VALID 0x00000001
#define ALLOCATED 0x00000002
#define IN_USE 0x00000004
#define BOOTABLE 0x00000008
#define READABLE 0x00000010
#define WRITEABLE 0x00000020
#define POSINDEPENDENT 0x00000040
/* end of partition flags */
@ -61,20 +61,20 @@
/* 8-byte driver description entry for ddmap, big endian */
struct apm_driver_desc_entry {
uint32_t block __attribute__ ((packed));
uint16_t size __attribute__ ((packed));
uint16_t type __attribute__ ((packed));
uint32_t block __attribute__((packed));
uint16_t size __attribute__((packed));
uint16_t type __attribute__((packed));
}; //NOTE may need to be renamed
/* 512(82)-byte driver descriptor map (Block0), big endian */
struct apm_driver_desc_map {
uint16_t signature __attribute__ ((packed));
uint16_t blockSize __attribute__ ((packed));
uint32_t blockCount __attribute__ ((packed));
uint16_t deviceType __attribute__ ((packed));
uint16_t deviceID __attribute__ ((packed));
uint32_t driverData __attribute__ ((packed));
uint16_t driverCount __attribute__ ((packed));
uint16_t signature __attribute__((packed));
uint16_t blockSize __attribute__((packed));
uint32_t blockCount __attribute__((packed));
uint16_t deviceType __attribute__((packed));
uint16_t deviceID __attribute__((packed));
uint32_t driverData __attribute__((packed));
uint16_t driverCount __attribute__((packed));
struct apm_driver_desc_entry driverTable[8];
/* zeroes fill remainder of sector (430 bytes in 512 sector size) */
};
@ -84,23 +84,23 @@ struct apm_driver_desc_map {
* struct to describe their details
*/
struct apm_partition_info {
uint16_t signature __attribute__ ((packed));
uint16_t reserved __attribute__ ((packed));
uint32_t numPartitions __attribute__ ((packed));
uint32_t pBlockStart __attribute__ ((packed));
uint32_t pBlockCount __attribute__ ((packed));
uint16_t signature __attribute__((packed));
uint16_t reserved __attribute__((packed));
uint32_t numPartitions __attribute__((packed));
uint32_t pBlockStart __attribute__((packed));
uint32_t pBlockCount __attribute__((packed));
uint8_t name[32];
uint8_t type[32];
uint32_t lBlockStart __attribute__ ((packed));
uint32_t lBlockCount __attribute__ ((packed));
uint32_t flags __attribute__ ((packed));
uint32_t bootBlockStart __attribute__ ((packed));
uint32_t bootSize __attribute__ ((packed));
uint32_t bootAddr __attribute__ ((packed));
uint32_t bootAddr2 __attribute__ ((packed));
uint32_t bootEntry __attribute__ ((packed));
uint32_t bootEntry2 __attribute__ ((packed));
uint32_t bootChecksum __attribute__ ((packed));
uint32_t lBlockStart __attribute__((packed));
uint32_t lBlockCount __attribute__((packed));
uint32_t flags __attribute__((packed));
uint32_t bootBlockStart __attribute__((packed));
uint32_t bootSize __attribute__((packed));
uint32_t bootAddr __attribute__((packed));
uint32_t bootAddr2 __attribute__((packed));
uint32_t bootEntry __attribute__((packed));
uint32_t bootEntry2 __attribute__((packed));
uint32_t bootChecksum __attribute__((packed));
uint8_t processor[16];
/* zeroes fill remainder of sector (376 bytes in 512 sector size) */
};

View file

@ -33,13 +33,13 @@ void arc4_init(struct arc4_state *a, const uint8_t *key, unsigned keylength)
uint8_t j;
uint32_t *S = &a->S[0];
for (i=0; i < 256;i ++)
S[i] = i;
for (i=0,j=0; i < 256; i++) {
uint8_t tmp = S[i];
j = j + S[i] + key[i % keylength];
S[i] = S[j];
S[j] = tmp;
for (i = 0; i < 256; i++)
S[i] = i;
for (i = 0, j = 0; i < 256; i++) {
uint8_t tmp = S[i];
j = j + S[i] + key[i % keylength];
S[i] = S[j];
S[j] = tmp;
}
a->i = a->j = 0;
}
@ -50,14 +50,14 @@ void arc4_apply(struct arc4_state *s, uint8_t *data, unsigned len)
uint32_t *S = &s->S[0];
while (len-- > 0) {
uint32_t a, b;
i++;
a = S[i];
j += a;
b = S[i] = S[j];
b += a;
S[j] = a;
*data++ ^= S[b & 0xff];
uint32_t a, b;
i++;
a = S[i];
j += a;
b = S[i] = S[j];
b += a;
S[j] = a;
*data++ ^= S[b & 0xff];
}
s->i = i;

File diff suppressed because it is too large Load diff

View file

@ -28,461 +28,467 @@
#include "rebuildpe.h"
#include "aspack.h"
#define ASPACK_BLOCKS_OFFSET_212 0x57c
#define ASPACK_BLOCKS_OFFSET_OTHER 0x5d8
#define ASPACK_BLOCKS_OFFSET_242 0x5e4
#define ASPACK_BLOCKS_OFFSET_212 0x57c
#define ASPACK_BLOCKS_OFFSET_OTHER 0x5d8
#define ASPACK_BLOCKS_OFFSET_242 0x5e4
#define ASPACK_STR_INIT_MLT_OFFSET_212 0x70e
#define ASPACK_STR_INIT_MLT_OFFSET_OTHER 0x76a
#define ASPACK_STR_INIT_MLT_OFFSET_242 0x776
#define ASPACK_STR_INIT_MLT_OFFSET_212 0x70e
#define ASPACK_STR_INIT_MLT_OFFSET_OTHER 0x76a
#define ASPACK_STR_INIT_MLT_OFFSET_242 0x776
#define ASPACK_COMP_BLOCK_OFFSET_212 0x6d6
#define ASPACK_COMP_BLOCK_OFFSET_OTHER 0x732
#define ASPACK_COMP_BLOCK_OFFSET_242 0x73e
#define ASPACK_COMP_BLOCK_OFFSET_212 0x6d6
#define ASPACK_COMP_BLOCK_OFFSET_OTHER 0x732
#define ASPACK_COMP_BLOCK_OFFSET_242 0x73e
#define ASPACK_WRKBUF_OFFSET_212 0x148
#define ASPACK_WRKBUF_OFFSET_OTHER 0x13a
#define ASPACK_WRKBUF_OFFSET_242 0x148
#define ASPACK_WRKBUF_OFFSET_212 0x148
#define ASPACK_WRKBUF_OFFSET_OTHER 0x13a
#define ASPACK_WRKBUF_OFFSET_242 0x148
struct DICT_HELPER {
uint32_t *starts;
uint8_t *ends;
uint32_t size;
uint32_t *starts;
uint8_t *ends;
uint32_t size;
};
struct ASPK {
uint32_t bitpos;
uint32_t hash;
uint32_t init_array[58];
struct DICT_HELPER dict_helper[4];
uint8_t *input;
uint8_t *iend;
uint8_t *decrypt_dict;
uint32_t decarray3[4][24];
uint32_t decarray4[4][24];
int dict_ok;
uint8_t array2[758];
uint8_t array1[19];
uint32_t bitpos;
uint32_t hash;
uint32_t init_array[58];
struct DICT_HELPER dict_helper[4];
uint8_t *input;
uint8_t *iend;
uint8_t *decrypt_dict;
uint32_t decarray3[4][24];
uint32_t decarray4[4][24];
int dict_ok;
uint8_t array2[758];
uint8_t array1[19];
};
static inline int readstream(struct ASPK *stream) {
while (stream->bitpos >= 8) {
if (stream->input>=stream->iend) return 0;
stream->hash = (stream->hash << 8) | *stream->input;
stream->input++;
stream->bitpos -= 8;
}
return 1;
static inline int readstream(struct ASPK *stream)
{
while (stream->bitpos >= 8) {
if (stream->input >= stream->iend) return 0;
stream->hash = (stream->hash << 8) | *stream->input;
stream->input++;
stream->bitpos -= 8;
}
return 1;
}
static uint32_t getdec(struct ASPK *stream, uint8_t which, int *err) {
uint32_t ret;
uint8_t pos;
uint32_t *d3 = stream->decarray3[which];
uint32_t *d4 = stream->decarray4[which];
static uint32_t getdec(struct ASPK *stream, uint8_t which, int *err)
{
uint32_t ret;
uint8_t pos;
uint32_t *d3 = stream->decarray3[which];
uint32_t *d4 = stream->decarray4[which];
*err=1;
*err = 1;
if (!readstream(stream)) return 0;
if (!readstream(stream)) return 0;
ret = (stream->hash >> (8 - stream->bitpos)) & 0xfffe00;
ret = (stream->hash >> (8 - stream->bitpos)) & 0xfffe00;
if (ret < d3[8]) {
if ((ret>>16) >= 0x100) return 0;
if (!(pos=stream->dict_helper[which].ends[ret>>16]) || pos>= 24) return 0; /* 0<pos<24 */
} else {
if (ret < d3[10]) {
if (ret < d3[9]) pos = 9;
else pos = 10;
if (ret < d3[8]) {
if ((ret >> 16) >= 0x100) return 0;
if (!(pos = stream->dict_helper[which].ends[ret >> 16]) || pos >= 24) return 0; /* 0<pos<24 */
} else {
if (ret < d3[11] ) pos = 11;
else {
if (ret < d3[12]) pos = 12;
else {
if (ret < d3[13]) pos = 13;
else {
if (ret < d3[14]) pos = 14;
else pos = 15;
}
}
}
}
}
stream->bitpos += pos;
ret = ((ret - d3[pos-1]) >> (24 - pos)) + d4[pos];
if (ret >= stream->dict_helper[which].size) return 0;
ret = stream->dict_helper[which].starts[ret];
*err=0;
return ret;
}
static uint8_t build_decrypt_array(struct ASPK *stream, uint8_t* array, uint8_t which) {
uint32_t sum = 0, counter = 23, i, endoff = 0, bus[18], dict[18];
uint32_t *d3 = stream->decarray3[which];
uint32_t *d4 = stream->decarray4[which];
memset(bus,0,sizeof(bus));
memset(dict,0,sizeof(dict));
for (i = 0; i < stream->dict_helper[which].size; i++) {
/* within bounds - see comments in build_decrypt_dictionaries */
if (array[i] > 17) return 0;
bus[array[i]]++;
}
d3[0] = 0;
d4[0] = 0;
i = 0;
while (counter >= 9) { /* 0<=i<=14 */
sum += (bus[i+1] << counter);
if (sum > 0x1000000) return 0;
d3[i+1] = sum;
d4[i+1] = dict[i+1] = bus[i] + d4[i];
if (counter >= 0x10) {
uint32_t old = endoff;
endoff = d3[i+1] >> 0x10;
if (endoff-old) {
if (!CLI_ISCONTAINED(stream->dict_helper[which].ends, 0x100, stream->dict_helper[which].ends+old, endoff-old)) return 0;
memset((stream->dict_helper[which].ends + old), i+1, endoff-old);
}
if (ret < d3[10]) {
if (ret < d3[9])
pos = 9;
else
pos = 10;
} else {
if (ret < d3[11])
pos = 11;
else {
if (ret < d3[12])
pos = 12;
else {
if (ret < d3[13])
pos = 13;
else {
if (ret < d3[14])
pos = 14;
else
pos = 15;
}
}
}
}
}
i++;
counter--;
}
stream->bitpos += pos;
ret = ((ret - d3[pos - 1]) >> (24 - pos)) + d4[pos];
if (sum != 0x1000000) return 0;
if (ret >= stream->dict_helper[which].size) return 0;
ret = stream->dict_helper[which].starts[ret];
i = 0;
for (i=0; i < stream->dict_helper[which].size; i++) {
if (array[i]) { /* within bounds - see above */
if (array[i] > 17) return 0;
if (dict[array[i]]>=stream->dict_helper[which].size) return 0;
stream->dict_helper[which].starts[dict[array[i]]] = i;
dict[array[i]]++;
*err = 0;
return ret;
}
static uint8_t build_decrypt_array(struct ASPK *stream, uint8_t *array, uint8_t which)
{
uint32_t sum = 0, counter = 23, i, endoff = 0, bus[18], dict[18];
uint32_t *d3 = stream->decarray3[which];
uint32_t *d4 = stream->decarray4[which];
memset(bus, 0, sizeof(bus));
memset(dict, 0, sizeof(dict));
for (i = 0; i < stream->dict_helper[which].size; i++) {
/* within bounds - see comments in build_decrypt_dictionaries */
if (array[i] > 17) return 0;
bus[array[i]]++;
}
}
return 1;
d3[0] = 0;
d4[0] = 0;
i = 0;
while (counter >= 9) { /* 0<=i<=14 */
sum += (bus[i + 1] << counter);
if (sum > 0x1000000) return 0;
d3[i + 1] = sum;
d4[i + 1] = dict[i + 1] = bus[i] + d4[i];
if (counter >= 0x10) {
uint32_t old = endoff;
endoff = d3[i + 1] >> 0x10;
if (endoff - old) {
if (!CLI_ISCONTAINED(stream->dict_helper[which].ends, 0x100, stream->dict_helper[which].ends + old, endoff - old)) return 0;
memset((stream->dict_helper[which].ends + old), i + 1, endoff - old);
}
}
i++;
counter--;
}
if (sum != 0x1000000) return 0;
i = 0;
for (i = 0; i < stream->dict_helper[which].size; i++) {
if (array[i]) { /* within bounds - see above */
if (array[i] > 17) return 0;
if (dict[array[i]] >= stream->dict_helper[which].size) return 0;
stream->dict_helper[which].starts[dict[array[i]]] = i;
dict[array[i]]++;
}
}
return 1;
}
static uint8_t getbits(struct ASPK *stream, uint32_t num, int *err)
{
uint8_t retvalue;
static uint8_t getbits(struct ASPK *stream, uint32_t num, int *err) {
uint8_t retvalue;
if (!readstream(stream)) {
*err = 1;
return 0;
}
if (!readstream(stream)) {
*err=1;
return 0;
}
*err = 0;
retvalue = ((stream->hash >> (8 - stream->bitpos)) & 0xffffff) >> (24 - num);
stream->bitpos += num;
*err = 0;
retvalue = ((stream->hash >> (8 - stream->bitpos))&0xffffff) >> (24 - num);
stream->bitpos += num;
return retvalue;
return retvalue;
}
static int build_decrypt_dictionaries(struct ASPK *stream)
{
unsigned int counter;
uint32_t ret;
int oob;
static int build_decrypt_dictionaries(struct ASPK *stream) {
unsigned int counter;
uint32_t ret;
int oob;
if (!getbits(stream, 1, &oob)) memset(stream->decrypt_dict, 0, 0x2f5);
if (oob) return 0;
for (counter = 0; counter < 19; counter++) {
stream->array1[counter]=getbits(stream, 4, &oob);
if (!getbits(stream, 1, &oob)) memset(stream->decrypt_dict, 0, 0x2f5);
if (oob) return 0;
}
if (!build_decrypt_array(stream, stream->array1, 3)) return 0; /* array1[19] - [3].size=19 */
counter = 0;
while (counter < 757) {
ret = getdec(stream, 3, &oob);
if (oob) return 0;
if (ret >= 16) {
if (ret != 16) {
if (ret == 17) ret = 3 + getbits(stream, 3, &oob);
else ret = 11 + getbits(stream, 7, &oob);
if (oob) return 0;
while (ret) {
if (counter >= 757) break;
stream->array2[1+counter] = 0;
counter++;
ret--;
}
} else {
ret = 3 + getbits(stream, 2, &oob);
if (oob) return 0;
while (ret) {
if (counter >= 757) break;
stream->array2[1+counter] = stream->array2[counter];
counter++;
ret--;
}
}
} else {
stream->array2[1+counter] = (stream->decrypt_dict[counter] + ret) & 0xF;
counter++;
for (counter = 0; counter < 19; counter++) {
stream->array1[counter] = getbits(stream, 4, &oob);
if (oob) return 0;
}
}
if (!build_decrypt_array(stream, &stream->array2[1], 0) /* array2[758-1=757] - [0].size=721 */ || !build_decrypt_array(stream, &stream->array2[722], 1) /* array2[758-722=36] - [1].size=28 */ || !build_decrypt_array(stream, &stream->array2[750], 2) /* array2[758-750=8] - [2].size=8 */ ) return 0;
if (!build_decrypt_array(stream, stream->array1, 3)) return 0; /* array1[19] - [3].size=19 */
stream->dict_ok = 0;
for (counter = 0; counter < 8; counter++) {
if (stream->array2[750+counter] != 3) {
stream->dict_ok = 1;
break;
counter = 0;
while (counter < 757) {
ret = getdec(stream, 3, &oob);
if (oob) return 0;
if (ret >= 16) {
if (ret != 16) {
if (ret == 17)
ret = 3 + getbits(stream, 3, &oob);
else
ret = 11 + getbits(stream, 7, &oob);
if (oob) return 0;
while (ret) {
if (counter >= 757) break;
stream->array2[1 + counter] = 0;
counter++;
ret--;
}
} else {
ret = 3 + getbits(stream, 2, &oob);
if (oob) return 0;
while (ret) {
if (counter >= 757) break;
stream->array2[1 + counter] = stream->array2[counter];
counter++;
ret--;
}
}
} else {
stream->array2[1 + counter] = (stream->decrypt_dict[counter] + ret) & 0xF;
counter++;
}
}
}
memcpy(stream->decrypt_dict,&stream->array2[1],757);
if (!build_decrypt_array(stream, &stream->array2[1], 0) /* array2[758-1=757] - [0].size=721 */ || !build_decrypt_array(stream, &stream->array2[722], 1) /* array2[758-722=36] - [1].size=28 */ || !build_decrypt_array(stream, &stream->array2[750], 2) /* array2[758-750=8] - [2].size=8 */) return 0;
return 1;
stream->dict_ok = 0;
for (counter = 0; counter < 8; counter++) {
if (stream->array2[750 + counter] != 3) {
stream->dict_ok = 1;
break;
}
}
memcpy(stream->decrypt_dict, &stream->array2[1], 757);
return 1;
}
static int decrypt(struct ASPK *stream, uint8_t *stuff, uint32_t size, uint8_t *output)
{
/* ep+6d6 -> ep+748 = 0x72*/
uint32_t gen, backsize, backbytes, useold, counter = 0;
uint32_t hist[4] = {0, 0, 0, 0};
int oob;
static int decrypt(struct ASPK *stream, uint8_t *stuff, uint32_t size, uint8_t *output) {
/* ep+6d6 -> ep+748 = 0x72*/
uint32_t gen, backsize, backbytes, useold, counter = 0;
uint32_t hist[4]={0,0,0,0};
int oob;
cli_dbgmsg("Aspack: decrypt size:%x\n", size);
while (counter < size) {
gen = getdec(stream, 0, &oob);
if (oob) return 0;
if (gen < 256) { /* implied within bounds */
output[counter] = (uint8_t)gen;
counter++;
continue;
}
if (gen >= 720) {
if (!build_decrypt_dictionaries(stream)) return 0;
continue;
}
if ((backbytes = (gen - 256) >> 3) >= 58) return 0; /* checks init_array + stuff */
backsize = ((gen - 256) & 7) + 2;
if ((backsize - 2) == 7) {
uint8_t hlp;
gen = getdec(stream, 1, &oob);
if (oob || gen >= 0x56) return 0;
hlp = stuff[gen + 0x1c];
if (!readstream(stream)) return 0;
backsize += stuff[gen] + (((stream->hash >> (8 - stream->bitpos)) & 0xffffff) >> (0x18 - hlp));
stream->bitpos += hlp;
}
cli_dbgmsg("Aspack: decrypt size:%x\n", size);
while (counter < size) {
gen = getdec(stream, 0, &oob);
if (oob) return 0;
if (gen < 256) { /* implied within bounds */
output[counter] = (uint8_t)gen;
counter++;
continue;
}
if (gen >= 720) {
if (!build_decrypt_dictionaries(stream)) return 0;
continue;
}
if ((backbytes = (gen - 256) >> 3)>=58) return 0; /* checks init_array + stuff */
backsize = ((gen - 256) & 7) + 2;
if ((backsize-2)==7) {
uint8_t hlp;
gen = getdec(stream, 1, &oob);
if (oob || gen>=0x56) return 0;
hlp = stuff[gen + 0x1c];
if (!readstream(stream)) return 0;
backsize += stuff[gen] + (( (stream->hash >> (8 - stream->bitpos)) & 0xffffff ) >> (0x18 - hlp));
stream->bitpos += hlp;
useold = stream->init_array[backbytes];
gen = stuff[backbytes + 0x38];
if (!stream->dict_ok || gen < 3) {
if (!readstream(stream)) return 0;
useold += ((stream->hash >> (8 - stream->bitpos)) & 0xffffff) >> (24 - gen);
stream->bitpos += gen;
} else {
gen -= 3;
if (!readstream(stream)) return 0;
useold += ((((stream->hash >> (8 - stream->bitpos)) & 0xffffff) >> (24 - gen)) * 8);
stream->bitpos += gen;
useold += getdec(stream, 2, &oob);
if (oob) return 0;
}
if (useold < 3) {
backbytes = hist[useold];
if (useold != 0) {
hist[useold] = hist[0];
hist[0] = backbytes;
}
} else {
hist[2] = hist[1];
hist[1] = hist[0];
hist[0] = backbytes = useold - 3;
}
backbytes++;
if (!backbytes || backbytes > counter || backsize > size - counter) return 0;
while (backsize--) {
output[counter] = output[counter - backbytes];
counter++;
}
}
useold = stream->init_array[backbytes];
gen = stuff[backbytes + 0x38];
if (!stream->dict_ok || gen < 3) {
if (!readstream(stream)) return 0;
useold += ((stream->hash >> ( 8 - stream->bitpos) ) & 0xffffff) >> (24 - gen);
stream->bitpos += gen;
} else {
gen -= 3;
if (!readstream(stream)) return 0;
useold += ((((stream->hash >> ( 8 - stream->bitpos)) & 0xffffff) >> (24 - gen)) * 8);
stream->bitpos += gen;
useold += getdec(stream, 2, &oob);
if (oob) return 0;
}
if (useold < 3) {
backbytes = hist[useold];
if (useold != 0) {
hist[useold] = hist[0];
hist[0] = backbytes;
}
} else {
hist[2] = hist[1];
hist[1] = hist[0];
hist[0] = backbytes = useold-3;
}
backbytes++;
if (!backbytes || backbytes>counter || backsize>size-counter) return 0;
while (backsize--) {
output[counter] = output[counter-backbytes];
counter++;
}
}
return 1;
return 1;
}
static int decomp_block(struct ASPK *stream, uint32_t size, uint8_t *stuff, uint8_t *output) {
memset(stream->decarray3,0,sizeof(stream->decarray3));
memset(stream->decarray4,0,sizeof(stream->decarray4));
memset(stream->decrypt_dict, 0, 757);
stream->bitpos = 0x20;
if (!build_decrypt_dictionaries(stream)) return 0;
return decrypt(stream, stuff, size, output);
static int decomp_block(struct ASPK *stream, uint32_t size, uint8_t *stuff, uint8_t *output)
{
memset(stream->decarray3, 0, sizeof(stream->decarray3));
memset(stream->decarray4, 0, sizeof(stream->decarray4));
memset(stream->decrypt_dict, 0, 757);
stream->bitpos = 0x20;
if (!build_decrypt_dictionaries(stream)) return 0;
return decrypt(stream, stuff, size, output);
}
#define INIT_DICT_HELPER(n,sz) \
stream.dict_helper[n].starts = (uint32_t *)wrkbuf; \
stream.dict_helper[n].ends = &wrkbuf[sz * sizeof(uint32_t)]; \
stream.dict_helper[n].size = sz; \
wrkbuf = &wrkbuf[sz * sizeof(uint32_t) + 0x100];
#define INIT_DICT_HELPER(n, sz) \
stream.dict_helper[n].starts = (uint32_t *)wrkbuf; \
stream.dict_helper[n].ends = &wrkbuf[sz * sizeof(uint32_t)]; \
stream.dict_helper[n].size = sz; \
wrkbuf = &wrkbuf[sz * sizeof(uint32_t) + 0x100];
int unaspack(uint8_t *image, unsigned int size, struct cli_exe_section *sections, uint16_t sectcount, uint32_t ep, uint32_t base, int f, aspack_version_t version)
{
struct ASPK stream;
uint32_t i=0, j=0;
uint8_t *blocks = NULL, *wrkbuf;
uint32_t block_rva = 1, block_size;
struct cli_exe_section *outsects;
struct ASPK stream;
uint32_t i = 0, j = 0;
uint8_t *blocks = NULL, *wrkbuf;
uint32_t block_rva = 1, block_size;
struct cli_exe_section *outsects;
uint32_t blocks_offset, stream_init_multiplier_offset, comp_block_offset, wrkbuf_offset;
uint32_t blocks_offset, stream_init_multiplier_offset, comp_block_offset, wrkbuf_offset;
switch (version) {
case ASPACK_VER_212:
cli_dbgmsg("Aspack: Attempting to unpack Aspack 2.12.\n");
blocks_offset = ASPACK_BLOCKS_OFFSET_212;
stream_init_multiplier_offset = ASPACK_STR_INIT_MLT_OFFSET_212;
comp_block_offset = ASPACK_COMP_BLOCK_OFFSET_212;
wrkbuf_offset = ASPACK_WRKBUF_OFFSET_212;
break;
case ASPACK_VER_OTHER:
cli_dbgmsg("Aspack: Attempting to unpack Aspack >2.12, <2.42.\n");
blocks_offset = ASPACK_BLOCKS_OFFSET_OTHER;
stream_init_multiplier_offset = ASPACK_STR_INIT_MLT_OFFSET_OTHER;
comp_block_offset = ASPACK_COMP_BLOCK_OFFSET_OTHER;
wrkbuf_offset = ASPACK_WRKBUF_OFFSET_OTHER;
break;
case ASPACK_VER_242:
cli_dbgmsg("Aspack: Attempting to unpack Aspack 2.42.\n");
blocks_offset = ASPACK_BLOCKS_OFFSET_242;
stream_init_multiplier_offset = ASPACK_STR_INIT_MLT_OFFSET_242;
comp_block_offset = ASPACK_COMP_BLOCK_OFFSET_242;
wrkbuf_offset = ASPACK_WRKBUF_OFFSET_242;
break;
default:
cli_dbgmsg("Aspack: Unexpected/Unknown version number.\n");
return 0;
}
blocks = image+ep+blocks_offset;
if (!(wrkbuf = cli_calloc(0x1800, sizeof(uint8_t)))) {
cli_dbgmsg("Aspack: Unable to allocate dictionary\n");
return 0;
}
INIT_DICT_HELPER(0, 721); /* dictionary -> dictionary + b44 */
INIT_DICT_HELPER(1, 28); /* dictionary + c44 -> dictionary + cb4 */
INIT_DICT_HELPER(2, 8); /* dictionary + db4 -> dictionary + dd4 */
INIT_DICT_HELPER(3, 19); /* dictionary + ed4 -> dictionary + f20 */
stream.decrypt_dict = wrkbuf;
stream.hash = 0x10000;
for (i = 0; i < 58; i++) {
stream.init_array[i] = j;
j += ( 1 << image[ep+i+stream_init_multiplier_offset]); /* boundchecked in pe.c */
}
memset(stream.array1,0,sizeof(stream.array1));
memset(stream.array2,0,sizeof(stream.array2));
i=0;
while (CLI_ISCONTAINED(image, size, blocks, 8) && (block_rva = cli_readint32(blocks)) && (block_size = cli_readint32(blocks+4)) && CLI_ISCONTAINED(image, size, image+block_rva, block_size)) {
cli_dbgmsg("Aspack: unpacking block rva:%x - sz:%x\n", block_rva, block_size);
wrkbuf = (uint8_t *)cli_calloc(block_size+0x10e, sizeof(uint8_t));
if (!wrkbuf) {
cli_dbgmsg("Aspack: Null work buff\n");
break;
switch (version) {
case ASPACK_VER_212:
cli_dbgmsg("Aspack: Attempting to unpack Aspack 2.12.\n");
blocks_offset = ASPACK_BLOCKS_OFFSET_212;
stream_init_multiplier_offset = ASPACK_STR_INIT_MLT_OFFSET_212;
comp_block_offset = ASPACK_COMP_BLOCK_OFFSET_212;
wrkbuf_offset = ASPACK_WRKBUF_OFFSET_212;
break;
case ASPACK_VER_OTHER:
cli_dbgmsg("Aspack: Attempting to unpack Aspack >2.12, <2.42.\n");
blocks_offset = ASPACK_BLOCKS_OFFSET_OTHER;
stream_init_multiplier_offset = ASPACK_STR_INIT_MLT_OFFSET_OTHER;
comp_block_offset = ASPACK_COMP_BLOCK_OFFSET_OTHER;
wrkbuf_offset = ASPACK_WRKBUF_OFFSET_OTHER;
break;
case ASPACK_VER_242:
cli_dbgmsg("Aspack: Attempting to unpack Aspack 2.42.\n");
blocks_offset = ASPACK_BLOCKS_OFFSET_242;
stream_init_multiplier_offset = ASPACK_STR_INIT_MLT_OFFSET_242;
comp_block_offset = ASPACK_COMP_BLOCK_OFFSET_242;
wrkbuf_offset = ASPACK_WRKBUF_OFFSET_242;
break;
default:
cli_dbgmsg("Aspack: Unexpected/Unknown version number.\n");
return 0;
}
stream.input = wrkbuf;
stream.iend = &wrkbuf[block_size+0x10e];
memcpy(wrkbuf, image + block_rva, block_size);
blocks = image + ep + blocks_offset;
if (!decomp_block(&stream, block_size, &image[ep+comp_block_offset], image + block_rva)) {
cli_dbgmsg("Aspack: decomp_block failed\n");
free(wrkbuf);
break;
if (!(wrkbuf = cli_calloc(0x1800, sizeof(uint8_t)))) {
cli_dbgmsg("Aspack: Unable to allocate dictionary\n");
return 0;
}
else
cli_dbgmsg("Aspack: decomp block succeed\n");
free(wrkbuf);
INIT_DICT_HELPER(0, 721); /* dictionary -> dictionary + b44 */
INIT_DICT_HELPER(1, 28); /* dictionary + c44 -> dictionary + cb4 */
INIT_DICT_HELPER(2, 8); /* dictionary + db4 -> dictionary + dd4 */
INIT_DICT_HELPER(3, 19); /* dictionary + ed4 -> dictionary + f20 */
stream.decrypt_dict = wrkbuf;
if (i==0 && block_size>7) { /* first sect j/c unrolling */
while (i < block_size - 6) {
uint8_t curbyte = image[block_rva+i];
if (curbyte == 0xe8 || curbyte == 0xe9) {
wrkbuf = &image[block_rva+i+1];
if (*wrkbuf == image[ep+wrkbuf_offset]) {
uint32_t target = cli_readint32(wrkbuf) & 0xffffff00;
CLI_ROL(target, 0x18);
cli_writeint32(wrkbuf, target - i);
i+=4;
}
stream.hash = 0x10000;
for (i = 0; i < 58; i++) {
stream.init_array[i] = j;
j += (1 << image[ep + i + stream_init_multiplier_offset]); /* boundchecked in pe.c */
}
memset(stream.array1, 0, sizeof(stream.array1));
memset(stream.array2, 0, sizeof(stream.array2));
i = 0;
while (CLI_ISCONTAINED(image, size, blocks, 8) && (block_rva = cli_readint32(blocks)) && (block_size = cli_readint32(blocks + 4)) && CLI_ISCONTAINED(image, size, image + block_rva, block_size)) {
cli_dbgmsg("Aspack: unpacking block rva:%x - sz:%x\n", block_rva, block_size);
wrkbuf = (uint8_t *)cli_calloc(block_size + 0x10e, sizeof(uint8_t));
if (!wrkbuf) {
cli_dbgmsg("Aspack: Null work buff\n");
break;
}
stream.input = wrkbuf;
stream.iend = &wrkbuf[block_size + 0x10e];
memcpy(wrkbuf, image + block_rva, block_size);
if (!decomp_block(&stream, block_size, &image[ep + comp_block_offset], image + block_rva)) {
cli_dbgmsg("Aspack: decomp_block failed\n");
free(wrkbuf);
break;
} else
cli_dbgmsg("Aspack: decomp block succeed\n");
free(wrkbuf);
if (i == 0 && block_size > 7) { /* first sect j/c unrolling */
while (i < block_size - 6) {
uint8_t curbyte = image[block_rva + i];
if (curbyte == 0xe8 || curbyte == 0xe9) {
wrkbuf = &image[block_rva + i + 1];
if (*wrkbuf == image[ep + wrkbuf_offset]) {
uint32_t target = cli_readint32(wrkbuf) & 0xffffff00;
CLI_ROL(target, 0x18);
cli_writeint32(wrkbuf, target - i);
i += 4;
}
}
i++;
}
}
if (version == ASPACK_VER_212) {
blocks += 8;
} else {
blocks += 12;
block_size = cli_readint32(blocks + 4);
while (!((block_size + 0x10e) & 0xffffffff)) {
blocks += 12;
block_size = cli_readint32(blocks + 4);
}
}
i++;
}
}
if (version == ASPACK_VER_212) {
blocks+=8;
cli_dbgmsg("Aspack: leaving loop all uncompressed\n");
free(stream.dict_helper[0].starts);
if (block_rva) {
cli_dbgmsg("Aspack: unpacking failure\n");
return 0;
}
if (sectcount > 2 && ep == sections[sectcount - 2].rva && !sections[sectcount - 1].rsz) {
sectcount -= 2;
}
if (!(outsects = cli_malloc(sizeof(struct cli_exe_section) * sectcount))) {
cli_dbgmsg("Aspack: OOM - rebuild failed\n");
cli_writen(f, image, size);
return 1; /* No whatsoheader - won't infloop in pe.c */
}
memcpy(outsects, sections, sizeof(struct cli_exe_section) * sectcount);
for (i = 0; i < sectcount; i++) {
outsects[i].raw = outsects[i].rva;
outsects[i].rsz = outsects[i].vsz;
}
if (!cli_rebuildpe((char *)image, outsects, sectcount, base, cli_readint32(image + ep + 0x39b), 0, 0, f)) {
cli_dbgmsg("Aspack: rebuild failed\n");
cli_writen(f, image, size);
} else {
blocks += 12;
block_size = cli_readint32(blocks+4);
while (!((block_size +0x10e) & 0xffffffff))
{
blocks += 12;
block_size = cli_readint32(blocks+4);
}
cli_dbgmsg("Aspack: successfully rebuilt\n");
}
}
cli_dbgmsg("Aspack: leaving loop all uncompressed\n");
free(stream.dict_helper[0].starts);
if (block_rva) {
cli_dbgmsg("Aspack: unpacking failure\n");
return 0;
}
if(sectcount>2 && ep == sections[sectcount-2].rva && !sections[sectcount-1].rsz) {
sectcount-=2;
}
if(!(outsects=cli_malloc(sizeof(struct cli_exe_section)*sectcount))) {
cli_dbgmsg("Aspack: OOM - rebuild failed\n");
cli_writen(f, image, size);
return 1; /* No whatsoheader - won't infloop in pe.c */
}
memcpy(outsects, sections, sizeof(struct cli_exe_section)*sectcount);
for(i=0; i<sectcount; i++) {
outsects[i].raw=outsects[i].rva;
outsects[i].rsz=outsects[i].vsz;
}
if (!cli_rebuildpe((char *)image, outsects, sectcount, base, cli_readint32(image + ep + 0x39b), 0, 0, f)) {
cli_dbgmsg("Aspack: rebuild failed\n");
cli_writen(f, image, size);
} else {
cli_dbgmsg("Aspack: successfully rebuilt\n");
}
free(outsects);
return 1;
free(outsects);
return 1;
}

View file

@ -25,16 +25,16 @@
#include "cltypes.h"
#include "execs.h"
#define ASPACK_EP_OFFSET_212 (58+0x70e)
#define ASPACK_EP_OFFSET_OTHER (58+0x76a)
#define ASPACK_EP_OFFSET_242 (58+0x776)
#define ASPACK_EP_OFFSET_212 (58 + 0x70e)
#define ASPACK_EP_OFFSET_OTHER (58 + 0x76a)
#define ASPACK_EP_OFFSET_242 (58 + 0x776)
#define ASPACK_EPBUFF_OFFSET_212 (0x3b9)
#define ASPACK_EPBUFF_OFFSET_OTHER (0x41f)
#define ASPACK_EPBUFF_OFFSET_242 (0x42B)
#define ASPACK_EPBUFF_OFFSET_212 (0x3b9)
#define ASPACK_EPBUFF_OFFSET_OTHER (0x41f)
#define ASPACK_EPBUFF_OFFSET_242 (0x42B)
typedef enum aspack_version_tag {
ASPACK_VER_NONE=0,
ASPACK_VER_NONE = 0,
ASPACK_VER_212,
ASPACK_VER_OTHER,
ASPACK_VER_242

File diff suppressed because it is too large Load diff

View file

@ -6,19 +6,19 @@
#include "bignum_fast.h"
typedef fp_int mp_int;
#define mp_cmp fp_cmp
#define mp_toradix_n(a,b,c,d) fp_toradix_n(a,b,c,d)
#define mp_toradix_n(a, b, c, d) fp_toradix_n(a, b, c, d)
#define mp_init(a) (fp_init(a), 0)
#define mp_add fp_add
#define mp_init_multi(a,b,c,d) (mp_init(a), mp_init(b), mp_init(c), 0)
#define mp_init_multi(a, b, c, d) (mp_init(a), mp_init(b), mp_init(c), 0)
#define mp_read_unsigned_bin(a,b,c) (fp_read_unsigned_bin(a, b, c), 0)
#define mp_read_unsigned_bin(a, b, c) (fp_read_unsigned_bin(a, b, c), 0)
#define mp_div fp_div
#define mp_clear_multi(...)
#define mp_copy(a,b) (fp_copy(a,b), 0)
#define mp_copy(a, b) (fp_copy(a, b), 0)
#define mp_unsigned_bin_size fp_unsigned_bin_size
#define mp_to_unsigned_bin(a,b) (fp_to_unsigned_bin(a,b), 0)
#define mp_to_unsigned_bin(a, b) (fp_to_unsigned_bin(a, b), 0)
#define mp_read_radix fp_read_radix
#define mp_exptmod fp_exptmod
#define mp_get_int(a) ((a)->used > 0 ? (a)->dp[0] : 0)

View file

@ -31,11 +31,11 @@
#include <limits.h>
#ifndef MIN
#define MIN(x,y) ((x)<(y)?(x):(y))
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#endif
#ifndef MAX
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#endif
/* externally define this symbol to ignore the default settings, useful for changing the build from the make process */
@ -103,212 +103,211 @@
/* autodetect x86-64 and make sure we are using 64-bit digits with x86-64 asm */
#if defined(__x86_64__)
#if defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM)
#error x86-64 detected, x86-32/SSE2/ARM optimizations are not valid!
#endif
#if !defined(TFM_X86_64) && !defined(TFM_NO_ASM)
#define TFM_X86_64
#endif
#if defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM)
#error x86-64 detected, x86-32/SSE2/ARM optimizations are not valid!
#endif
#if !defined(TFM_X86_64) && !defined(TFM_NO_ASM)
#define TFM_X86_64
#endif
#endif
#if defined(TFM_X86_64)
#if !defined(FP_64BIT)
#define FP_64BIT
#endif
#if !defined(FP_64BIT)
#define FP_64BIT
#endif
#endif
/* try to detect x86-32 */
#if defined(__i386__) && !defined(TFM_SSE2)
#if defined(TFM_X86_64) || defined(TFM_ARM)
#error x86-32 detected, x86-64/ARM optimizations are not valid!
#endif
#if !defined(TFM_X86) && !defined(TFM_NO_ASM)
#define TFM_X86
#endif
#if defined(TFM_X86_64) || defined(TFM_ARM)
#error x86-32 detected, x86-64/ARM optimizations are not valid!
#endif
#if !defined(TFM_X86) && !defined(TFM_NO_ASM)
#define TFM_X86
#endif
#endif
/* make sure we're 32-bit for x86-32/sse/arm/ppc32 */
#if (defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM) || defined(TFM_PPC32)) && defined(FP_64BIT)
#warning x86-32, SSE2 and ARM, PPC32 optimizations require 32-bit digits (undefining)
#undef FP_64BIT
#warning x86-32, SSE2 and ARM, PPC32 optimizations require 32-bit digits (undefining)
#undef FP_64BIT
#endif
/* multi asms? */
#ifdef TFM_X86
#define TFM_ASM
#define TFM_ASM
#endif
#ifdef TFM_X86_64
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#endif
#ifdef TFM_SSE2
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#endif
#ifdef TFM_ARM
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#endif
#ifdef TFM_PPC32
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#endif
#ifdef TFM_PPC64
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#endif
#ifdef TFM_AVR32
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#ifdef TFM_ASM
#error TFM_ASM already defined!
#endif
#define TFM_ASM
#endif
/* we want no asm? */
#ifdef TFM_NO_ASM
#undef TFM_X86
#undef TFM_X86_64
#undef TFM_SSE2
#undef TFM_ARM
#undef TFM_PPC32
#undef TFM_PPC64
#undef TFM_AVR32
#undef TFM_ASM
#undef TFM_X86
#undef TFM_X86_64
#undef TFM_SSE2
#undef TFM_ARM
#undef TFM_PPC32
#undef TFM_PPC64
#undef TFM_AVR32
#undef TFM_ASM
#endif
/* ECC helpers */
#ifdef TFM_ECC192
#ifdef FP_64BIT
#define TFM_MUL3
#define TFM_SQR3
#else
#define TFM_MUL6
#define TFM_SQR6
#endif
#ifdef FP_64BIT
#define TFM_MUL3
#define TFM_SQR3
#else
#define TFM_MUL6
#define TFM_SQR6
#endif
#endif
#ifdef TFM_ECC224
#ifdef FP_64BIT
#define TFM_MUL4
#define TFM_SQR4
#else
#define TFM_MUL7
#define TFM_SQR7
#endif
#ifdef FP_64BIT
#define TFM_MUL4
#define TFM_SQR4
#else
#define TFM_MUL7
#define TFM_SQR7
#endif
#endif
#ifdef TFM_ECC256
#ifdef FP_64BIT
#define TFM_MUL4
#define TFM_SQR4
#else
#define TFM_MUL8
#define TFM_SQR8
#endif
#ifdef FP_64BIT
#define TFM_MUL4
#define TFM_SQR4
#else
#define TFM_MUL8
#define TFM_SQR8
#endif
#endif
#ifdef TFM_ECC384
#ifdef FP_64BIT
#define TFM_MUL6
#define TFM_SQR6
#else
#define TFM_MUL12
#define TFM_SQR12
#endif
#ifdef FP_64BIT
#define TFM_MUL6
#define TFM_SQR6
#else
#define TFM_MUL12
#define TFM_SQR12
#endif
#endif
#ifdef TFM_ECC521
#ifdef FP_64BIT
#define TFM_MUL9
#define TFM_SQR9
#else
#define TFM_MUL17
#define TFM_SQR17
#endif
#ifdef FP_64BIT
#define TFM_MUL9
#define TFM_SQR9
#else
#define TFM_MUL17
#define TFM_SQR17
#endif
#endif
/* some default configurations.
*/
#if defined(FP_64BIT)
/* for GCC only on supported platforms */
/* for GCC only on supported platforms */
#ifndef CRYPT
typedef unsigned long ulong64;
typedef unsigned long ulong64;
#endif
typedef ulong64 fp_digit;
typedef unsigned long fp_word __attribute__ ((mode(TI)));
typedef ulong64 fp_digit;
typedef unsigned long fp_word __attribute__((mode(TI)));
#else
/* this is to make porting into LibTomCrypt easier :-) */
/* this is to make porting into LibTomCrypt easier :-) */
#ifndef CRYPT
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 ulong64;
typedef signed __int64 long64;
#else
typedef unsigned long long ulong64;
typedef signed long long long64;
#endif
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 ulong64;
typedef signed __int64 long64;
#else
typedef unsigned long long ulong64;
typedef signed long long long64;
#endif
/* The code requires that fp_word be twice the size of fp_digit.
#endif
/* The code requires that fp_word be twice the size of fp_digit.
* Add size-checking for special case (both long and long long are 64) */
#if (SIZEOF_LONG == 8) && (SIZEOF_LONG_LONG == 8)
typedef unsigned int fp_digit;
#else
typedef unsigned long fp_digit;
#endif
typedef ulong64 fp_word;
#if (SIZEOF_LONG == 8) && (SIZEOF_LONG_LONG == 8)
typedef unsigned int fp_digit;
#else
typedef unsigned long fp_digit;
#endif
typedef ulong64 fp_word;
#endif
/* # of digits this is */
#define DIGIT_BIT (int)((CHAR_BIT) * sizeof(fp_digit))
#define DIGIT_BIT (int)((CHAR_BIT) * sizeof(fp_digit))
/* Max size of any number in bits. Basically the largest size you will be multiplying
* should be half [or smaller] of FP_MAX_SIZE-four_digit
*
* You can externally define this or it defaults to 4096-bits [allowing multiplications upto 2048x2048 bits ]
*/
#ifndef FP_MAX_SIZE
#define FP_MAX_SIZE (8192+(8*DIGIT_BIT))
#define FP_MAX_SIZE (8192 + (8 * DIGIT_BIT))
#endif
/* will this lib work? */
#if (CHAR_BIT & 7)
#error CHAR_BIT must be a multiple of eight.
#error CHAR_BIT must be a multiple of eight.
#endif
#define FP_MASK (fp_digit)(-1)
#define FP_SIZE (FP_MAX_SIZE/DIGIT_BIT)
#define FP_MASK (fp_digit)(-1)
#define FP_SIZE (FP_MAX_SIZE / DIGIT_BIT)
/* signs */
#define FP_ZPOS 0
#define FP_NEG 1
#define FP_ZPOS 0
#define FP_NEG 1
/* return codes */
#define FP_OKAY 0
#define FP_VAL 1
#define FP_MEM 2
#define FP_OKAY 0
#define FP_VAL 1
#define FP_MEM 2
/* equalities */
#define FP_LT -1 /* less than */
#define FP_EQ 0 /* equal to */
#define FP_GT 1 /* greater than */
#define FP_LT -1 /* less than */
#define FP_EQ 0 /* equal to */
#define FP_GT 1 /* greater than */
/* replies */
#define FP_YES 1 /* yes response */
#define FP_NO 0 /* no response */
#define FP_YES 1 /* yes response */
#define FP_NO 0 /* no response */
/* a FP type */
typedef struct {
fp_digit dp[FP_SIZE];
int used,
sign;
int used,
sign;
} fp_int;
/* functions */
@ -317,27 +316,40 @@ typedef struct {
const char *fp_ident(void);
/* initialize [or zero] an fp int */
#define fp_init(a) (void)memset((a), 0, sizeof(fp_int))
#define fp_zero(a) fp_init(a)
#define fp_init(a) (void)memset((a), 0, sizeof(fp_int))
#define fp_zero(a) fp_init(a)
/* zero/even/odd ? */
#define fp_iszero(a) (((a)->used == 0) ? FP_YES : FP_NO)
#define fp_iseven(a) (((a)->used >= 0 && (((a)->dp[0] & 1) == 0)) ? FP_YES : FP_NO)
#define fp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? FP_YES : FP_NO)
#define fp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? FP_YES : FP_NO)
/* set to a small digit */
void fp_set(fp_int *a, fp_digit b);
/* copy from a to b */
#define fp_copy(a, b) (void)(((a) != (b)) && memcpy((b), (a), sizeof(fp_int)))
#define fp_copy(a, b) (void)(((a) != (b)) && memcpy((b), (a), sizeof(fp_int)))
#define fp_init_copy(a, b) fp_copy(b, a)
/* clamp digits */
#define fp_clamp(a) { while ((a)->used && (a)->dp[(a)->used-1] == 0) --((a)->used); (a)->sign = (a)->used ? (a)->sign : FP_ZPOS; }
#define fp_clamp(a) \
{ \
while ((a)->used && (a)->dp[(a)->used - 1] == 0) --((a)->used); \
(a)->sign = (a)->used ? (a)->sign : FP_ZPOS; \
}
/* negate and absolute */
#define fp_neg(a, b) { fp_copy(a, b); (b)->sign ^= 1; fp_clamp(b); }
#define fp_abs(a, b) { fp_copy(a, b); (b)->sign = 0; }
#define fp_neg(a, b) \
{ \
fp_copy(a, b); \
(b)->sign ^= 1; \
fp_clamp(b); \
}
#define fp_abs(a, b) \
{ \
fp_copy(a, b); \
(b)->sign = 0; \
}
/* right shift x digits */
void fp_rshd(fp_int *a, int x);
@ -355,7 +367,7 @@ int fp_cmp_mag(fp_int *a, fp_int *b);
void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d);
void fp_mod_2d(fp_int *a, int b, fp_int *c);
void fp_mul_2d(fp_int *a, int b, fp_int *c);
void fp_2expt (fp_int *a, int b);
void fp_2expt(fp_int *a, int b);
void fp_mul_2(fp_int *a, fp_int *c);
void fp_div_2(fp_int *a, fp_int *c);
@ -437,21 +449,21 @@ int fp_exptmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
/* primality stuff */
/* perform a Miller-Rabin test of a to the base b and store result in "result" */
void fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result);
void fp_prime_miller_rabin(fp_int *a, fp_int *b, int *result);
/* 256 trial divisions + 8 Miller-Rabins, returns FP_YES if probable prime */
int fp_isprime(fp_int *a);
/* Primality generation flags */
#define TFM_PRIME_BBS 0x0001 /* BBS style prime */
#define TFM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */
#define TFM_PRIME_BBS 0x0001 /* BBS style prime */
#define TFM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */
#define TFM_PRIME_2MSB_OFF 0x0004 /* force 2nd MSB to 0 */
#define TFM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */
#define TFM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */
/* callback for fp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int tfm_prime_callback(unsigned char *dst, int len, void *dat);
#define fp_prime_random(a, t, size, bbs, cb, dat) fp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?TFM_PRIME_BBS:0, cb, dat)
#define fp_prime_random(a, t, size, bbs, cb, dat) fp_prime_random_ex(a, t, ((size)*8) + 1, (bbs == 1) ? TFM_PRIME_BBS : 0, cb, dat)
int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback cb, void *dat);
@ -468,8 +480,7 @@ void fp_to_signed_bin(fp_int *a, unsigned char *b);
int fp_read_radix(fp_int *a, const char *str, int radix);
int fp_toradix(fp_int *a, char *str, int radix);
int fp_toradix_n(fp_int * a, char *str, int radix, int maxlen);
int fp_toradix_n(fp_int *a, char *str, int radix, int maxlen);
/* VARIOUS LOW LEVEL STUFFS */
void s_fp_add(fp_int *a, fp_int *b, fp_int *c);
@ -579,7 +590,6 @@ extern const char *fp_s_rmap;
#endif
/* $Source: /cvs/libtom/tomsfastmath/src/headers/tfm.h,v $ */
/* $Revision: 1.3 $ */
/* $Date: 2007/02/27 02:38:44 $ */

View file

@ -33,7 +33,6 @@
#include "fmap.h"
#include "binhex.h"
// clang-format off
static const uint8_t hqxtbl[] = {
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f */
@ -50,220 +49,225 @@ static const uint8_t hqxtbl[] = {
#define BH_FLUSH_SZ (BUFSIZ - 256)
int cli_binhex(cli_ctx *ctx) {
fmap_t *map = *ctx->fmap;
int cli_binhex(cli_ctx *ctx)
{
fmap_t *map = *ctx->fmap;
const uint8_t *encoded = NULL;
uint8_t decoded[BUFSIZ], spare_bits = 0, last_byte = 0, this_byte = 0, offset = 0;
size_t enc_done=0, enc_todo=map->len;
unsigned int dec_done=0, chunksz = 0, chunkoff=0;
size_t enc_done = 0, enc_todo = map->len;
unsigned int dec_done = 0, chunksz = 0, chunkoff = 0;
uint32_t datalen = 0, reslen = 0;
int in_data = 0, in_run = 0, datafd, resfd, ret = CL_CLEAN;
enum binhex_phase { IN_BANNER, IN_HEADER, IN_DATA, IN_LIMBO1, IN_LIMBO2, IN_RES } write_phase = IN_BANNER;
enum binhex_phase { IN_BANNER,
IN_HEADER,
IN_DATA,
IN_LIMBO1,
IN_LIMBO2,
IN_RES } write_phase = IN_BANNER;
char *dname, *rname;
cli_dbgmsg("in cli_binhex\n");
if(!map->len) return CL_CLEAN;
if (!map->len) return CL_CLEAN;
if((ret = cli_gentempfd(ctx->engine->tmpdir, &dname, &datafd)) != CL_SUCCESS)
return ret;
if ((ret = cli_gentempfd(ctx->engine->tmpdir, &dname, &datafd)) != CL_SUCCESS)
return ret;
if((ret = cli_gentempfd(ctx->engine->tmpdir, &rname, &resfd)) != CL_SUCCESS) {
close(datafd);
if(cli_unlink(dname)) ret = CL_EUNLINK;
free(dname);
return ret;
if ((ret = cli_gentempfd(ctx->engine->tmpdir, &rname, &resfd)) != CL_SUCCESS) {
close(datafd);
if (cli_unlink(dname)) ret = CL_EUNLINK;
free(dname);
return ret;
}
memset(decoded, 0, 24);
while(1) {
uint8_t b;
if(!enc_todo || dec_done >= BH_FLUSH_SZ) {
if(write_phase == IN_HEADER) {
uint32_t namelen = (uint32_t)decoded[0], hdrlen = 1 + namelen + 1 + 4 + 4 + 2;
if(!dec_done) {
cli_dbgmsg("cli_binhex: file is empty\n");
break;
}
datalen = (decoded[hdrlen]<<24) | (decoded[hdrlen+1]<<16) | (decoded[hdrlen+2]<<8) | decoded[hdrlen+3];
hdrlen += 4;
reslen = (decoded[hdrlen]<<24) | (decoded[hdrlen+1]<<16) | (decoded[hdrlen+2]<<8) | decoded[hdrlen+3];
hdrlen += 4 + 2;
decoded[namelen+1] = 0;
if(dec_done <= hdrlen) {
cli_dbgmsg("cli_binhex: file too short for header\n");
break;
}
if((ret = cli_checklimits("cli_binhex(data)", ctx, datalen, 0, 0)) != CL_CLEAN)
break;
if(cli_checklimits("cli_binhex(resources)", ctx, reslen, 0, 0) != CL_CLEAN)
reslen = 0;
cli_dbgmsg("cli_binhex: decoding '%s' - %u bytes of data to %s - %u bytes or resources to %s\n", decoded+1, datalen, dname, reslen, rname);
memmove(decoded, &decoded[hdrlen], dec_done - hdrlen);
dec_done -= hdrlen;
write_phase++;
}
if(dec_done && write_phase == IN_DATA) {
unsigned int todo = MIN(dec_done, datalen);
datalen -= todo;
dec_done -= todo;
if(cli_writen(datafd, decoded, todo)!=(int)todo) {
ret = CL_EWRITE;
break;
}
if(!datalen) {
write_phase++;
if (lseek(datafd, 0, SEEK_SET) == -1) {
cli_dbgmsg("cli_binhex: call to lseek() has failed\n");
ret = CL_ESEEK;
while (1) {
uint8_t b;
if (!enc_todo || dec_done >= BH_FLUSH_SZ) {
if (write_phase == IN_HEADER) {
uint32_t namelen = (uint32_t)decoded[0], hdrlen = 1 + namelen + 1 + 4 + 4 + 2;
if (!dec_done) {
cli_dbgmsg("cli_binhex: file is empty\n");
break;
}
datalen = (decoded[hdrlen] << 24) | (decoded[hdrlen + 1] << 16) | (decoded[hdrlen + 2] << 8) | decoded[hdrlen + 3];
hdrlen += 4;
reslen = (decoded[hdrlen] << 24) | (decoded[hdrlen + 1] << 16) | (decoded[hdrlen + 2] << 8) | decoded[hdrlen + 3];
hdrlen += 4 + 2;
decoded[namelen + 1] = 0;
if (dec_done <= hdrlen) {
cli_dbgmsg("cli_binhex: file too short for header\n");
break;
}
if ((ret = cli_checklimits("cli_binhex(data)", ctx, datalen, 0, 0)) != CL_CLEAN)
break;
if (cli_checklimits("cli_binhex(resources)", ctx, reslen, 0, 0) != CL_CLEAN)
reslen = 0;
cli_dbgmsg("cli_binhex: decoding '%s' - %u bytes of data to %s - %u bytes or resources to %s\n", decoded + 1, datalen, dname, reslen, rname);
memmove(decoded, &decoded[hdrlen], dec_done - hdrlen);
dec_done -= hdrlen;
write_phase++;
}
if (dec_done && write_phase == IN_DATA) {
unsigned int todo = MIN(dec_done, datalen);
datalen -= todo;
dec_done -= todo;
if (cli_writen(datafd, decoded, todo) != (int)todo) {
ret = CL_EWRITE;
break;
}
if (!datalen) {
write_phase++;
if (lseek(datafd, 0, SEEK_SET) == -1) {
cli_dbgmsg("cli_binhex: call to lseek() has failed\n");
ret = CL_ESEEK;
break;
}
ret = cli_magic_scandesc(datafd, dname, ctx);
if (ret == CL_VIRUS) break;
}
if (dec_done)
memmove(decoded, &decoded[todo], dec_done);
}
if (dec_done && write_phase == IN_LIMBO1) {
if (dec_done > 1) {
if (reslen < 5) {
cli_dbgmsg("cli_binhex: skipping resources (too small)\n");
break;
}
dec_done -= 2;
write_phase += 2;
if (dec_done)
memmove(decoded, &decoded[2], dec_done);
} else {
dec_done--;
write_phase++;
if (dec_done)
memmove(decoded, &decoded[1], dec_done);
}
}
if (dec_done && write_phase == IN_LIMBO2) {
if (reslen < 5) {
cli_dbgmsg("cli_binhex: skipping resources (too small)\n");
break;
}
write_phase++;
if (--dec_done)
memmove(decoded, &decoded[1], dec_done);
}
if (dec_done && write_phase == IN_RES) {
unsigned int todo = MIN(dec_done, reslen);
reslen -= todo;
dec_done -= todo;
if (cli_writen(resfd, decoded, todo) != (int)todo) {
ret = CL_EWRITE;
break;
}
if (!reslen) {
if (lseek(resfd, 0, SEEK_SET) == -1) {
cli_dbgmsg("cli_binhex: call to lseek() has failed\n");
ret = CL_ESEEK;
break;
}
ret = cli_magic_scandesc(resfd, rname, ctx);
break;
}
}
if (!enc_todo) {
if (write_phase == IN_DATA) {
cli_dbgmsg("cli_binhex: scanning partially extracted data fork\n");
if (lseek(datafd, 0, SEEK_SET) == -1) {
cli_dbgmsg("cli_binhex: call to lseek() has failed\n");
ret = CL_ESEEK;
break;
}
ret = cli_magic_scandesc(datafd, dname, ctx);
} else if (write_phase == IN_RES) {
cli_dbgmsg("cli_binhex: scanning partially extracted resource fork\n");
if (lseek(resfd, 0, SEEK_SET) == -1) {
cli_dbgmsg("cli_binhex: call to lseek() has failed\n");
ret = CL_ESEEK;
break;
}
ret = cli_magic_scandesc(resfd, rname, ctx);
}
break;
}
ret = cli_magic_scandesc(datafd, dname, ctx);
if(ret == CL_VIRUS) break;
}
if(dec_done)
memmove(decoded, &decoded[todo], dec_done);
}
if(dec_done && write_phase == IN_LIMBO1) {
if(dec_done > 1) {
if(reslen<5) {
cli_dbgmsg("cli_binhex: skipping resources (too small)\n");
break;
}
dec_done-=2;
write_phase+=2;
if(dec_done)
memmove(decoded, &decoded[2], dec_done);
} else {
dec_done--;
write_phase++;
if(dec_done)
memmove(decoded, &decoded[1], dec_done);
}
}
if(dec_done && write_phase == IN_LIMBO2) {
if(reslen<5) {
cli_dbgmsg("cli_binhex: skipping resources (too small)\n");
break;
}
write_phase++;
if(--dec_done)
memmove(decoded, &decoded[1], dec_done);
}
if(dec_done && write_phase == IN_RES) {
unsigned int todo = MIN(dec_done, reslen);
reslen -= todo;
dec_done -= todo;
if(cli_writen(resfd, decoded, todo)!=(int)todo) {
ret = CL_EWRITE;
break;
}
if(!reslen) {
if (lseek(resfd, 0, SEEK_SET) == -1) {
cli_dbgmsg("cli_binhex: call to lseek() has failed\n");
ret = CL_ESEEK;
}
// 'chunksz' must be 0 the first iteration,
// so that 'encoded' will be initialized before first dereference.
if (!chunksz) {
chunksz = MIN(enc_todo, map->pgsz);
encoded = fmap_need_off_once(map, enc_done, chunksz);
if (!encoded) {
ret = CL_EREAD;
break;
}
ret = cli_magic_scandesc(resfd, rname, ctx);
break;
}
}
if(!enc_todo) {
if(write_phase == IN_DATA) {
cli_dbgmsg("cli_binhex: scanning partially extracted data fork\n");
if (lseek(datafd, 0, SEEK_SET) == -1) {
cli_dbgmsg("cli_binhex: call to lseek() has failed\n");
ret = CL_ESEEK;
chunkoff = 0;
}
chunksz--;
b = encoded[chunkoff++];
enc_done++;
enc_todo--;
if ((char)b == '\r' || (char)b == '\n') {
in_data = 1;
continue;
}
if (!in_data) continue;
if (write_phase == IN_BANNER) {
if ((char)b != ':') {
cli_dbgmsg("cli_binhex: broken file (missing stream start identifier)\n");
break;
}
ret = cli_magic_scandesc(datafd, dname, ctx);
} else if(write_phase == IN_RES) {
cli_dbgmsg("cli_binhex: scanning partially extracted resource fork\n");
if (lseek(resfd, 0, SEEK_SET) == -1) {
cli_dbgmsg("cli_binhex: call to lseek() has failed\n");
ret = CL_ESEEK;
write_phase++;
}
if ((char)b == ':')
continue;
if (b > 0x7f || (b = hqxtbl[b]) == 0xff) {
cli_dbgmsg("cli_binhex: Invalid character (%02x)\n", encoded[chunkoff - 1]);
break;
}
switch ((offset++) & 3) { /* 6 bits per char */
case 0: /* left-6h */
spare_bits = b << 2;
continue;
case 1: /* left-2l + middle-4h */
this_byte = spare_bits | (b >> 4);
spare_bits = b << 4;
break;
case 2: /* middle-4l + right-2h */
this_byte = spare_bits | (b >> 2);
spare_bits = b << 6;
break;
case 3: /* right-6l */
this_byte = spare_bits | b;
}
if (in_run) {
in_run = 0;
if (!this_byte)
this_byte = 0x90;
else {
while (--this_byte)
decoded[dec_done++] = last_byte;
continue;
}
ret = cli_magic_scandesc(resfd, rname, ctx);
}
break;
}
}
// 'chunksz' must be 0 the first iteration,
// so that 'encoded' will be initialized before first dereference.
if(!chunksz)
{
chunksz = MIN(enc_todo, map->pgsz);
encoded = fmap_need_off_once(map, enc_done, chunksz);
if(!encoded) {
ret = CL_EREAD;
break;
}
chunkoff = 0;
}
chunksz--;
b = encoded[chunkoff++];
enc_done++;
enc_todo--;
if((char)b == '\r' || (char)b == '\n') {
in_data = 1;
continue;
}
if(!in_data) continue;
if(write_phase == IN_BANNER) {
if((char)b != ':') {
cli_dbgmsg("cli_binhex: broken file (missing stream start identifier)\n");
break;
}
write_phase++;
}
if((char)b == ':')
continue;
if(b > 0x7f || (b = hqxtbl[b]) == 0xff) {
cli_dbgmsg("cli_binhex: Invalid character (%02x)\n", encoded[chunkoff-1]);
break;
}
switch((offset++) & 3) { /* 6 bits per char */
case 0: /* left-6h */
spare_bits = b<<2;
continue;
case 1: /* left-2l + middle-4h */
this_byte = spare_bits | (b>>4);
spare_bits = b<<4;
break;
case 2: /* middle-4l + right-2h */
this_byte = spare_bits | (b>>2);
spare_bits = b<<6;
break;
case 3: /* right-6l */
this_byte = spare_bits | b;
}
if(in_run) {
in_run = 0;
if(!this_byte)
this_byte = 0x90;
else {
while(--this_byte)
decoded[dec_done++] = last_byte;
continue;
}
} else if(this_byte == 0x90) {
in_run = 1;
continue;
}
decoded[dec_done++] = this_byte;
last_byte = this_byte;
} else if (this_byte == 0x90) {
in_run = 1;
continue;
}
decoded[dec_done++] = this_byte;
last_byte = this_byte;
}
close(datafd);
close(resfd);
if(!ctx->engine->keeptmp) {
if(cli_unlink(dname) && ret != CL_VIRUS) ret = CL_EUNLINK;
if(cli_unlink(rname) && ret != CL_VIRUS) ret = CL_EUNLINK;
if (!ctx->engine->keeptmp) {
if (cli_unlink(dname) && ret != CL_VIRUS) ret = CL_EUNLINK;
if (cli_unlink(rname) && ret != CL_VIRUS) ret = CL_EUNLINK;
}
free(dname);
free(rname);

File diff suppressed because it is too large Load diff

View file

@ -26,56 +26,56 @@
* Resizable chunk of memory
*/
typedef struct blob {
char *name; /* filename */
unsigned char *data; /* the stuff itself */
off_t len; /* number of bytes of data so far */
off_t size; /* number of bytes allocated to data so far */
int isClosed;
#ifdef CL_DEBUG
object_type magic; /* verify that this is a blob */
char *name; /* filename */
unsigned char *data; /* the stuff itself */
off_t len; /* number of bytes of data so far */
off_t size; /* number of bytes allocated to data so far */
int isClosed;
#ifdef CL_DEBUG
object_type magic; /* verify that this is a blob */
#endif
} blob;
blob *blobCreate(void);
void blobDestroy(blob *b);
void blobArrayDestroy(blob *b[], int n);
void *blobToMem(blob *b);
void blobSetFilename(blob *b, const char *dir, const char *filename);
int blobAddData(blob *b, const unsigned char *data, size_t len);
blob *blobCreate(void);
void blobDestroy(blob *b);
void blobArrayDestroy(blob *b[], int n);
void *blobToMem(blob *b);
void blobSetFilename(blob *b, const char *dir, const char *filename);
int blobAddData(blob *b, const unsigned char *data, size_t len);
unsigned char *blobGetData(const blob *b);
size_t blobGetDataSize(const blob *b);
void blobClose(blob *b);
int blobcmp(const blob *b1, const blob *b2);
int blobGrow(blob *b, size_t len);
size_t blobGetDataSize(const blob *b);
void blobClose(blob *b);
int blobcmp(const blob *b1, const blob *b2);
int blobGrow(blob *b, size_t len);
/*
* Like a blob, but associated with a file stored in the temporary directory
*/
typedef struct fileblob {
FILE *fp;
int fd;
blob b; /*
typedef struct fileblob {
FILE *fp;
int fd;
blob b; /*
* b.name is the name of the attachment as stored in the
* email, not the full path name of the temporary file
*/
char *fullname; /* full pathname of the file */
cli_ctx *ctx; /* When set we can scan the blob, otherwise NULL */
unsigned long bytes_scanned;
unsigned int isNotEmpty : 1;
unsigned int isInfected : 1;
char *fullname; /* full pathname of the file */
cli_ctx *ctx; /* When set we can scan the blob, otherwise NULL */
unsigned long bytes_scanned;
unsigned int isNotEmpty : 1;
unsigned int isInfected : 1;
} fileblob;
fileblob *fileblobCreate(void);
int fileblobScanAndDestroy(fileblob *fb);
void fileblobDestructiveDestroy(fileblob *fb);
void fileblobDestroy(fileblob *fb);
void fileblobSetFilename(fileblob *fb, const char *dir, const char *filename);
void fileblobPartialSet(fileblob *fb, const char *fullname, const char *arg);
const char *fileblobGetFilename(const fileblob *fb);
void fileblobSetCTX(fileblob *fb, cli_ctx *ctx);
int fileblobAddData(fileblob *fb, const unsigned char *data, size_t len);
int fileblobScan(const fileblob *fb);
int fileblobInfected(const fileblob *fb);
void sanitiseName(char *name);
fileblob *fileblobCreate(void);
int fileblobScanAndDestroy(fileblob *fb);
void fileblobDestructiveDestroy(fileblob *fb);
void fileblobDestroy(fileblob *fb);
void fileblobSetFilename(fileblob *fb, const char *dir, const char *filename);
void fileblobPartialSet(fileblob *fb, const char *fullname, const char *arg);
const char *fileblobGetFilename(const fileblob *fb);
void fileblobSetCTX(fileblob *fb, cli_ctx *ctx);
int fileblobAddData(fileblob *fb, const unsigned char *data, size_t len);
int fileblobScan(const fileblob *fb);
int fileblobInfected(const fileblob *fb);
void sanitiseName(char *name);
#endif /*_BLOB_H*/

View file

@ -31,66 +31,65 @@
* Usually bytecode.cvd will contain this bytecode */
static const char* builtin_bc_startup =
"ClamBCafhhbfkjmld|afefdfggifnf```aa```|biacflfafmfbfcfmb`cnbacacmbachcccmbgfbfcc`ccchcbfdf``bgcaap`clamcoincidencejb:4096\n"
"\n"
"Teddaaahdabahdacahdadahdaeahdafahdagahebfgebidebegebdgebgdebkdebcgebbgebageb`gebofebnfebmfebedeblfebkfebjfebadcbgab`bb`bb`bb`bb`bb`bb`bbifbifbifbifbifbifbifahahahahahahahahahebneebifaaaaaaaab`baabb`bb`baacb`bbadb`baacb`bboeb`baacb`bb`bb`baadb`bbadb`bb`baadb`bbadbadb`bdbadahdbkaahdbbcahdbibahdb`eahdbddahdbodahdbdaahdaiahdakahdamahdahahdbncahdbnbah\n"
"Ebjdaibcdbbf|bcaefnfgfifnfefoedfcfofnfffoelfeffgeflf``bbdbbf|bkaefnfgfifnfefoeffegnfcfdgifofnfaflfifdgigoelfeffgeflf``agbcf|baadfefbfeggfoe`gbgifnfdgoeegifnfdg``bcabcf|afdgefcgdgbc``afbdf|b`adfefbfeggfoe`gbgifnfdgoecgdgbg``bhdbef|b`agfefdgoeefnffgifbgofnfmfefnfdg``aabff|afdgefcgdgac``bidbgf|bdadfifcgafbflfefoebfigdgefcfofdfefoeifff``bjdbgf|aodfifcgafbflfefoejfifdgoeifff``\n"
"G`b`c`@`b`aAa`bfgBifBkeBccBdcBmeBhcBfcB`bBdfBefBdgBefBcfBdgBefBdfBlbB`bBjdBidBdeB`bBnfBefBefBdfBcgB`bB`gBefBnfBdgBifBegBmfB`bBofBbgB`bBbfBefBdgBdgBefBbg@`bidBifBccBhcBfc@`bidBifBdcBhcBfc@`begBcdB`eBeeB`bBdfBofBefBcgBnfBgbBdgB`bBcgBegB`gB`gBofBbgBdgB`bBcdBmdBodBfeBlbB`bBggBofBegBlfBdfB`bBnfBefBefBdfB`bB`cBnbBicBgcB`bBhbBldBldBfeBmdB`bBbcBnbBhcBibB`bBdgBofB`bBggBofBbgBkfBab@`bidBifBecBhcBfc@`bdgB`gBefBnfBdgBifBegBmf@`bidBifBfcBhcBfc@`bgdBkfBfc@`bidBkfBfcBmbBbc@`bidBkfBfcBmbBcc@`bkdBafBdgBhfBlfBofBnf@`bcgBafBdgBhfBlfBofBnfBmbBdgBbfBifBbgBdf@`bbgBggBifBnfBcfBhfBifB`gBmbBcfBfc@`bagBggBifBnfBcfBhfBifB`gBbc@`bgdBcfBcc@`b`gBbeBgeBheB`bBmfBafB`gB`gBifBnfBgfB`bBdfBefBnfBifBefBdfBnb@`bofBneBceBedBldBifBnfBegBhgB`bBifBcgB`bB`gBbgBefBfgBefBnfBdgBifBnfBgfB`bBgbBefBhgBefBcfBmfBefBmfBgbB`bBafBcfBcfBefBcgBcgBnbAjBbeBegBnfB`bB`bBgbBcgBefBdgBcgBefBbfBofBofBlfB`bBmbB`eB`bBcfBlfBafBmfBdfBoeBegBcgBefBoeBjfBifBdgB`bBofBnfBgbBnb@`bnfBneB`eBafBheB`bBifBcgB`bB`gBbgBefBfgBefBnfBdgBifBnfBgfB`bBgbBmfB`gBbgBofBdgBefBcfBdgBgbB`bBafBcfBcfBefBcgBcgBnbAjBbeBegBnfB`bBgbB`gBafBhgBcfBdgBlfB`bBmbBcfBmfB`bBlcBefBhgBefBcfBegBdgBafBbfBlfBefBncBgb@`bmfBneBbeBgeBheB`bBmfBafB`gB`gBifBnfBgfB`bBdfBefBnfBifBefBdfB`bBffBofBbgB`bBegBnfBkfBnfBofBggBnfB`bBbgBefBafBcgBofBnfBnbB`eBlfBefBafBcgBefB`bBbgBefB`gBofBbgBdgB`bBdgBofB`bBhfBdgBdgB`gBjcBobBobBbfBegBgfBcgBnbBcfBlfBafBmfBafBfgBnbBnfBefBdgAj@`bed@`blfBcgBdgBafBbgBdgBegB`gBjcB`bBbfBigBdgBefBcfBofBdfBefB`bBefBhgBefBcfBegBdgBifBofBnfB`bBifBnfB`bBafBegBdgBofB`bBmfBofBdfBef@`bkfBcgBdgBafBbgBdgBegB`gBjcB`bBbfBigBdgBefBcfBofBdfBefB`bBefBhgBefBcfBegBdgBifBofBnfB`bBggBifBdgBhfB`bBifBnfBdgBefBbgB`gBbgBefBdgBefBbgB`bBofBnfBlfBig@`bjfBcgBdgBafBbgBdgBegB`gBjcB`bBbfBigBdgBefBcfBofBdfBefB`bBdfBifBcgBafBbfBlfBefBdf@`bad@Ab`bad@Ac`bad@Ad`bad@Ae`bad@Af`bad@Ag`bad@Ah`bad@Ai`bad@Aj`bad@Ak`bad@Al`bad@Am`bad@An`bad@Ao`bad@B`a`bad@Baa`bad@Bba`bad@Bca`bad@Bda`bad@Bea`bad@Bfa`bad@Bga`bad@Bha`\n"
"A`b`bLblib`bab`b`b`b`bneab`b`bad`ah`aa`bad`ah`aa`b`f`bad`b`b`aa`b`b`aa`b`b`b`b`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`b`b`bad`ah`b`b`b`b`aa`b`b`bad`ah`aa`ah`b`b`b`b`aa`b`b`b`b`aa`b`b`b`b`bad`ah`aa`bad`ah`aa`b`b`aa`b`b`b`b`aa`aa`aa`aa`aa`b`b`b`b`b`b`ah`aa`bcd`b`b`aa`bcd`b`b`bcd`b`b`aa`b`b`aa`b`b`b`b`aa`bad`ah`b`b`aa`b`b`aa`bad`ah`b`b`b`b`bad`ah`b`b`b`b`bad`ah`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`bad`ah`b`b`b`b`bcd`b`b`b`b`b`b`bad`ah`b`b`b`b`bcd`b`b`b`b`bcd`b`b`aa`b`b`bcd`b`b`aa`b`b`bcd`b`b`aa`b`b`b`b`aa`b`b`b`b`aa`b`b`b`b`Fbbnbec\n"
"Bb`badabbbhdacClnadbadaedbboeacBdadahafgbaeaaageaahaf@aTaaagblaaa\n"
"BbadahdbboeacB`adahaigbahaaajeaahaiAaaTaaajabbaa\n"
"Bb`fakdbboeacAidbadaldbb`fak@db`bamkbalBja`Aedaaaneab`bam@db`b`bbAadabTaaanadac\n"
"Bb`baokbalBka`Aedaab`aeab`bao@db`bab`ab`ab`b`bbababTbaad\n"
"Bb`bbaabbabbaab`bbbaabcbjdBia`@dbaab`bbcaab`bbdaabdaiab`bbcaBicdTaabdaaebaa\n"
"Bb`bbeakbalBma`Aedaabfaeab`bbea@db`b`bbAadaaTaabfab`aaf\n"
"Bb`bbgakbalBna`Ahdaabhaeab`bbga@db`b`bbAadaaTaabhab`aag\n"
"Bb`bbiakbalBoa`Aedaabjaeab`bbia@db`b`bbAadaaTaabjab`aah\n"
"Bb`bbkakbalB`b`Acdaablaeab`bbka@db`b`bbAadaaTaablab`aai\n"
"Bb`bbmakbalBab`Aedaabnaeab`bbma@db`b`bbAadaaTaabnab`aaj\n"
"Bb`bboakbalBbb`Aedaab`beab`bboa@db`b`bbAadaaTaab`bb`aak\n"
"Bb`bbabkbalBcb`Agdaabbbeab`bbab@db`b`bbAadaaTaabbbb`aal\n"
"Bb`bbcbkbalBdb`Amdaabdbeab`bbcb@db`b`bbAadaaTaabdbb`aam\n"
"Bb`bbebkbalBeb`Akdaabfbeab`bbeb@db`b`bbAadaaTaabfbb`aan\n"
"Bb`bbgbkbalBfb`Aidaabhbeab`bbgb@db`b`bbAadaaTaabhbb`aao\n"
"Bb`bbibkbalBgb`Acdaabjbeab`bbib@db`baa`abjbb`b`bbaaaaTbab`a\n"
"Bb`bbkbbbaabkbb`bblbabcbjdBla`@dbkbTbabaa\n"
"BbadbmbdbboeacBeadahbnbgbbmbb`bbob`abnbb`bb`ck`bobAadaabaceab`bb`c@dTaabacbbabha\n"
"Bb`bbbcabcbjdBhb`@dAadbadbccdbboeacBaadahbdcgbbccaabeceaahbdcAjaTaabecbcabla\n"
"Bahbfcgbbmbb`bbgc`abfcb`bbhck`bgcAbdaabiceab`bbhc@dTaabicbeabda\n"
"Bb`bbjcabcbjdBib`@dAadTbabla\n"
"Bb`bbkck`bgcAhdaablceab`bbkc@dTaablcbgabfa\n"
"Bb`bbmcabcbjdBjb`@dAadTbabla\n"
"Bb`bbncabcbjdBkb`@dAadTbabla\n"
"BbadbocdbboeacBaadahb`dgbbocaabadeaahb`dAjaTaabadbjabia\n"
"BbadbbddbboeacBbadahbcdgbbbdaabddeaahbcdAfaTaabddbjabla\n"
"Bb`bbedk`bobB`adaabfdeab`bbed@dTaabfdblabka\n"
"Bb`bbgdabcbjdBjb`@dAadTbabla\n"
"Bb`bbhdabcbidBlb`@d@daabidnab`bbhdAadTaabidb`bbma\n"
"Baabjdnab`bbhdAbdTaabjdboabna\n"
"Baabkdeab`bbhdAbdTaabkdbcbbdb\n"
"Baabldeab`bbhdAadTaabldbbbbdb\n"
"Baabmdeab`bbhd@dTaabmdbabbdb\n"
"Bb`bbndabbafBmb`@dTbabdb\n"
"Bb`bbodabbafBnb`@dTbabdb\n"
"Bb`bb`eabbafBob`@dTbabdb\n"
"Bahbaegbaeaabbeeaahbae@aTaabbebfbbeb\n"
"BbcdbcedbboeacAddb`bbdegbbceaabeeeab`bbde@db`b`bbEamjnmd`Taabeebdcbfb\n"
"BbcdbfedbboeacAfdb`bbgegbbfebcdbhedbboeacAedb`bbiegbbheaabjeiab`bbgebieb`b`bbEbmjnmd`Taabjebdcbgb\n"
"Bb`bbkeab`bbdaableeab`bbiebkeb`b`bbEcmjnmd`Taablebhbbdc\n"
"Bb`bbmegbbfeb`bbneab`bcdaaboeeab`bbmebneb`b`bbEdmjnmd`Taaboebibbdc\n"
"Bbadb`fdbboeacAndahbafgbb`fb`bbbf`abafaabcflbb`bbdf`abcfaabefeab`bbbfbdfb`b`bbEemjnmd`Taabefbjbbdc\n"
"BbadbffdbboeacBaadahbgfgbbffb`bbhf`abgfb`bbifh`bhfBhadbadbjfdbboeacB`adahbkfgbbjfb`bblf`abkfb`bbmfh`blfBdadbadbnfdbboeacBcadahbofgbbnfb`bb`g`abofb`bbagh`b`gB`adb`bbbggbbheb`bbcgh`bbgAhdb`bbdggbbfeb`bbegl`bmfbifb`bbfgl`begbcgb`bbggl`bfgbdgb`bbhgl`bggbagb`bbigh`bbfBladbadbjgdbboeacAodahbkggbbjgb`bblg`abkgb`bbmgh`blgBhadbcdbngdbboeacAddb`bboggbbngb`bb`hl`bogbigb`bbahl`b`hbmgbadbbhdbboeacBeadahbchgbbbhb`bbdh`abchb`bbehh`bdhBhadbcdbfhdbboeacAcdb`bbghgbbfhb`bbhhl`behbghbcdbihdbboeac@db`bbjhgbbihaabkheab`bbhgbjhTaabkhblbbkb\n"
"Bb`bblhabaagbhgTcab`bEfmjnmd\n"
"BbcdbmhdbboeacAadb`bbnhgbbmhaaboheab`bbahbnhTaabohbnbbmb\n"
"Bb`bb`iabaagbahTcab`bEgmjnmd\n"
"BbcdbaidbboeacAbdb`bbbigbbaiaabcieab`bbhhbbiTaabcib`cbob\n"
"Bb`bbdiabaagbhhTcab`bEhmjnmd\n"
"Bb`bbeiabbaaHonnkm``odHm``oonnkdaabfieab`bbeiHhgfedcbadTaabfibbcbac\n"
"Bb`bbgiabaagbeiTcab`bEimjnmd\n"
"Bb`bbhiababcaDm``odaabiieab`bbhiDo``mdb`b`bbHnejkjgjmd`Taabiibdcbcc\n"
"Bb`bbjiabaagbhiTcab`bF`amjnmd\n"
"Bb`bbkibb`bkiTcab`bbkiE\n"
;
"ClamBCafhhbfkjmld|afefdfggifnf```aa```|biacflfafmfbfcfmb`cnbacacmbachcccmbgfbfcc`ccchcbfdf``bgcaap`clamcoincidencejb:4096\n"
"\n"
"Teddaaahdabahdacahdadahdaeahdafahdagahebfgebidebegebdgebgdebkdebcgebbgebageb`gebofebnfebmfebedeblfebkfebjfebadcbgab`bb`bb`bb`bb`bb`bb`bbifbifbifbifbifbifbifahahahahahahahahahebneebifaaaaaaaab`baabb`bb`baacb`bbadb`baacb`bboeb`baacb`bb`bb`baadb`bbadb`bb`baadb`bbadbadb`bdbadahdbkaahdbbcahdbibahdb`eahdbddahdbodahdbdaahdaiahdakahdamahdahahdbncahdbnbah\n"
"Ebjdaibcdbbf|bcaefnfgfifnfefoedfcfofnfffoelfeffgeflf``bbdbbf|bkaefnfgfifnfefoeffegnfcfdgifofnfaflfifdgigoelfeffgeflf``agbcf|baadfefbfeggfoe`gbgifnfdgoeegifnfdg``bcabcf|afdgefcgdgbc``afbdf|b`adfefbfeggfoe`gbgifnfdgoecgdgbg``bhdbef|b`agfefdgoeefnffgifbgofnfmfefnfdg``aabff|afdgefcgdgac``bidbgf|bdadfifcgafbflfefoebfigdgefcfofdfefoeifff``bjdbgf|aodfifcgafbflfefoejfifdgoeifff``\n"
"G`b`c`@`b`aAa`bfgBifBkeBccBdcBmeBhcBfcB`bBdfBefBdgBefBcfBdgBefBdfBlbB`bBjdBidBdeB`bBnfBefBefBdfBcgB`bB`gBefBnfBdgBifBegBmfB`bBofBbgB`bBbfBefBdgBdgBefBbg@`bidBifBccBhcBfc@`bidBifBdcBhcBfc@`begBcdB`eBeeB`bBdfBofBefBcgBnfBgbBdgB`bBcgBegB`gB`gBofBbgBdgB`bBcdBmdBodBfeBlbB`bBggBofBegBlfBdfB`bBnfBefBefBdfB`bB`cBnbBicBgcB`bBhbBldBldBfeBmdB`bBbcBnbBhcBibB`bBdgBofB`bBggBofBbgBkfBab@`bidBifBecBhcBfc@`bdgB`gBefBnfBdgBifBegBmf@`bidBifBfcBhcBfc@`bgdBkfBfc@`bidBkfBfcBmbBbc@`bidBkfBfcBmbBcc@`bkdBafBdgBhfBlfBofBnf@`bcgBafBdgBhfBlfBofBnfBmbBdgBbfBifBbgBdf@`bbgBggBifBnfBcfBhfBifB`gBmbBcfBfc@`bagBggBifBnfBcfBhfBifB`gBbc@`bgdBcfBcc@`b`gBbeBgeBheB`bBmfBafB`gB`gBifBnfBgfB`bBdfBefBnfBifBefBdfBnb@`bofBneBceBedBldBifBnfBegBhgB`bBifBcgB`bB`gBbgBefBfgBefBnfBdgBifBnfBgfB`bBgbBefBhgBefBcfBmfBefBmfBgbB`bBafBcfBcfBefBcgBcgBnbAjBbeBegBnfB`bB`bBgbBcgBefBdgBcgBefBbfBofBofBlfB`bBmbB`eB`bBcfBlfBafBmfBdfBoeBegBcgBefBoeBjfBifBdgB`bBofBnfBgbBnb@`bnfBneB`eBafBheB`bBifBcgB`bB`gBbgBefBfgBefBnfBdgBifBnfBgfB`bBgbBmfB`gBbgBofBdgBefBcfBdgBgbB`bBafBcfBcfBefBcgBcgBnbAjBbeBegBnfB`bBgbB`gBafBhgBcfBdgBlfB`bBmbBcfBmfB`bBlcBefBhgBefBcfBegBdgBafBbfBlfBefBncBgb@`bmfBneBbeBgeBheB`bBmfBafB`gB`gBifBnfBgfB`bBdfBefBnfBifBefBdfB`bBffBofBbgB`bBegBnfBkfBnfBofBggBnfB`bBbgBefBafBcgBofBnfBnbB`eBlfBefBafBcgBefB`bBbgBefB`gBofBbgBdgB`bBdgBofB`bBhfBdgBdgB`gBjcBobBobBbfBegBgfBcgBnbBcfBlfBafBmfBafBfgBnbBnfBefBdgAj@`bed@`blfBcgBdgBafBbgBdgBegB`gBjcB`bBbfBigBdgBefBcfBofBdfBefB`bBefBhgBefBcfBegBdgBifBofBnfB`bBifBnfB`bBafBegBdgBofB`bBmfBofBdfBef@`bkfBcgBdgBafBbgBdgBegB`gBjcB`bBbfBigBdgBefBcfBofBdfBefB`bBefBhgBefBcfBegBdgBifBofBnfB`bBggBifBdgBhfB`bBifBnfBdgBefBbgB`gBbgBefBdgBefBbgB`bBofBnfBlfBig@`bjfBcgBdgBafBbgBdgBegB`gBjcB`bBbfBigBdgBefBcfBofBdfBefB`bBdfBifBcgBafBbfBlfBefBdf@`bad@Ab`bad@Ac`bad@Ad`bad@Ae`bad@Af`bad@Ag`bad@Ah`bad@Ai`bad@Aj`bad@Ak`bad@Al`bad@Am`bad@An`bad@Ao`bad@B`a`bad@Baa`bad@Bba`bad@Bca`bad@Bda`bad@Bea`bad@Bfa`bad@Bga`bad@Bha`\n"
"A`b`bLblib`bab`b`b`b`bneab`b`bad`ah`aa`bad`ah`aa`b`f`bad`b`b`aa`b`b`aa`b`b`b`b`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`aa`b`b`b`b`bad`ah`b`b`b`b`aa`b`b`bad`ah`aa`ah`b`b`b`b`aa`b`b`b`b`aa`b`b`b`b`bad`ah`aa`bad`ah`aa`b`b`aa`b`b`b`b`aa`aa`aa`aa`aa`b`b`b`b`b`b`ah`aa`bcd`b`b`aa`bcd`b`b`bcd`b`b`aa`b`b`aa`b`b`b`b`aa`bad`ah`b`b`aa`b`b`aa`bad`ah`b`b`b`b`bad`ah`b`b`b`b`bad`ah`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`bad`ah`b`b`b`b`bcd`b`b`b`b`b`b`bad`ah`b`b`b`b`bcd`b`b`b`b`bcd`b`b`aa`b`b`bcd`b`b`aa`b`b`bcd`b`b`aa`b`b`b`b`aa`b`b`b`b`aa`b`b`b`b`Fbbnbec\n"
"Bb`badabbbhdacClnadbadaedbboeacBdadahafgbaeaaageaahaf@aTaaagblaaa\n"
"BbadahdbboeacB`adahaigbahaaajeaahaiAaaTaaajabbaa\n"
"Bb`fakdbboeacAidbadaldbb`fak@db`bamkbalBja`Aedaaaneab`bam@db`b`bbAadabTaaanadac\n"
"Bb`baokbalBka`Aedaab`aeab`bao@db`bab`ab`ab`b`bbababTbaad\n"
"Bb`bbaabbabbaab`bbbaabcbjdBia`@dbaab`bbcaab`bbdaabdaiab`bbcaBicdTaabdaaebaa\n"
"Bb`bbeakbalBma`Aedaabfaeab`bbea@db`b`bbAadaaTaabfab`aaf\n"
"Bb`bbgakbalBna`Ahdaabhaeab`bbga@db`b`bbAadaaTaabhab`aag\n"
"Bb`bbiakbalBoa`Aedaabjaeab`bbia@db`b`bbAadaaTaabjab`aah\n"
"Bb`bbkakbalB`b`Acdaablaeab`bbka@db`b`bbAadaaTaablab`aai\n"
"Bb`bbmakbalBab`Aedaabnaeab`bbma@db`b`bbAadaaTaabnab`aaj\n"
"Bb`bboakbalBbb`Aedaab`beab`bboa@db`b`bbAadaaTaab`bb`aak\n"
"Bb`bbabkbalBcb`Agdaabbbeab`bbab@db`b`bbAadaaTaabbbb`aal\n"
"Bb`bbcbkbalBdb`Amdaabdbeab`bbcb@db`b`bbAadaaTaabdbb`aam\n"
"Bb`bbebkbalBeb`Akdaabfbeab`bbeb@db`b`bbAadaaTaabfbb`aan\n"
"Bb`bbgbkbalBfb`Aidaabhbeab`bbgb@db`b`bbAadaaTaabhbb`aao\n"
"Bb`bbibkbalBgb`Acdaabjbeab`bbib@db`baa`abjbb`b`bbaaaaTbab`a\n"
"Bb`bbkbbbaabkbb`bblbabcbjdBla`@dbkbTbabaa\n"
"BbadbmbdbboeacBeadahbnbgbbmbb`bbob`abnbb`bb`ck`bobAadaabaceab`bb`c@dTaabacbbabha\n"
"Bb`bbbcabcbjdBhb`@dAadbadbccdbboeacBaadahbdcgbbccaabeceaahbdcAjaTaabecbcabla\n"
"Bahbfcgbbmbb`bbgc`abfcb`bbhck`bgcAbdaabiceab`bbhc@dTaabicbeabda\n"
"Bb`bbjcabcbjdBib`@dAadTbabla\n"
"Bb`bbkck`bgcAhdaablceab`bbkc@dTaablcbgabfa\n"
"Bb`bbmcabcbjdBjb`@dAadTbabla\n"
"Bb`bbncabcbjdBkb`@dAadTbabla\n"
"BbadbocdbboeacBaadahb`dgbbocaabadeaahb`dAjaTaabadbjabia\n"
"BbadbbddbboeacBbadahbcdgbbbdaabddeaahbcdAfaTaabddbjabla\n"
"Bb`bbedk`bobB`adaabfdeab`bbed@dTaabfdblabka\n"
"Bb`bbgdabcbjdBjb`@dAadTbabla\n"
"Bb`bbhdabcbidBlb`@d@daabidnab`bbhdAadTaabidb`bbma\n"
"Baabjdnab`bbhdAbdTaabjdboabna\n"
"Baabkdeab`bbhdAbdTaabkdbcbbdb\n"
"Baabldeab`bbhdAadTaabldbbbbdb\n"
"Baabmdeab`bbhd@dTaabmdbabbdb\n"
"Bb`bbndabbafBmb`@dTbabdb\n"
"Bb`bbodabbafBnb`@dTbabdb\n"
"Bb`bb`eabbafBob`@dTbabdb\n"
"Bahbaegbaeaabbeeaahbae@aTaabbebfbbeb\n"
"BbcdbcedbboeacAddb`bbdegbbceaabeeeab`bbde@db`b`bbEamjnmd`Taabeebdcbfb\n"
"BbcdbfedbboeacAfdb`bbgegbbfebcdbhedbboeacAedb`bbiegbbheaabjeiab`bbgebieb`b`bbEbmjnmd`Taabjebdcbgb\n"
"Bb`bbkeab`bbdaableeab`bbiebkeb`b`bbEcmjnmd`Taablebhbbdc\n"
"Bb`bbmegbbfeb`bbneab`bcdaaboeeab`bbmebneb`b`bbEdmjnmd`Taaboebibbdc\n"
"Bbadb`fdbboeacAndahbafgbb`fb`bbbf`abafaabcflbb`bbdf`abcfaabefeab`bbbfbdfb`b`bbEemjnmd`Taabefbjbbdc\n"
"BbadbffdbboeacBaadahbgfgbbffb`bbhf`abgfb`bbifh`bhfBhadbadbjfdbboeacB`adahbkfgbbjfb`bblf`abkfb`bbmfh`blfBdadbadbnfdbboeacBcadahbofgbbnfb`bb`g`abofb`bbagh`b`gB`adb`bbbggbbheb`bbcgh`bbgAhdb`bbdggbbfeb`bbegl`bmfbifb`bbfgl`begbcgb`bbggl`bfgbdgb`bbhgl`bggbagb`bbigh`bbfBladbadbjgdbboeacAodahbkggbbjgb`bblg`abkgb`bbmgh`blgBhadbcdbngdbboeacAddb`bboggbbngb`bb`hl`bogbigb`bbahl`b`hbmgbadbbhdbboeacBeadahbchgbbbhb`bbdh`abchb`bbehh`bdhBhadbcdbfhdbboeacAcdb`bbghgbbfhb`bbhhl`behbghbcdbihdbboeac@db`bbjhgbbihaabkheab`bbhgbjhTaabkhblbbkb\n"
"Bb`bblhabaagbhgTcab`bEfmjnmd\n"
"BbcdbmhdbboeacAadb`bbnhgbbmhaaboheab`bbahbnhTaabohbnbbmb\n"
"Bb`bb`iabaagbahTcab`bEgmjnmd\n"
"BbcdbaidbboeacAbdb`bbbigbbaiaabcieab`bbhhbbiTaabcib`cbob\n"
"Bb`bbdiabaagbhhTcab`bEhmjnmd\n"
"Bb`bbeiabbaaHonnkm``odHm``oonnkdaabfieab`bbeiHhgfedcbadTaabfibbcbac\n"
"Bb`bbgiabaagbeiTcab`bEimjnmd\n"
"Bb`bbhiababcaDm``odaabiieab`bbhiDo``mdb`b`bbHnejkjgjmd`Taabiibdcbcc\n"
"Bb`bbjiabaagbhiTcab`bF`amjnmd\n"
"Bb`bbkibb`bkiTcab`bbkiE\n";
/* source-code for builtin_bc_startup: */
#if 0
const uint16_t __clambc_kind = BC_STARTUP;
@ -224,6 +223,5 @@ int entrypoint()
return 0xda7aba5e;
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -72,7 +72,7 @@ struct cli_bc {
uint32_t numGlobalBytes;
uint8_t *globalBytes;
uint32_t sigtime_id, sigmatch_id;
char * hook_name;
char *hook_name;
};
struct cli_all_bc {
@ -80,7 +80,7 @@ struct cli_all_bc {
unsigned count;
struct cli_bcengine *engine;
struct cli_environment env;
int inited;
int inited;
};
struct cli_pe_hook_data;
@ -123,12 +123,11 @@ void cli_bytevalue_describe(const struct cli_bc *bc, unsigned funcid);
void cli_byteinst_describe(const struct cli_bc_inst *inst, unsigned *bbnum);
void cli_bytefunc_describe(const struct cli_bc *bc, unsigned funcid);
/* Hooks */
struct cli_exe_info;
struct cli_ctx_tag;
struct cli_target_info;
int cli_bytecode_runlsig(struct cli_ctx_tag *ctx, struct cli_target_info *info, const struct cli_all_bc *bcs, unsigned bc_idx, const uint32_t* lsigcnt, const uint32_t *lsigsuboff, fmap_t *map);
int cli_bytecode_runlsig(struct cli_ctx_tag *ctx, struct cli_target_info *info, const struct cli_all_bc *bcs, unsigned bc_idx, const uint32_t *lsigcnt, const uint32_t *lsigsuboff, fmap_t *map);
int cli_bytecode_runhook(struct cli_ctx_tag *cctx, const struct cl_engine *engine, struct cli_bc_ctx *ctx, unsigned id, fmap_t *map);
#ifdef __cplusplus
@ -142,15 +141,15 @@ void cli_bytecode_printversion(void);
void cli_bytecode_debug_printsrc(const struct cli_bc_ctx *ctx);
void cli_printcxxver(void);
typedef void (*bc_dbg_callback_trace)(struct cli_bc_ctx*, unsigned event);
typedef void (*bc_dbg_callback_trace_op)(struct cli_bc_ctx*, const char *op);
typedef void (*bc_dbg_callback_trace_val)(struct cli_bc_ctx*, const char *name, uint32_t value);
typedef void (*bc_dbg_callback_trace_ptr)(struct cli_bc_ctx*, const void *val);
void cli_bytecode_context_set_trace(struct cli_bc_ctx*, unsigned level,
bc_dbg_callback_trace,
bc_dbg_callback_trace_op,
bc_dbg_callback_trace_val,
bc_dbg_callback_trace_ptr);
typedef void (*bc_dbg_callback_trace)(struct cli_bc_ctx *, unsigned event);
typedef void (*bc_dbg_callback_trace_op)(struct cli_bc_ctx *, const char *op);
typedef void (*bc_dbg_callback_trace_val)(struct cli_bc_ctx *, const char *name, uint32_t value);
typedef void (*bc_dbg_callback_trace_ptr)(struct cli_bc_ctx *, const void *val);
void cli_bytecode_context_set_trace(struct cli_bc_ctx *, unsigned level,
bc_dbg_callback_trace,
bc_dbg_callback_trace_op,
bc_dbg_callback_trace_val,
bc_dbg_callback_trace_ptr);
void cli_sigperf_print(void);
void cli_sigperf_events_destroy(void);
#ifdef __cplusplus

File diff suppressed because it is too large Load diff

View file

@ -42,7 +42,7 @@ struct cli_exe_section;
struct DISASM_RESULT;
#endif
/**
/**
\group_pe
* Invalid RVA specified
*/
@ -54,12 +54,12 @@ struct DISASM_RESULT;
*/
enum BytecodeKind {
/** generic bytecode, not tied a specific hook */
BC_GENERIC=0,
BC_GENERIC = 0,
/** triggered at startup, only one is allowed per ClamAV startup */
BC_STARTUP=1,
_BC_START_HOOKS=256,
BC_STARTUP = 1,
_BC_START_HOOKS = 256,
/** executed on a logical trigger */
BC_LOGICAL=256,
BC_LOGICAL = 256,
/** specifies a PE unpacker, executed on PE files on a logical trigger */
BC_PE_UNPACKER,
/** specifies a PDF hook, executes at a predetermined point of PDF parsing for PDF files */
@ -78,43 +78,43 @@ enum BytecodeKind {
* LibClamAV functionality level constants
*/
enum FunctionalityLevels {
FUNC_LEVEL_096 = 51, /* LibClamAV release 0.96.0: bytecode engine released */
FUNC_LEVEL_096_dev = 52,
FUNC_LEVEL_096_1 = 53, /* LibClamAV release 0.96.1: logical signature use of VI/macros requires this minimum functionality level */
FUNC_LEVEL_096_1_dev = 54,
FUNC_LEVEL_096_2 = 54, /* LibClamAV release 0.96.2: PDF Hooks require this minimum level */
FUNC_LEVEL_096_2_dev = 55,
FUNC_LEVEL_096_3 = 55, /* LibClamAV release 0.96.3: BC_PE_ALL bytecodes require this minimum level */
FUNC_LEVEL_096_4 = 56, /* LibClamAV release 0.96.4: minimum recommended engine version, older versions have quadratic load time */
FUNC_LEVEL_096_5 = 58, /* LibClamAV release 0.96.5 */
FUNC_LEVEL_097 = 60, /* LibClamAV release 0.97.0: older bytecodes may incorrectly use 57 */
FUNC_LEVEL_097_1 = 61, /* LibClamAV release 0.97.1 */
FUNC_LEVEL_097_2 = 62, /* LibClamAV release 0.97.2 */
FUNC_LEVEL_097_3 = 63, /* LibClamAV release 0.97.3: last bcc changes as former team resigns*/
FUNC_LEVEL_097_4 = 64, /* LibClamAV release 0.97.4 */
FUNC_LEVEL_097_5 = 65, /* LibClamAV release 0.97.5 */
FUNC_LEVEL_097_6 = 67, /* LibClamAV release 0.97.6 */
FUNC_LEVEL_097_7 = 68, /* LibClamAV release 0.97.7 */
FUNC_LEVEL_097_8 = 69, /* LibClamAV release 0.97.8 */
FUNC_LEVEL_098_1 = 76, /* LibClamAV release 0.98.1: last syncing to clamav*/
FUNC_LEVEL_098_2 = 77, /* LibClamAV release 0.98.2 */
FUNC_LEVEL_098_3 = 77, /* LibClamAV release 0.98.3 */
FUNC_LEVEL_098_4 = 77, /* LibClamAV release 0.98.4 */
FUNC_LEVEL_098_5 = 79, /* LibClamAV release 0.98.5: JSON reading API requires this minimum level */
FUNC_LEVEL_098_6 = 79, /* LibClamAV release 0.98.6 */
FUNC_LEVEL_098_7 = 80, /* LibClamAV release 0.98.7: BC_PRECLASS bytecodes require minimum level */
FUNC_LEVEL_099 = 81, /* LibClamAV release 0.99, 0.99-beta1(.1-.5), 0.99-beta2 */
FUNC_LEVEL_099_1 = 82, /* LibClamAV release 0.99.1 */
FUNC_LEVEL_099_2 = 82, /* LibClamAV release 0.99.2 */
FUNC_LEVEL_099_3 = 84, /* LibClamAV release 0.99.3 */
FUNC_LEVEL_099_4 = 85, /* LibClamAV release 0.99.4 */
FUNC_LEVEL_0100_0_BETA = 90, /* LibClamAV beta release 0.100.0-beta */
FUNC_LEVEL_0100_0 = 91, /* LibClamAV release 0.100.0, 0.100.0-rc */
FUNC_LEVEL_0100_1 = 92, /**< LibClamAV release 0.100.1 */
FUNC_LEVEL_0100_2 = 93, /**< LibClamAV release 0.100.2 */
FUNC_LEVEL_096 = 51, /* LibClamAV release 0.96.0: bytecode engine released */
FUNC_LEVEL_096_dev = 52,
FUNC_LEVEL_096_1 = 53, /* LibClamAV release 0.96.1: logical signature use of VI/macros requires this minimum functionality level */
FUNC_LEVEL_096_1_dev = 54,
FUNC_LEVEL_096_2 = 54, /* LibClamAV release 0.96.2: PDF Hooks require this minimum level */
FUNC_LEVEL_096_2_dev = 55,
FUNC_LEVEL_096_3 = 55, /* LibClamAV release 0.96.3: BC_PE_ALL bytecodes require this minimum level */
FUNC_LEVEL_096_4 = 56, /* LibClamAV release 0.96.4: minimum recommended engine version, older versions have quadratic load time */
FUNC_LEVEL_096_5 = 58, /* LibClamAV release 0.96.5 */
FUNC_LEVEL_097 = 60, /* LibClamAV release 0.97.0: older bytecodes may incorrectly use 57 */
FUNC_LEVEL_097_1 = 61, /* LibClamAV release 0.97.1 */
FUNC_LEVEL_097_2 = 62, /* LibClamAV release 0.97.2 */
FUNC_LEVEL_097_3 = 63, /* LibClamAV release 0.97.3: last bcc changes as former team resigns*/
FUNC_LEVEL_097_4 = 64, /* LibClamAV release 0.97.4 */
FUNC_LEVEL_097_5 = 65, /* LibClamAV release 0.97.5 */
FUNC_LEVEL_097_6 = 67, /* LibClamAV release 0.97.6 */
FUNC_LEVEL_097_7 = 68, /* LibClamAV release 0.97.7 */
FUNC_LEVEL_097_8 = 69, /* LibClamAV release 0.97.8 */
FUNC_LEVEL_098_1 = 76, /* LibClamAV release 0.98.1: last syncing to clamav*/
FUNC_LEVEL_098_2 = 77, /* LibClamAV release 0.98.2 */
FUNC_LEVEL_098_3 = 77, /* LibClamAV release 0.98.3 */
FUNC_LEVEL_098_4 = 77, /* LibClamAV release 0.98.4 */
FUNC_LEVEL_098_5 = 79, /* LibClamAV release 0.98.5: JSON reading API requires this minimum level */
FUNC_LEVEL_098_6 = 79, /* LibClamAV release 0.98.6 */
FUNC_LEVEL_098_7 = 80, /* LibClamAV release 0.98.7: BC_PRECLASS bytecodes require minimum level */
FUNC_LEVEL_099 = 81, /* LibClamAV release 0.99, 0.99-beta1(.1-.5), 0.99-beta2 */
FUNC_LEVEL_099_1 = 82, /* LibClamAV release 0.99.1 */
FUNC_LEVEL_099_2 = 82, /* LibClamAV release 0.99.2 */
FUNC_LEVEL_099_3 = 84, /* LibClamAV release 0.99.3 */
FUNC_LEVEL_099_4 = 85, /* LibClamAV release 0.99.4 */
FUNC_LEVEL_0100_0_BETA = 90, /* LibClamAV beta release 0.100.0-beta */
FUNC_LEVEL_0100_0 = 91, /* LibClamAV release 0.100.0, 0.100.0-rc */
FUNC_LEVEL_0100_1 = 92, /**< LibClamAV release 0.100.1 */
FUNC_LEVEL_0100_2 = 93, /**< LibClamAV release 0.100.2 */
FUNC_LEVEL_0101_0_BETA = 100, /* LibClamAV beta release 0.101.0-beta */
FUNC_LEVEL_0101_0 = 101, /* LibClamAV release 0.101.0, 0.101.0-rc */
FUNC_LEVEL_100 = 255 /* future release candidate */
FUNC_LEVEL_0101_0 = 101, /* LibClamAV release 0.101.0, 0.101.0-rc */
FUNC_LEVEL_100 = 255 /* future release candidate */
};
/**
@ -134,7 +134,7 @@ enum pdf_phase {
* PDF flags
*/
enum pdf_flag {
BAD_PDF_VERSION=0, /* */
BAD_PDF_VERSION = 0, /* */
BAD_PDF_HEADERPOS, /* */
BAD_PDF_TRAILER, /* */
BAD_PDF_TOOMANYOBJS, /* */
@ -162,7 +162,7 @@ enum pdf_flag {
* PDF obj flags
*/
enum pdf_objflags {
OBJ_STREAM=0, /* */
OBJ_STREAM = 0, /* */
OBJ_DICT, /* */
OBJ_EMBEDDED_FILE, /* */
OBJ_FILTER_AH, /* */
@ -194,13 +194,13 @@ enum pdf_objflags {
* JSON types
*/
enum bc_json_type {
JSON_TYPE_NULL=0, /* */
JSON_TYPE_BOOLEAN, /* */
JSON_TYPE_DOUBLE, /* */
JSON_TYPE_INT, /* */
JSON_TYPE_OBJECT, /* */
JSON_TYPE_ARRAY, /* */
JSON_TYPE_STRING /* */
JSON_TYPE_NULL = 0, /* */
JSON_TYPE_BOOLEAN, /* */
JSON_TYPE_DOUBLE, /* */
JSON_TYPE_INT, /* */
JSON_TYPE_OBJECT, /* */
JSON_TYPE_ARRAY, /* */
JSON_TYPE_STRING /* */
};
/**
@ -296,14 +296,14 @@ uint32_t test1(uint32_t a, uint32_t b);
* @param[out] data pointer to buffer where data is read into
* @return amount read.
*/
int32_t read(uint8_t *data, int32_t size);
int32_t read(uint8_t* data, int32_t size);
/**
\group_file
*/
enum {
/**set file position to specified absolute position */
SEEK_SET=0,
SEEK_SET = 0,
/**set file position relative to current position */
SEEK_CUR,
/**set file position relative to file end*/
@ -320,7 +320,7 @@ enum {
* byte
* @return amount of bytes successfully written
*/
int32_t write(uint8_t *data, int32_t size);
int32_t write(uint8_t* data, int32_t size);
/**
\group_file
@ -339,7 +339,7 @@ int32_t seek(int32_t pos, uint32_t whence);
* @param[in] len length of the virusname
* @return 0
*/
uint32_t setvirusname(const uint8_t *name, uint32_t len);
uint32_t setvirusname(const uint8_t* name, uint32_t len);
/**
\group_debug
@ -348,7 +348,7 @@ uint32_t setvirusname(const uint8_t *name, uint32_t len);
* @param[in] len length of message to print
* @return 0
*/
uint32_t debug_print_str(const uint8_t *str, uint32_t len);
uint32_t debug_print_str(const uint8_t* str, uint32_t len);
/**
\group_debug
@ -436,7 +436,7 @@ uint32_t test2(uint32_t a);
* @return 0 - success
* @return -1 - failure
*/
int32_t get_pe_section(struct cli_exe_section *section, uint32_t num);
int32_t get_pe_section(struct cli_exe_section* section, uint32_t num);
/**
\group_file
@ -534,7 +534,7 @@ int32_t hashset_empty(int32_t id);
* @param[in] size size of buffer
* @return ID of newly created buffer_pipe
*/
int32_t buffer_pipe_new(uint32_t size);
int32_t buffer_pipe_new(uint32_t size);
/**
\group_adt
@ -543,7 +543,7 @@ int32_t buffer_pipe_new(uint32_t size);
* @param[in] pos starting position of pipe input in current file
* @return ID of newly created buffer_pipe
*/
int32_t buffer_pipe_new_fromfile(uint32_t pos);
int32_t buffer_pipe_new_fromfile(uint32_t pos);
/**
\group_adt
@ -564,7 +564,7 @@ uint32_t buffer_pipe_read_avail(int32_t id);
* specified amount
*/
//uint8_t *buffer_pipe_read_get(int32_t id, uint32_t amount);
const uint8_t *buffer_pipe_read_get(int32_t id, uint32_t amount);
const uint8_t* buffer_pipe_read_get(int32_t id, uint32_t amount);
/**
\group_adt
@ -573,7 +573,7 @@ const uint8_t *buffer_pipe_read_get(int32_t id, uint32_t amount);
* @param[in] amount amount of bytes to move read cursor
* @return 0 on success
*/
int32_t buffer_pipe_read_stopped(int32_t id, uint32_t amount);
int32_t buffer_pipe_read_stopped(int32_t id, uint32_t amount);
/**
\group_adt
@ -593,7 +593,7 @@ uint32_t buffer_pipe_write_avail(int32_t id);
* @return pointer to write buffer, or NULL if requested amount
* is more than what is available in the buffer
*/
uint8_t *buffer_pipe_write_get(int32_t id, uint32_t size);
uint8_t* buffer_pipe_write_get(int32_t id, uint32_t size);
/**
\group_adt
@ -602,7 +602,7 @@ uint8_t *buffer_pipe_write_get(int32_t id, uint32_t size);
* @param[in] amount amount of bytes to move write cursor
* @return 0 on success
*/
int32_t buffer_pipe_write_stopped(int32_t id, uint32_t amount);
int32_t buffer_pipe_write_stopped(int32_t id, uint32_t amount);
/**
\group_adt
@ -613,7 +613,7 @@ int32_t buffer_pipe_write_stopped(int32_t id, uint32_t amount);
* @param[in] id ID of buffer_pipe
* @return 0 on success
*/
int32_t buffer_pipe_done(int32_t id);
int32_t buffer_pipe_done(int32_t id);
/**
\group_adt
@ -782,7 +782,7 @@ int32_t atoi(const uint8_t* str, int32_t size);
* @param[in] len length of \p str
* @return 0
*/
uint32_t debug_print_str_start(const uint8_t *str, uint32_t len);
uint32_t debug_print_str_start(const uint8_t* str, uint32_t len);
/**
\group_debug
@ -792,7 +792,7 @@ uint32_t debug_print_str_start(const uint8_t *str, uint32_t len);
* @param[in] len length of \p str
* @return 0
*/
uint32_t debug_print_str_nonl(const uint8_t *str, uint32_t len);
uint32_t debug_print_str_nonl(const uint8_t* str, uint32_t len);
/**
\group_string
@ -823,7 +823,7 @@ int32_t map_new(int32_t keysize, int32_t valuesize);
* @return 1 - if key didn't exist before
* @return <0 - if ksize doesn't match keysize specified at table creation
*/
int32_t map_addkey(const uint8_t *key, int32_t ksize, int32_t id);
int32_t map_addkey(const uint8_t* key, int32_t ksize, int32_t id);
/**
\group_adt
@ -834,7 +834,7 @@ int32_t map_addkey(const uint8_t *key, int32_t ksize, int32_t id);
* @return 0 - if update was successful
* @return <0 - if there is no last key
*/
int32_t map_setvalue(const uint8_t *value, int32_t vsize, int32_t id);
int32_t map_setvalue(const uint8_t* value, int32_t vsize, int32_t id);
/**
\group_adt
@ -903,7 +903,7 @@ int32_t map_done(int32_t id);
* match_pos + \p len < \p maxpos
* @return offset in the current file if match is found, -1 otherwise
*/
int32_t file_find_limit(const uint8_t *data, uint32_t len, int32_t maxpos);
int32_t file_find_limit(const uint8_t* data, uint32_t len, int32_t maxpos);
/* ------------- Engine Query ----------------------------------------------- */
/**
@ -971,7 +971,7 @@ int32_t input_switch(int32_t extracted_file);
* @param[in] len - size of \p env
* @return 0
*/
uint32_t get_environment(struct cli_environment *env, uint32_t len);
uint32_t get_environment(struct cli_environment* env, uint32_t len);
/**
\group_env
@ -984,7 +984,7 @@ uint32_t get_environment(struct cli_environment *env, uint32_t len);
* @return 1 - JIT disabled
* @return 2 - fully disabled
*/
uint32_t disable_bytecode_if(const int8_t *reason, uint32_t len, uint32_t cond);
uint32_t disable_bytecode_if(const int8_t* reason, uint32_t len, uint32_t cond);
/**
\group_env
@ -1011,7 +1011,7 @@ uint32_t disable_jit_if(const int8_t* reason, uint32_t len, uint32_t cond);
* @return 1 - lhs > rhs
*/
int32_t version_compare(const uint8_t* lhs, uint32_t lhs_len,
const uint8_t* rhs, uint32_t rhs_len);
const uint8_t* rhs, uint32_t rhs_len);
/**
\group_env
@ -1077,7 +1077,7 @@ uint32_t pdf_getobjsize(int32_t objidx);
* @return NULL - invalid objidx/amount
* @return pointer - pointer to original object */
//uint8_t *pdf_getobj(int32_t objidx, uint32_t amount);
const uint8_t *pdf_getobj(int32_t objidx, uint32_t amount);
const uint8_t* pdf_getobj(int32_t objidx, uint32_t amount);
/**
\group_pdf
@ -1303,7 +1303,7 @@ int32_t json_get_int(int32_t objid);
* @param[in] scan_options enum value for desired scan option category.
* @return CL_SCAN_<OPTION>_* flags
*/
uint32_t engine_scan_options_ex(const uint8_t *option_name, uint32_t name_len);
uint32_t engine_scan_options_ex(const uint8_t* option_name, uint32_t name_len);
/* ----------------- END 0.101 APIs ---------------------------------- */
#endif

View file

@ -39,7 +39,8 @@
#include <sys/utsname.h>
#endif
#define CHECK_ARCH(a) if (!strcmp(TARGET_ARCH_TYPE, #a)) env->arch = arch_##a
#define CHECK_ARCH(a) \
if (!strcmp(TARGET_ARCH_TYPE, #a)) env->arch = arch_##a
extern int have_clamjit;
@ -52,22 +53,22 @@ static void cli_print_environment(struct cli_environment *env)
/* the space separated groups can be a concrete value, or 0xff for ANY */
cli_dbgmsg("environment detected:\n");
cli_dbgmsg("check_platform(0x%08x, 0x%08x, 0x%08x)\n",
id_a, id_b, id_c);
id_a, id_b, id_c);
cli_dbgmsg("check_platform(0x%02x %01x %01x %02x %02x,"
"0x%01x %01x %02x %02x %02x,"
"0x%02x %02x %02x %02x)\n",
env->os_category, env->arch, env->compiler,
env->functionality_level,
env->dconf_level,
"0x%01x %01x %02x %02x %02x,"
"0x%02x %02x %02x %02x)\n",
env->os_category, env->arch, env->compiler,
env->functionality_level,
env->dconf_level,
env->big_endian,
env->sizeof_ptr,
(env->cpp_version >> 16)&0xff,
(env->cpp_version >> 8)&0xff,
env->cpp_version&0xff,
env->os_features,
(env->c_version >> 16)&0xff,
(env->c_version >> 8)&0xff,
env->c_version&0xff);
(env->cpp_version >> 16) & 0xff,
(env->cpp_version >> 8) & 0xff,
env->cpp_version & 0xff,
env->os_features,
(env->c_version >> 16) & 0xff,
(env->c_version >> 8) & 0xff,
env->c_version & 0xff);
cli_dbgmsg("check_platform( OS CPU COM FL DCONF,BE PTR CXX VV.VV.VV, FLG CC VV.VV.VV)\n");
cli_dbgmsg("Engine version: %s\n", env->engine_version);
cli_dbgmsg("Host triple: %s\n", env->triple);
@ -89,14 +90,14 @@ static int detect_PaX(void)
int pax = 0;
FILE *f = fopen("/proc/self/status", "r");
if (!f)
return 0;
return 0;
while (fgets(line, sizeof(line), f)) {
if (!memcmp(line, "PaX:", 4)) {
pax = 1;
if (!strchr(line,'m'))
pax = 2;
break;
}
if (!memcmp(line, "PaX:", 4)) {
pax = 1;
if (!strchr(line, 'm'))
pax = 2;
break;
}
}
fclose(f);
return pax;
@ -107,37 +108,37 @@ static int detect_SELinux(void)
char line[128];
int selinux = 0;
int enforce = 0;
FILE *f = fopen("/proc/filesystems", "r");
FILE *f = fopen("/proc/filesystems", "r");
if (!f) {
f = fopen("/selinux/enforce", "r");
f = fopen("/selinux/enforce", "r");
if (!f && errno == EACCES)
return 2;
if (f) {
if (fscanf(f, "%d", &enforce) == 1)
selinux = 2;
fclose(f);
}
return selinux;
return 2;
if (f) {
if (fscanf(f, "%d", &enforce) == 1)
selinux = 2;
fclose(f);
}
return selinux;
}
while (fgets(line, sizeof(line), f)) {
if (strstr(line, "selinuxfs\n")) {
selinux = 1;
break;
}
if (strstr(line, "selinuxfs\n")) {
selinux = 1;
break;
}
}
fclose(f);
if (!selinux)
return 0;
return 0;
f = fopen("/selinux/enforce", "r");
if (f) {
if (fscanf(f, "%d", &enforce) == 1) {
if (enforce == 1)
selinux = 2;
if (enforce == -1)
selinux = 0;
}
fclose(f);
if (fscanf(f, "%d", &enforce) == 1) {
if (enforce == 1)
selinux = 2;
if (enforce == -1)
selinux = 0;
}
fclose(f);
}
return selinux;
}
@ -146,24 +147,24 @@ static void detect_os_features(uint8_t *os_features)
{
int features = 0;
switch (detect_PaX()) {
case 2:
features |= 1 << feature_pax_mprotect;
/* fall through */
case 1:
features |= 1 << feature_pax;
break;
default:
break;
case 2:
features |= 1 << feature_pax_mprotect;
/* fall through */
case 1:
features |= 1 << feature_pax;
break;
default:
break;
}
switch (detect_SELinux()) {
case 2:
features |= 1 << feature_selinux_enforcing;
/* fall through */
case 1:
features |= 1 << feature_selinux;
break;
default:
break;
case 2:
features |= 1 << feature_selinux_enforcing;
/* fall through */
case 1:
features |= 1 << feature_selinux;
break;
default:
break;
}
*os_features = features;
@ -185,15 +186,15 @@ void cli_detect_environment(struct cli_environment *env)
#if WORDS_BIGENDIAN == 0
env->big_endian = 0;
#else
env->big_endian = 1;
env->big_endian = 1;
#endif
env->sizeof_ptr = sizeof(void*);
env->sizeof_ptr = sizeof(void *);
/* -- Detect arch -- */
CHECK_ARCH(i386);
else CHECK_ARCH(x86_64);
else if (!strcmp(TARGET_ARCH_TYPE,"amd64")) env->arch = arch_x86_64;
else if (!strcmp(TARGET_ARCH_TYPE,"ppc")) env->arch = arch_ppc32;/* llvm will fix ppc64 */
else if (!strcmp(TARGET_ARCH_TYPE, "amd64")) env->arch = arch_x86_64;
else if (!strcmp(TARGET_ARCH_TYPE, "ppc")) env->arch = arch_ppc32; /* llvm will fix ppc64 */
else CHECK_ARCH(arm);
else CHECK_ARCH(sparc);
else CHECK_ARCH(sparc64);
@ -248,29 +249,29 @@ void cli_detect_environment(struct cli_environment *env)
/* check GNUC last, because some other compilers might define it */
#ifdef __INTEL_COMPILER
env->compiler = compiler_intel;
env->compiler = compiler_intel;
env->c_version = __INTEL_COMPILER;
#elif defined(_MSC_VER)
env->compiler = compiler_msc;
env->compiler = compiler_msc;
env->c_version = _MSC_VER;
#elif defined(__SUNPRO_C)
env->compiler = compiler_sun;
env->c_version = __SUNPRO_C;
env->compiler = compiler_sun;
env->c_version = __SUNPRO_C;
#elif defined(__GNUC__)
#ifdef __clang__
env->compiler = compiler_clang;
env->compiler = compiler_clang;
#elif defined(__llvm__)
env->compiler = compiler_llvm;
#else
env->compiler = compiler_gnuc;
#endif
env->c_version =
MAKE_VERSION(0, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
MAKE_VERSION(0, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
#else
env->compiler = compiler_other;
env->c_version = 0;
env->compiler = compiler_other;
env->c_version = 0;
#endif
env->cpp_version = 0;
@ -278,40 +279,40 @@ void cli_detect_environment(struct cli_environment *env)
/* engine */
env->functionality_level = cl_retflevel();
env->dconf_level = CL_FLEVEL_DCONF;
env->dconf_level = CL_FLEVEL_DCONF;
INIT_STRFIELD(env->engine_version, cl_retver());
#ifdef HAVE_UNAME_SYSCALL
{
struct utsname name;
if (uname(&name) == 0) {
INIT_STRFIELD(env->sysname, name.sysname);
INIT_STRFIELD(env->release, name.release);
INIT_STRFIELD(env->version, name.version);
INIT_STRFIELD(env->machine, name.machine);
}
struct utsname name;
if (uname(&name) == 0) {
INIT_STRFIELD(env->sysname, name.sysname);
INIT_STRFIELD(env->release, name.release);
INIT_STRFIELD(env->version, name.version);
INIT_STRFIELD(env->machine, name.machine);
}
}
#endif
#ifdef _WIN32
{
OSVERSIONINFOEX info;
info.dwOSVersionInfoSize = sizeof(info);
if (GetVersionEx((OSVERSIONINFO *)&info) != 0 && info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
if (info.wProductType == VER_NT_WORKSTATION)
INIT_STRFIELD(env->sysname, "Microsoft Windows");
else
INIT_STRFIELD(env->sysname, "Microsoft Windows Server");
snprintf((char*)env->release, sizeof(env->release), "%d.%d SP%d.%d",
info.dwMajorVersion, info.dwMinorVersion,
info.wServicePackMajor, info.wServicePackMinor);
snprintf((char*)env->version, sizeof(env->version),"Build %d",
info.dwBuildNumber);
}
OSVERSIONINFOEX info;
info.dwOSVersionInfoSize = sizeof(info);
if (GetVersionEx((OSVERSIONINFO *)&info) != 0 && info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
if (info.wProductType == VER_NT_WORKSTATION)
INIT_STRFIELD(env->sysname, "Microsoft Windows");
else
INIT_STRFIELD(env->sysname, "Microsoft Windows Server");
snprintf((char *)env->release, sizeof(env->release), "%d.%d SP%d.%d",
info.dwMajorVersion, info.dwMinorVersion,
info.wServicePackMajor, info.wServicePackMinor);
snprintf((char *)env->version, sizeof(env->version), "Build %d",
info.dwBuildNumber);
}
}
#endif
if (!env->sysname[0]) {
INIT_STRFIELD(env->sysname, TARGET_OS_TYPE);
INIT_STRFIELD(env->sysname, TARGET_OS_TYPE);
}
detect_os_features(&env->os_features);
@ -319,10 +320,10 @@ void cli_detect_environment(struct cli_environment *env)
cli_detect_env_jit(env);
env->platform_id_a = (env->os_category << 24) | (env->arch << 20) |
(env->compiler << 16) | (env->functionality_level << 8) |
(env->dconf_level);
(env->compiler << 16) | (env->functionality_level << 8) |
(env->dconf_level);
env->platform_id_b = (env->big_endian << 28) | (env->sizeof_ptr << 24) |
env->cpp_version;
env->cpp_version;
env->platform_id_c = (env->os_features << 24) | env->c_version;
cli_print_environment(env);
}

View file

@ -28,92 +28,92 @@
#define BYTECODE_DETECT_H
/* mostly from m4/acinclude.m4 */
enum arch_list {
arch_unknown=0,
arch_i386,
arch_x86_64,
arch_ppc32,
arch_ppc64,
arch_arm,
arch_sparc,
arch_sparc64,
arch_mips,
arch_mips64,
arch_alpha,
arch_hppa1,
arch_hppa2,
arch_m68k,
arch_ANY = 0xf
arch_unknown = 0,
arch_i386,
arch_x86_64,
arch_ppc32,
arch_ppc64,
arch_arm,
arch_sparc,
arch_sparc64,
arch_mips,
arch_mips64,
arch_alpha,
arch_hppa1,
arch_hppa2,
arch_m68k,
arch_ANY = 0xf
};
/* from ClamAV's configure.in */
enum os_kind_conf {
os_unknown=0,
os_aix,
os_beos,
os_bsd,
os_darwin,
os_gnu_hurd,
os_hpux,
os_interix,
os_irix,
os_kfreebsd_gnu,
os_linux,
os_os2,
os_osf,
os_qnx6,
os_solaris,
os_win32,
os_win64,
os_generic,
os_ANY = 0xff
os_unknown = 0,
os_aix,
os_beos,
os_bsd,
os_darwin,
os_gnu_hurd,
os_hpux,
os_interix,
os_irix,
os_kfreebsd_gnu,
os_linux,
os_os2,
os_osf,
os_qnx6,
os_solaris,
os_win32,
os_win64,
os_generic,
os_ANY = 0xff
};
enum os_kind_llvm {
llvm_os_UnknownOS=0,
llvm_os_AuroraUX,
llvm_os_Cygwin,
llvm_os_Darwin,
llvm_os_DragonFly,
llvm_os_FreeBSD,
llvm_os_Linux,
llvm_os_Lv2,
llvm_os_MinGW32,
llvm_os_MinGW64,
llvm_os_NetBSD,
llvm_os_OpenBSD,
llvm_os_Psp,
llvm_os_Solaris,
llvm_os_Win32,
llvm_os_Haiku,
llvm_os_Minix,
llvm_os_ANY = 0xff
llvm_os_UnknownOS = 0,
llvm_os_AuroraUX,
llvm_os_Cygwin,
llvm_os_Darwin,
llvm_os_DragonFly,
llvm_os_FreeBSD,
llvm_os_Linux,
llvm_os_Lv2,
llvm_os_MinGW32,
llvm_os_MinGW64,
llvm_os_NetBSD,
llvm_os_OpenBSD,
llvm_os_Psp,
llvm_os_Solaris,
llvm_os_Win32,
llvm_os_Haiku,
llvm_os_Minix,
llvm_os_ANY = 0xff
};
/* the ones from clamconf */
enum compiler_list {
compiler_unknown = 0,
compiler_gnuc,
compiler_llvm,
compiler_clang,
compiler_intel,
compiler_msc,
compiler_sun,
compiler_other,
compiler_ANY = 0xf
compiler_unknown = 0,
compiler_gnuc,
compiler_llvm,
compiler_clang,
compiler_intel,
compiler_msc,
compiler_sun,
compiler_other,
compiler_ANY = 0xf
};
enum endian_list {
endian_little=0,
endian_big=1,
endian_ANY=0xf
endian_little = 0,
endian_big = 1,
endian_ANY = 0xf
};
enum os_feature_bits {
feature_map_rwx = 0,
feature_selinux = 1,
feature_map_rwx = 0,
feature_selinux = 1,
feature_selinux_enforcing = 2,
feature_pax = 3,
feature_pax_mprotect = 4
feature_pax = 3,
feature_pax_mprotect = 4
};
struct cli_environment {
@ -125,21 +125,21 @@ struct cli_environment {
/* engine */
uint32_t functionality_level;
uint32_t dconf_level;
int8_t engine_version[65];
int8_t engine_version[65];
/* detailed runtime info */
int8_t triple[65];/* LLVM only */
int8_t cpu[65];/* LLVM only */
int8_t triple[65]; /* LLVM only */
int8_t cpu[65]; /* LLVM only */
/* uname */
int8_t sysname[65];
int8_t release[65];
int8_t version[65];
int8_t machine[65];
int8_t sysname[65];
int8_t release[65];
int8_t version[65];
int8_t machine[65];
/* build time */
uint8_t big_endian;
uint8_t sizeof_ptr;
uint8_t arch;
uint8_t os_category;/* from configure */
uint8_t os;/* from LLVM if available */
uint8_t os_category; /* from configure */
uint8_t os; /* from LLVM if available */
uint8_t compiler;
uint8_t has_jit_compiled;
uint8_t os_features;
@ -147,11 +147,12 @@ struct cli_environment {
};
#ifndef __CLAMBC__
#define MAKE_VERSION(a,b,c,d) ((a << 24) | (b << 16) | (c << 8) | d)
#define INIT_STRFIELD(field, value) do {\
strncpy((char*)(field), (value), sizeof(field)-1);\
(field)[sizeof(field)-1]=0;\
} while (0)
#define MAKE_VERSION(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | d)
#define INIT_STRFIELD(field, value) \
do { \
strncpy((char *)(field), (value), sizeof(field) - 1); \
(field)[sizeof(field) - 1] = 0; \
} while (0)
#endif
void cli_detect_env_jit(struct cli_environment *env);

View file

@ -33,14 +33,14 @@
int cli_bytecode_prepare_jit(struct cli_all_bc *bcs)
{
unsigned i;
for (i=0;i<bcs->count;i++) {
if (bcs->all_bcs[i].state == bc_skip)
continue;
if (bcs->all_bcs[i].state != bc_loaded &&
bcs->all_bcs[i].kind != BC_STARTUP) {
cli_warnmsg("Cannot prepare for JIT, because it has already been converted to interpreter\n");
return CL_EBYTECODE;
}
for (i = 0; i < bcs->count; i++) {
if (bcs->all_bcs[i].state == bc_skip)
continue;
if (bcs->all_bcs[i].state != bc_loaded &&
bcs->all_bcs[i].kind != BC_STARTUP) {
cli_warnmsg("Cannot prepare for JIT, because it has already been converted to interpreter\n");
return CL_EBYTECODE;
}
}
cli_dbgmsg("Cannot prepare for JIT, LLVM is not compiled or not linked\n");
return CL_EBYTECODE;
@ -68,8 +68,9 @@ int cli_bytecode_done_jit(struct cli_all_bc *allbc, int partial)
return CL_SUCCESS;
}
void cli_bytecode_debug(int argc, char **argv) {
/* Empty */
void cli_bytecode_debug(int argc, char **argv)
{
/* Empty */
UNUSEDPARAM(argc);
UNUSEDPARAM(argv);
}
@ -79,14 +80,16 @@ int bytecode_init(void)
return 0;
}
void cli_bytecode_debug_printsrc(const struct cli_bc_ctx *ctx) {
void cli_bytecode_debug_printsrc(const struct cli_bc_ctx *ctx)
{
/* Empty */
UNUSEDPARAM(ctx);
}
void cli_bytecode_printversion(void) {
printf("LLVM is not compiled or not linked\n");
void cli_bytecode_printversion(void)
{
printf("LLVM is not compiled or not linked\n");
}
int have_clamjit=0;
int have_clamjit = 0;
void cli_printcxxver()
{
/* Empty */

View file

@ -39,8 +39,8 @@ typedef uint16_t bbid_t;
typedef uint16_t funcid_t;
struct cli_bc_callop {
operand_t* ops;
uint16_t* opsizes;
operand_t *ops;
uint16_t *opsizes;
funcid_t funcid;
uint8_t numOps;
};
@ -54,7 +54,7 @@ struct branch {
struct cli_bc_cast {
uint64_t mask;
operand_t source;
uint8_t size;/* 0: 1-bit, 1: 8b, 2: 16b, 3: 32b, 4: 64b */
uint8_t size; /* 0: 1-bit, 1: 8b, 2: 16b, 3: 32b, 4: 64b */
};
typedef uint8_t interp_op_t;
@ -62,7 +62,7 @@ struct cli_bc_inst {
enum bc_opcode opcode;
uint16_t type;
operand_t dest;
interp_op_t interp_op;/* opcode for interpreter */
interp_op_t interp_op; /* opcode for interpreter */
union {
operand_t unaryop;
struct cli_bc_cast cast;
@ -83,9 +83,9 @@ struct cli_bc_func {
uint8_t numArgs;
uint16_t numLocals;
uint32_t numInsts;
uint32_t numValues;/* without constants */
uint32_t numValues; /* without constants */
uint32_t numConstants;
uint32_t numBytes;/* stack size */
uint32_t numBytes; /* stack size */
uint16_t numBB;
uint16_t returnType;
uint16_t *types;
@ -105,12 +105,12 @@ struct cli_bc_dbgnode_element {
struct cli_bc_dbgnode {
unsigned numelements;
struct cli_bc_dbgnode_element* elements;
struct cli_bc_dbgnode_element *elements;
};
#define MAX_OP ~0u
enum trace_level {
trace_none=0,
trace_none = 0,
trace_func,
trace_param,
trace_scope,
@ -131,7 +131,7 @@ struct bc_inflate {
z_stream stream;
int32_t from;
int32_t to;
int8_t needSync;
int8_t needSync;
};
struct bc_jsnorm {
@ -162,7 +162,7 @@ enum bc_events {
};
struct cli_bc_ctx {
uint8_t timeout;/* must be first byte in struct! */
uint8_t timeout; /* must be first byte in struct! */
uint16_t funcid;
unsigned numParams;
/* id and params of toplevel function called */
@ -185,7 +185,7 @@ struct cli_bc_ctx {
uint32_t lsigoff[64];
uint32_t pdf_nobjs;
struct pdf_obj **pdf_objs;
uint32_t* pdf_flags;
uint32_t *pdf_flags;
uint32_t pdf_size;
uint32_t pdf_startoff;
unsigned pdf_phase;
@ -210,14 +210,14 @@ struct cli_bc_ctx {
unsigned line;
unsigned col;
mpool_t *mpool;
struct bc_inflate* inflates;
struct bc_inflate *inflates;
struct bc_buffer *buffers;
unsigned nbuffers;
unsigned nhashsets;
unsigned njsnorms;
unsigned jsnormwritten;
struct cli_hashset *hashsets;
struct bc_jsnorm* jsnorms;
struct bc_jsnorm *jsnorms;
char *jsnormdir;
struct cli_map *maps;
unsigned nmaps;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -32,7 +32,7 @@
#include <openssl/err.h>
/* Certain OSs already use 64bit variables in their stat struct */
#if ( !defined(__FreeBSD__) && !defined(__APPLE__) )
#if (!defined(__FreeBSD__) && !defined(__APPLE__))
#define STAT64_BLACKLIST 1
#else
#define STAT64_BLACKLIST 0
@ -46,7 +46,7 @@
#define CLAMSTAT stat64
#define LSTAT lstat64
#define FSTAT fstat64
#define safe_open(a, b) open(a, b|O_LARGEFILE)
#define safe_open(a, b) open(a, b | O_LARGEFILE)
#else
#define STATBUF struct stat
@ -68,8 +68,7 @@
#include "cltypes.h"
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
#define CL_COUNT_PRECISION 4096
@ -77,7 +76,7 @@ extern "C"
/* return codes */
typedef enum cl_error_t {
/* libclamav specific */
CL_CLEAN = 0,
CL_CLEAN = 0,
CL_SUCCESS = 0,
CL_VIRUS,
CL_ENULLARG,
@ -110,7 +109,7 @@ typedef enum cl_error_t {
CL_EMAXFILES,
CL_EFORMAT,
CL_EPARSE,
CL_EBYTECODE,/* may be reported in testmode */
CL_EBYTECODE, /* may be reported in testmode */
CL_EBYTECODE_TESTFAIL, /* may be reported in testmode */
/* c4w error codes */
@ -250,7 +249,7 @@ int cl_initialize_crypto(void);
*/
void cl_cleanup_crypto(void);
#define CL_INIT_DEFAULT 0x0
#define CL_INIT_DEFAULT 0x0
/**
* @brief Initialize the ClamAV library.
*
@ -269,56 +268,56 @@ extern int cl_init(unsigned int initoptions);
extern struct cl_engine *cl_engine_new(void);
enum cl_engine_field {
CL_ENGINE_MAX_SCANSIZE, /* uint64_t */
CL_ENGINE_MAX_FILESIZE, /* uint64_t */
CL_ENGINE_MAX_RECURSION, /* uint32_t */
CL_ENGINE_MAX_FILES, /* uint32_t */
CL_ENGINE_MIN_CC_COUNT, /* uint32_t */
CL_ENGINE_MIN_SSN_COUNT, /* uint32_t */
CL_ENGINE_PUA_CATEGORIES, /* (char *) */
CL_ENGINE_DB_OPTIONS, /* uint32_t */
CL_ENGINE_DB_VERSION, /* uint32_t */
CL_ENGINE_DB_TIME, /* time_t */
CL_ENGINE_AC_ONLY, /* uint32_t */
CL_ENGINE_AC_MINDEPTH, /* uint32_t */
CL_ENGINE_AC_MAXDEPTH, /* uint32_t */
CL_ENGINE_TMPDIR, /* (char *) */
CL_ENGINE_KEEPTMP, /* uint32_t */
CL_ENGINE_BYTECODE_SECURITY, /* uint32_t */
CL_ENGINE_BYTECODE_TIMEOUT, /* uint32_t */
CL_ENGINE_BYTECODE_MODE, /* uint32_t */
CL_ENGINE_MAX_EMBEDDEDPE, /* uint64_t */
CL_ENGINE_MAX_HTMLNORMALIZE, /* uint64_t */
CL_ENGINE_MAX_HTMLNOTAGS, /* uint64_t */
CL_ENGINE_MAX_SCRIPTNORMALIZE, /* uint64_t */
CL_ENGINE_MAX_ZIPTYPERCG, /* uint64_t */
CL_ENGINE_FORCETODISK, /* uint32_t */
CL_ENGINE_DISABLE_CACHE, /* uint32_t */
CL_ENGINE_DISABLE_PE_STATS, /* uint32_t */
CL_ENGINE_STATS_TIMEOUT, /* uint32_t */
CL_ENGINE_MAX_PARTITIONS, /* uint32_t */
CL_ENGINE_MAX_ICONSPE, /* uint32_t */
CL_ENGINE_MAX_RECHWP3, /* uint32_t */
CL_ENGINE_TIME_LIMIT, /* uint32_t */
CL_ENGINE_PCRE_MATCH_LIMIT, /* uint64_t */
CL_ENGINE_PCRE_RECMATCH_LIMIT, /* uint64_t */
CL_ENGINE_PCRE_MAX_FILESIZE, /* uint64_t */
CL_ENGINE_DISABLE_PE_CERTS, /* uint32_t */
CL_ENGINE_PE_DUMPCERTS /* uint32_t */
CL_ENGINE_MAX_SCANSIZE, /* uint64_t */
CL_ENGINE_MAX_FILESIZE, /* uint64_t */
CL_ENGINE_MAX_RECURSION, /* uint32_t */
CL_ENGINE_MAX_FILES, /* uint32_t */
CL_ENGINE_MIN_CC_COUNT, /* uint32_t */
CL_ENGINE_MIN_SSN_COUNT, /* uint32_t */
CL_ENGINE_PUA_CATEGORIES, /* (char *) */
CL_ENGINE_DB_OPTIONS, /* uint32_t */
CL_ENGINE_DB_VERSION, /* uint32_t */
CL_ENGINE_DB_TIME, /* time_t */
CL_ENGINE_AC_ONLY, /* uint32_t */
CL_ENGINE_AC_MINDEPTH, /* uint32_t */
CL_ENGINE_AC_MAXDEPTH, /* uint32_t */
CL_ENGINE_TMPDIR, /* (char *) */
CL_ENGINE_KEEPTMP, /* uint32_t */
CL_ENGINE_BYTECODE_SECURITY, /* uint32_t */
CL_ENGINE_BYTECODE_TIMEOUT, /* uint32_t */
CL_ENGINE_BYTECODE_MODE, /* uint32_t */
CL_ENGINE_MAX_EMBEDDEDPE, /* uint64_t */
CL_ENGINE_MAX_HTMLNORMALIZE, /* uint64_t */
CL_ENGINE_MAX_HTMLNOTAGS, /* uint64_t */
CL_ENGINE_MAX_SCRIPTNORMALIZE, /* uint64_t */
CL_ENGINE_MAX_ZIPTYPERCG, /* uint64_t */
CL_ENGINE_FORCETODISK, /* uint32_t */
CL_ENGINE_DISABLE_CACHE, /* uint32_t */
CL_ENGINE_DISABLE_PE_STATS, /* uint32_t */
CL_ENGINE_STATS_TIMEOUT, /* uint32_t */
CL_ENGINE_MAX_PARTITIONS, /* uint32_t */
CL_ENGINE_MAX_ICONSPE, /* uint32_t */
CL_ENGINE_MAX_RECHWP3, /* uint32_t */
CL_ENGINE_TIME_LIMIT, /* uint32_t */
CL_ENGINE_PCRE_MATCH_LIMIT, /* uint64_t */
CL_ENGINE_PCRE_RECMATCH_LIMIT, /* uint64_t */
CL_ENGINE_PCRE_MAX_FILESIZE, /* uint64_t */
CL_ENGINE_DISABLE_PE_CERTS, /* uint32_t */
CL_ENGINE_PE_DUMPCERTS /* uint32_t */
};
enum bytecode_security {
CL_BYTECODE_TRUST_ALL=0, /* obsolete */
CL_BYTECODE_TRUST_SIGNED, /* default */
CL_BYTECODE_TRUST_NOTHING /* paranoid setting */
CL_BYTECODE_TRUST_ALL = 0, /* obsolete */
CL_BYTECODE_TRUST_SIGNED, /* default */
CL_BYTECODE_TRUST_NOTHING /* paranoid setting */
};
enum bytecode_mode {
CL_BYTECODE_MODE_AUTO=0, /* JIT if possible, fallback to interpreter */
CL_BYTECODE_MODE_JIT, /* force JIT */
CL_BYTECODE_MODE_AUTO = 0, /* JIT if possible, fallback to interpreter */
CL_BYTECODE_MODE_JIT, /* force JIT */
CL_BYTECODE_MODE_INTERPRETER, /* force interpreter */
CL_BYTECODE_MODE_TEST, /* both JIT and interpreter, compare results, all failures are fatal */
CL_BYTECODE_MODE_OFF /* for query only, not settable */
CL_BYTECODE_MODE_TEST, /* both JIT and interpreter, compare results, all failures are fatal */
CL_BYTECODE_MODE_OFF /* for query only, not settable */
};
struct cli_section_hash {
@ -571,8 +570,8 @@ extern void cl_engine_set_clcb_sigload(struct cl_engine *engine, clcb_sigload ca
enum cl_msg {
/* leave room for more message levels in the future */
CL_MSG_INFO_VERBOSE = 32, /* verbose */
CL_MSG_WARN = 64, /* LibClamAV WARNING: */
CL_MSG_ERROR = 128/* LibClamAV ERROR: */
CL_MSG_WARN = 64, /* LibClamAV WARNING: */
CL_MSG_ERROR = 128 /* LibClamAV ERROR: */
};
/**
@ -646,8 +645,8 @@ extern void cl_engine_set_clcb_hash(struct cl_engine *engine, clcb_hash callback
* @return CL_VIRUS to blacklist
* @return CL_CLEAN to continue scanning
*/
typedef cl_error_t (*clcb_meta)(const char* container_type, unsigned long fsize_container, const char *filename,
unsigned long fsize_real, int is_encrypted, unsigned int filepos_container, void *context);
typedef cl_error_t (*clcb_meta)(const char *container_type, unsigned long fsize_container, const char *filename,
unsigned long fsize_real, int is_encrypted, unsigned int filepos_container, void *context);
/**
* @brief Set a custom archive metadata matching callback function.
*
@ -813,7 +812,7 @@ extern void cl_engine_set_clcb_stats_get_size(struct cl_engine *engine, clcb_sta
*
* @param cbdata The statistics data. Probably a pointer to a malloc'd struct.
*/
typedef char * (*clcb_stats_get_hostid)(void *cbdata);
typedef char *(*clcb_stats_get_hostid)(void *cbdata);
/**
* @brief Set a custom callback function to get the machine's unique host ID.
*
@ -844,7 +843,7 @@ extern void cl_engine_stats_enable(struct cl_engine *engine);
* @param scanoptions Scanning options.
* @return cl_error_t CL_CLEAN, CL_VIRUS, or an error code if an error occured during the scan.
*/
extern int cl_scandesc(int desc, const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options* scanoptions);
extern int cl_scandesc(int desc, const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options *scanoptions);
/**
* @brief Scan a file, given a file descriptor.
@ -860,7 +859,7 @@ extern int cl_scandesc(int desc, const char *filename, const char **virname, uns
* @param[in/out] context An opaque context structure allowing the caller to record details about the sample being scanned.
* @return cl_error_t CL_CLEAN, CL_VIRUS, or an error code if an error occured during the scan.
*/
extern int cl_scandesc_callback(int desc, const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options* scanoptions, void *context);
extern int cl_scandesc_callback(int desc, const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options *scanoptions, void *context);
/**
* @brief Scan a file, given a filename.
@ -872,7 +871,7 @@ extern int cl_scandesc_callback(int desc, const char *filename, const char **vir
* @param scanoptions Scanning options.
* @return cl_error_t CL_CLEAN, CL_VIRUS, or an error code if an error occured during the scan.
*/
extern int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options* scanoptions);
extern int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options *scanoptions);
/**
* @brief Scan a file, given a filename.
@ -887,7 +886,7 @@ extern int cl_scanfile(const char *filename, const char **virname, unsigned long
* @param[in/out] context An opaque context structure allowing the caller to record details about the sample being scanned.
* @return cl_error_t CL_CLEAN, CL_VIRUS, or an error code if an error occured during the scan.
*/
extern int cl_scanfile_callback(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options* scanoptions, void *context);
extern int cl_scanfile_callback(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options *scanoptions, void *context);
/* ----------------------------------------------------------------------------
* Database handling.
@ -899,16 +898,16 @@ extern const char *cl_retdbdir(void);
* CVD / database functions
*/
struct cl_cvd { /* field no. */
char *time; /* 2 */
unsigned int version; /* 3 */
unsigned int sigs; /* 4 */
unsigned int fl; /* 5 */
/* padding */
char *md5; /* 6 */
char *dsig; /* 7 */
char *builder; /* 8 */
unsigned int stime; /* 9 */
struct cl_cvd { /* field no. */
char *time; /* 2 */
unsigned int version; /* 3 */
unsigned int sigs; /* 4 */
unsigned int fl; /* 5 */
/* padding */
char *md5; /* 6 */
char *dsig; /* 7 */
char *builder; /* 8 */
unsigned int stime; /* 9 */
};
/**
@ -1053,7 +1052,7 @@ typedef struct cl_fmap cl_fmap_t;
* end-of-file, zero is returned. Otherwise, a -1 is returned
* and the global variable errno is set to indicate the error.
*/
typedef off_t (*clcb_pread)(void* handle, void *buf, size_t count, off_t offset);
typedef off_t (*clcb_pread)(void *handle, void *buf, size_t count, off_t offset);
/**
* @brief Open a map given a handle.
@ -1072,8 +1071,8 @@ typedef off_t (*clcb_pread)(void* handle, void *buf, size_t count, off_t offset)
* @param pread_cb A callback function to read data from the handle.
* @return cl_fmap_t* A map representing the handle interface.
*/
extern cl_fmap_t *cl_fmap_open_handle(void* handle, size_t offset, size_t len,
clcb_pread, int use_aging);
extern cl_fmap_t *cl_fmap_open_handle(void *handle, size_t offset, size_t len,
clcb_pread, int use_aging);
/**
* @brief Open a map given a buffer.
@ -1097,7 +1096,7 @@ extern cl_fmap_t *cl_fmap_open_memory(const void *start, size_t len);
*
* @param map Map to be closed.
*/
extern void cl_fmap_close(cl_fmap_t*);
extern void cl_fmap_close(cl_fmap_t *);
/**
* @brief Scan custom data.

View file

@ -29,7 +29,7 @@ struct bytecode_metadata {
uint64_t timestamp;
unsigned formatlevel;
unsigned minfunc, maxfunc;
unsigned maxresource;/* reserved */
unsigned maxresource; /* reserved */
unsigned targetExclude;
};
@ -38,97 +38,96 @@ struct bytecode_metadata {
#define BC_HEADER "ClamBC"
enum bc_opcode {
OP_BC_ADD=1,
OP_BC_SUB,
OP_BC_MUL,
OP_BC_UDIV,
OP_BC_SDIV,
OP_BC_UREM,
OP_BC_SREM,
OP_BC_SHL,
OP_BC_LSHR,
OP_BC_ASHR,
OP_BC_AND,
OP_BC_OR,
OP_BC_XOR,
OP_BC_ADD = 1,
OP_BC_SUB,
OP_BC_MUL,
OP_BC_UDIV,
OP_BC_SDIV,
OP_BC_UREM,
OP_BC_SREM,
OP_BC_SHL,
OP_BC_LSHR,
OP_BC_ASHR,
OP_BC_AND,
OP_BC_OR,
OP_BC_XOR,
OP_BC_TRUNC,
OP_BC_SEXT,
OP_BC_ZEXT,
OP_BC_TRUNC,
OP_BC_SEXT,
OP_BC_ZEXT,
OP_BC_BRANCH,
OP_BC_JMP,
OP_BC_RET,
OP_BC_RET_VOID,
OP_BC_BRANCH,
OP_BC_JMP,
OP_BC_RET,
OP_BC_RET_VOID,
OP_BC_ICMP_EQ,
OP_BC_ICMP_NE,
OP_BC_ICMP_UGT,
OP_BC_ICMP_UGE,
OP_BC_ICMP_ULT,
OP_BC_ICMP_ULE,
OP_BC_ICMP_SGT,
OP_BC_ICMP_SGE,
OP_BC_ICMP_SLE,
OP_BC_ICMP_SLT,
OP_BC_SELECT,
OP_BC_CALL_DIRECT,
OP_BC_CALL_API,
OP_BC_COPY,
OP_BC_GEP1,
OP_BC_GEPZ,
OP_BC_GEPN,
OP_BC_STORE,
OP_BC_LOAD,
OP_BC_MEMSET,
OP_BC_MEMCPY,
OP_BC_MEMMOVE,
OP_BC_MEMCMP,
OP_BC_ISBIGENDIAN,
OP_BC_ABORT,
OP_BC_BSWAP16,
OP_BC_BSWAP32,
OP_BC_BSWAP64,
OP_BC_PTRDIFF32,
OP_BC_PTRTOINT64,
OP_BC_INVALID /* last */
OP_BC_ICMP_EQ,
OP_BC_ICMP_NE,
OP_BC_ICMP_UGT,
OP_BC_ICMP_UGE,
OP_BC_ICMP_ULT,
OP_BC_ICMP_ULE,
OP_BC_ICMP_SGT,
OP_BC_ICMP_SGE,
OP_BC_ICMP_SLE,
OP_BC_ICMP_SLT,
OP_BC_SELECT,
OP_BC_CALL_DIRECT,
OP_BC_CALL_API,
OP_BC_COPY,
OP_BC_GEP1,
OP_BC_GEPZ,
OP_BC_GEPN,
OP_BC_STORE,
OP_BC_LOAD,
OP_BC_MEMSET,
OP_BC_MEMCPY,
OP_BC_MEMMOVE,
OP_BC_MEMCMP,
OP_BC_ISBIGENDIAN,
OP_BC_ABORT,
OP_BC_BSWAP16,
OP_BC_BSWAP32,
OP_BC_BSWAP64,
OP_BC_PTRDIFF32,
OP_BC_PTRTOINT64,
OP_BC_INVALID /* last */
};
static const unsigned char operand_counts[] = {
0,
/* ADD -> XOR */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* TRUNC -> ZEXT */
1, 1, 1,
/* BRANCH, JMP, RET */
3, 1, 1, 0,
/* ICMP */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* SELECT */
3,
/* CALLs have variable number of operands */
0, 0,
/* OP_BC_COPY */
2,
/* OP_BC_GEP1, OP_BC_GEPZ, OP_BC_GEPN, OP_BC_STORE, OP_BC_LOAD*/
3, 3, 0, 2, 1,
/* OP_MEM* */
3, 3, 3, 3,
/* OP_BC_ISBIGENDIAN */
0,
/* OP_BC_ABORT, OP_BSWAP*, OP_PTRDIFF32, OP_PTRINT64 */
0, 1, 1, 1, 2, 1
};
0,
/* ADD -> XOR */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* TRUNC -> ZEXT */
1, 1, 1,
/* BRANCH, JMP, RET */
3, 1, 1, 0,
/* ICMP */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* SELECT */
3,
/* CALLs have variable number of operands */
0, 0,
/* OP_BC_COPY */
2,
/* OP_BC_GEP1, OP_BC_GEPZ, OP_BC_GEPN, OP_BC_STORE, OP_BC_LOAD*/
3, 3, 0, 2, 1,
/* OP_MEM* */
3, 3, 3, 3,
/* OP_BC_ISBIGENDIAN */
0,
/* OP_BC_ABORT, OP_BSWAP*, OP_PTRDIFF32, OP_PTRINT64 */
0, 1, 1, 1, 2, 1};
enum bc_global {
_FIRST_GLOBAL = 0x8000,
GLOBAL_MATCH_COUNTS = 0x8000,
GLOBAL_KIND,
GLOBAL_VIRUSNAMES,
GLOBAL_PEDATA,
GLOBAL_FILESIZE,
GLOBAL_MATCH_OFFSETS,
_LAST_GLOBAL
_FIRST_GLOBAL = 0x8000,
GLOBAL_MATCH_COUNTS = 0x8000,
GLOBAL_KIND,
GLOBAL_VIRUSNAMES,
GLOBAL_PEDATA,
GLOBAL_FILESIZE,
GLOBAL_MATCH_OFFSETS,
_LAST_GLOBAL
};
#define BC_START_TID 69

View file

@ -39,31 +39,31 @@
#elif defined(_MSC_VER)
#include <stdint.h>
#else
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned char uint8_t;
#if SIZEOF_INT == 2
typedef signed int int16_t;
typedef unsigned int uint16_t;
typedef signed int int16_t;
typedef unsigned int uint16_t;
#elif SIZEOF_SHORT == 2
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
#endif
#if SIZEOF_INT == 4
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
#elif SIZEOF_LONG == 4
typedef signed long int32_t;
typedef unsigned long uint32_t;
typedef signed long int32_t;
typedef unsigned long uint32_t;
#endif
#if SIZEOF_LONG == 8
typedef signed long int64_t;
typedef unsigned long uint64_t;
typedef signed long int64_t;
typedef unsigned long uint64_t;
#elif SIZEOF_LONG_LONG == 8
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
#endif
#endif

View file

@ -47,16 +47,16 @@
*/
static size_t base64_len(const char *data, size_t len)
{
int padding=0;
int padding = 0;
size_t i;
if (!len)
return 0;
for (i=len-1; i > 0 && data[i] == '='; i--)
for (i = len - 1; i > 0 && data[i] == '='; i--)
padding++;
return (size_t)((3*len)/4 - padding);
return (size_t)((3 * len) / 4 - padding);
}
/** Decode a base64-encoded string
@ -71,7 +71,7 @@ void *cl_base64_decode(char *data, size_t len, void *obuf, size_t *olen, int one
BIO *bio, *b64;
void *buf;
buf = (obuf) ? obuf : malloc(base64_len(data, len)+1);
buf = (obuf) ? obuf : malloc(base64_len(data, len) + 1);
if (!(buf))
return NULL;
@ -130,14 +130,14 @@ char *cl_base64_encode(void *data, size_t len)
elen = (size_t)BIO_get_mem_data(bio, &buf);
/* Ensure we're dealing with a NULL-terminated string */
p = (char *)malloc(elen+1);
p = (char *)malloc(elen + 1);
if (NULL == p) {
BIO_free(b64);
return NULL;
}
memcpy((void *)p, (void *)buf, elen);
p[elen] = 0x00;
buf = p;
buf = p;
BIO_free_all(bio);
@ -151,12 +151,12 @@ int main(int argc, char *argv[])
char *plaintext, *encoded, *decoded;
unsigned char *sha_plaintext, *sha_decoded;
size_t len;
int ret=0;
int ret = 0;
unsigned int shalen;
initialize_crypto();
plaintext = (argv[1]) ? argv[1] : "Hello. This is dog";
plaintext = (argv[1]) ? argv[1] : "Hello. This is dog";
sha_plaintext = sha256(plaintext, strlen(plaintext), NULL, NULL);
if (!(sha_plaintext)) {
fprintf(stderr, "Could not generate sha256 of plaintext\n");

View file

@ -85,102 +85,100 @@ struct cpio_hdr_newc {
char check[8];
};
#define EC16(v, conv) (conv ? cbswap16(v) : v)
#define EC16(v, conv) (conv ? cbswap16(v) : v)
static void sanitname(char *name)
{
while(*name) {
if(!isascii(*name) || strchr("%\\\t\n\r", *name))
*name = '_';
name++;
while (*name) {
if (!isascii(*name) || strchr("%\\\t\n\r", *name))
*name = '_';
name++;
}
}
int cli_scancpio_old(cli_ctx *ctx)
{
struct cpio_hdr_old hdr_old;
char name[513];
unsigned int file = 0, trailer = 0;
uint32_t filesize, namesize, hdr_namesize;
int ret = CL_CLEAN, conv;
off_t pos = 0;
int virus_found = 0;
struct cpio_hdr_old hdr_old;
char name[513];
unsigned int file = 0, trailer = 0;
uint32_t filesize, namesize, hdr_namesize;
int ret = CL_CLEAN, conv;
off_t pos = 0;
int virus_found = 0;
while(fmap_readn(*ctx->fmap, &hdr_old, pos, sizeof(hdr_old)) == sizeof(hdr_old)) {
pos += sizeof(hdr_old);
if(!hdr_old.magic && trailer) {
while (fmap_readn(*ctx->fmap, &hdr_old, pos, sizeof(hdr_old)) == sizeof(hdr_old)) {
pos += sizeof(hdr_old);
if (!hdr_old.magic && trailer) {
ret = CL_SUCCESS;
goto leave;
goto leave;
}
if(hdr_old.magic == 070707) {
conv = 0;
} else if(hdr_old.magic == 0143561) {
conv = 1;
} else {
cli_dbgmsg("cli_scancpio_old: Invalid magic number\n");
ret = CL_EFORMAT;
if (hdr_old.magic == 070707) {
conv = 0;
} else if (hdr_old.magic == 0143561) {
conv = 1;
} else {
cli_dbgmsg("cli_scancpio_old: Invalid magic number\n");
ret = CL_EFORMAT;
goto leave;
}
}
cli_dbgmsg("CPIO: -- File %u --\n", ++file);
cli_dbgmsg("CPIO: -- File %u --\n", ++file);
if(hdr_old.namesize) {
hdr_namesize = EC16(hdr_old.namesize, conv);
namesize = MIN(sizeof(name), hdr_namesize);
if ((uint32_t)fmap_readn(*ctx->fmap, &name, pos, namesize) != namesize) {
cli_dbgmsg("cli_scancpio_old: Can't read file name\n");
return CL_EFORMAT;
}
pos += namesize;
name[namesize - 1] = 0;
sanitname(name);
cli_dbgmsg("CPIO: Name: %s\n", name);
if(!strcmp(name, "TRAILER!!!"))
trailer = 1;
if (hdr_old.namesize) {
hdr_namesize = EC16(hdr_old.namesize, conv);
namesize = MIN(sizeof(name), hdr_namesize);
if ((uint32_t)fmap_readn(*ctx->fmap, &name, pos, namesize) != namesize) {
cli_dbgmsg("cli_scancpio_old: Can't read file name\n");
return CL_EFORMAT;
}
pos += namesize;
name[namesize - 1] = 0;
sanitname(name);
cli_dbgmsg("CPIO: Name: %s\n", name);
if (!strcmp(name, "TRAILER!!!"))
trailer = 1;
if(namesize < hdr_namesize) {
if(hdr_namesize % 2)
hdr_namesize++;
pos += hdr_namesize - namesize;
} else if(hdr_namesize % 2)
pos++;
}
filesize = (uint32_t) (EC16(hdr_old.filesize[0], conv) << 16 | EC16(hdr_old.filesize[1], conv));
cli_dbgmsg("CPIO: Filesize: %u\n", filesize);
if(!filesize)
continue;
if (namesize < hdr_namesize) {
if (hdr_namesize % 2)
hdr_namesize++;
pos += hdr_namesize - namesize;
} else if (hdr_namesize % 2)
pos++;
}
filesize = (uint32_t)(EC16(hdr_old.filesize[0], conv) << 16 | EC16(hdr_old.filesize[1], conv));
cli_dbgmsg("CPIO: Filesize: %u\n", filesize);
if (!filesize)
continue;
if(cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS) {
if (cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS) {
if (!SCAN_ALLMATCHES)
return CL_VIRUS;
virus_found = 1;
}
if((EC16(hdr_old.mode, conv) & 0170000) != 0100000) {
cli_dbgmsg("CPIO: Not a regular file, skipping\n");
} else {
ret = cli_checklimits("cli_scancpio_old", ctx, filesize, 0, 0);
if(ret == CL_EMAXFILES) {
goto leave;
} else if(ret == CL_SUCCESS) {
ret = cli_map_scan(*ctx->fmap, pos, filesize, ctx, CL_TYPE_ANY);
if(ret == CL_VIRUS) {
if ((EC16(hdr_old.mode, conv) & 0170000) != 0100000) {
cli_dbgmsg("CPIO: Not a regular file, skipping\n");
} else {
ret = cli_checklimits("cli_scancpio_old", ctx, filesize, 0, 0);
if (ret == CL_EMAXFILES) {
goto leave;
} else if (ret == CL_SUCCESS) {
ret = cli_map_scan(*ctx->fmap, pos, filesize, ctx, CL_TYPE_ANY);
if (ret == CL_VIRUS) {
if (!SCAN_ALLMATCHES)
return ret;
virus_found = 1;
}
}
}
if(filesize % 2)
filesize++;
}
}
if (filesize % 2)
filesize++;
pos += filesize;
pos += filesize;
}
leave:
leave:
if (virus_found != 0)
return CL_VIRUS;
return ret;
@ -188,87 +186,85 @@ int cli_scancpio_old(cli_ctx *ctx)
int cli_scancpio_odc(cli_ctx *ctx)
{
struct cpio_hdr_odc hdr_odc;
char name[513], buff[12];
unsigned int file = 0, trailer = 0;
uint32_t filesize, namesize, hdr_namesize;
int ret = CL_CLEAN;
off_t pos = 0;
int virus_found = 0;
struct cpio_hdr_odc hdr_odc;
char name[513], buff[12];
unsigned int file = 0, trailer = 0;
uint32_t filesize, namesize, hdr_namesize;
int ret = CL_CLEAN;
off_t pos = 0;
int virus_found = 0;
while(fmap_readn(*ctx->fmap, &hdr_odc, pos, sizeof(hdr_odc)) == sizeof(hdr_odc)) {
pos += sizeof(hdr_odc);
if(!hdr_odc.magic[0] && trailer)
goto leave;
if(strncmp(hdr_odc.magic, "070707", 6)) {
cli_dbgmsg("cli_scancpio_odc: Invalid magic string\n");
ret = CL_EFORMAT;
while (fmap_readn(*ctx->fmap, &hdr_odc, pos, sizeof(hdr_odc)) == sizeof(hdr_odc)) {
pos += sizeof(hdr_odc);
if (!hdr_odc.magic[0] && trailer)
goto leave;
}
cli_dbgmsg("CPIO: -- File %u --\n", ++file);
strncpy(buff, hdr_odc.namesize, 6);
buff[6] = 0;
if(sscanf(buff, "%o", &hdr_namesize) != 1) {
cli_dbgmsg("cli_scancpio_odc: Can't convert name size\n");
ret = CL_EFORMAT;
if (strncmp(hdr_odc.magic, "070707", 6)) {
cli_dbgmsg("cli_scancpio_odc: Invalid magic string\n");
ret = CL_EFORMAT;
goto leave;
}
if(hdr_namesize) {
namesize = MIN(sizeof(name), hdr_namesize);
if ((uint32_t)fmap_readn(*ctx->fmap, &name, pos, namesize) != namesize) {
cli_dbgmsg("cli_scancpio_odc: Can't read file name\n");
ret = CL_EFORMAT;
}
cli_dbgmsg("CPIO: -- File %u --\n", ++file);
strncpy(buff, hdr_odc.namesize, 6);
buff[6] = 0;
if (sscanf(buff, "%o", &hdr_namesize) != 1) {
cli_dbgmsg("cli_scancpio_odc: Can't convert name size\n");
ret = CL_EFORMAT;
goto leave;
}
if (hdr_namesize) {
namesize = MIN(sizeof(name), hdr_namesize);
if ((uint32_t)fmap_readn(*ctx->fmap, &name, pos, namesize) != namesize) {
cli_dbgmsg("cli_scancpio_odc: Can't read file name\n");
ret = CL_EFORMAT;
goto leave;
}
pos += namesize;
name[namesize - 1] = 0;
sanitname(name);
cli_dbgmsg("CPIO: Name: %s\n", name);
if(!strcmp(name, "TRAILER!!!"))
trailer = 1;
}
pos += namesize;
name[namesize - 1] = 0;
sanitname(name);
cli_dbgmsg("CPIO: Name: %s\n", name);
if (!strcmp(name, "TRAILER!!!"))
trailer = 1;
if(namesize < hdr_namesize)
pos += hdr_namesize - namesize;
}
if (namesize < hdr_namesize)
pos += hdr_namesize - namesize;
}
strncpy(buff, hdr_odc.filesize, 11);
buff[11] = 0;
if(sscanf(buff, "%o", &filesize) != 1) {
cli_dbgmsg("cli_scancpio_odc: Can't convert file size\n");
ret = CL_EFORMAT;
strncpy(buff, hdr_odc.filesize, 11);
buff[11] = 0;
if (sscanf(buff, "%o", &filesize) != 1) {
cli_dbgmsg("cli_scancpio_odc: Can't convert file size\n");
ret = CL_EFORMAT;
goto leave;
}
cli_dbgmsg("CPIO: Filesize: %u\n", filesize);
if(!filesize)
continue;
}
cli_dbgmsg("CPIO: Filesize: %u\n", filesize);
if (!filesize)
continue;
if(cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS) {
if (cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS) {
if (!SCAN_ALLMATCHES)
return CL_VIRUS;
virus_found = 1;
}
ret = cli_checklimits("cli_scancpio_odc", ctx, filesize, 0, 0);
if(ret == CL_EMAXFILES) {
goto leave;
} else if(ret == CL_SUCCESS) {
ret = cli_map_scan(*ctx->fmap, pos, filesize, ctx, CL_TYPE_ANY);
if(ret == CL_VIRUS) {
ret = cli_checklimits("cli_scancpio_odc", ctx, filesize, 0, 0);
if (ret == CL_EMAXFILES) {
goto leave;
} else if (ret == CL_SUCCESS) {
ret = cli_map_scan(*ctx->fmap, pos, filesize, ctx, CL_TYPE_ANY);
if (ret == CL_VIRUS) {
if (!SCAN_ALLMATCHES)
return ret;
virus_found = 1;
}
}
}
pos += filesize;
pos += filesize;
}
leave:
leave:
if (virus_found != 0)
return CL_VIRUS;
return ret;
@ -276,95 +272,95 @@ int cli_scancpio_odc(cli_ctx *ctx)
int cli_scancpio_newc(cli_ctx *ctx, int crc)
{
struct cpio_hdr_newc hdr_newc;
char name[513], buff[9];
unsigned int file = 0, trailer = 0;
uint32_t filesize, namesize, hdr_namesize, pad;
int ret = CL_CLEAN;
off_t pos = 0;
int virus_found = 0;
struct cpio_hdr_newc hdr_newc;
char name[513], buff[9];
unsigned int file = 0, trailer = 0;
uint32_t filesize, namesize, hdr_namesize, pad;
int ret = CL_CLEAN;
off_t pos = 0;
int virus_found = 0;
memset(name, 0, 513);
while(fmap_readn(*ctx->fmap, &hdr_newc, pos, sizeof(hdr_newc)) == sizeof(hdr_newc)) {
pos += sizeof(hdr_newc);
if(!hdr_newc.magic[0] && trailer)
goto leave;
if((!crc && strncmp(hdr_newc.magic, "070701", 6)) || (crc && strncmp(hdr_newc.magic, "070702", 6))) {
cli_dbgmsg("cli_scancpio_newc: Invalid magic string\n");
ret = CL_EFORMAT;
while (fmap_readn(*ctx->fmap, &hdr_newc, pos, sizeof(hdr_newc)) == sizeof(hdr_newc)) {
pos += sizeof(hdr_newc);
if (!hdr_newc.magic[0] && trailer)
goto leave;
}
cli_dbgmsg("CPIO: -- File %u --\n", ++file);
strncpy(buff, hdr_newc.namesize, 8);
buff[8] = 0;
if(sscanf(buff, "%x", &hdr_namesize) != 1) {
cli_dbgmsg("cli_scancpio_newc: Can't convert name size\n");
ret = CL_EFORMAT;
if ((!crc && strncmp(hdr_newc.magic, "070701", 6)) || (crc && strncmp(hdr_newc.magic, "070702", 6))) {
cli_dbgmsg("cli_scancpio_newc: Invalid magic string\n");
ret = CL_EFORMAT;
goto leave;
}
if(hdr_namesize) {
namesize = MIN(sizeof(name), hdr_namesize);
if ((uint32_t)fmap_readn(*ctx->fmap, &name, pos, namesize) != namesize) {
cli_dbgmsg("cli_scancpio_newc: Can't read file name\n");
ret = CL_EFORMAT;
}
cli_dbgmsg("CPIO: -- File %u --\n", ++file);
strncpy(buff, hdr_newc.namesize, 8);
buff[8] = 0;
if (sscanf(buff, "%x", &hdr_namesize) != 1) {
cli_dbgmsg("cli_scancpio_newc: Can't convert name size\n");
ret = CL_EFORMAT;
goto leave;
}
if (hdr_namesize) {
namesize = MIN(sizeof(name), hdr_namesize);
if ((uint32_t)fmap_readn(*ctx->fmap, &name, pos, namesize) != namesize) {
cli_dbgmsg("cli_scancpio_newc: Can't read file name\n");
ret = CL_EFORMAT;
goto leave;
}
pos += namesize;
name[namesize - 1] = 0;
sanitname(name);
cli_dbgmsg("CPIO: Name: %s\n", name);
if(!strcmp(name, "TRAILER!!!"))
trailer = 1;
}
pos += namesize;
name[namesize - 1] = 0;
sanitname(name);
cli_dbgmsg("CPIO: Name: %s\n", name);
if (!strcmp(name, "TRAILER!!!"))
trailer = 1;
pad = (4 - (sizeof(hdr_newc) + hdr_namesize) % 4) % 4;
if(namesize < hdr_namesize) {
if(pad)
hdr_namesize += pad;
pos += hdr_namesize - namesize;
} else if(pad)
pos += pad;
}
pad = (4 - (sizeof(hdr_newc) + hdr_namesize) % 4) % 4;
if (namesize < hdr_namesize) {
if (pad)
hdr_namesize += pad;
pos += hdr_namesize - namesize;
} else if (pad)
pos += pad;
}
strncpy(buff, hdr_newc.filesize, 8);
buff[8] = 0;
if(sscanf(buff, "%x", &filesize) != 1) {
cli_dbgmsg("cli_scancpio_newc: Can't convert file size\n");
ret = CL_EFORMAT;
strncpy(buff, hdr_newc.filesize, 8);
buff[8] = 0;
if (sscanf(buff, "%x", &filesize) != 1) {
cli_dbgmsg("cli_scancpio_newc: Can't convert file size\n");
ret = CL_EFORMAT;
goto leave;
}
cli_dbgmsg("CPIO: Filesize: %u\n", filesize);
if(!filesize)
continue;
}
cli_dbgmsg("CPIO: Filesize: %u\n", filesize);
if (!filesize)
continue;
if(cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS) {
if (cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS) {
if (!SCAN_ALLMATCHES)
return CL_VIRUS;
virus_found = 1;
}
ret = cli_checklimits("cli_scancpio_newc", ctx, filesize, 0, 0);
if(ret == CL_EMAXFILES) {
goto leave;
} else if(ret == CL_SUCCESS) {
ret = cli_map_scan(*ctx->fmap, pos, filesize, ctx, CL_TYPE_ANY);
if(ret == CL_VIRUS) {
ret = cli_checklimits("cli_scancpio_newc", ctx, filesize, 0, 0);
if (ret == CL_EMAXFILES) {
goto leave;
} else if (ret == CL_SUCCESS) {
ret = cli_map_scan(*ctx->fmap, pos, filesize, ctx, CL_TYPE_ANY);
if (ret == CL_VIRUS) {
if (!SCAN_ALLMATCHES)
return ret;
virus_found = 1;
}
}
}
if((pad = filesize % 4))
filesize += (4 - pad);
if ((pad = filesize % 4))
filesize += (4 - pad);
pos += filesize;
pos += filesize;
}
leave:
leave:
if (virus_found != 0)
return CL_VIRUS;
return ret;

View file

@ -42,14 +42,14 @@
#define OID_2_16_840_1_101_3_4_2_3 "\x60\x86\x48\x01\x65\x03\x04\x02\x03"
#define OID_sha512 OID_2_16_840_1_101_3_4_2_3
int cli_crt_init(cli_crt *x509) {
int cli_crt_init(cli_crt *x509)
{
int ret;
if((ret = mp_init_multi(&x509->n, &x509->e, &x509->sig, NULL))) {
if ((ret = mp_init_multi(&x509->n, &x509->e, &x509->sig, NULL))) {
cli_errmsg("cli_crt_init: mp_init_multi failed with %d\n", ret);
return 1;
}
x509->name = NULL;
x509->name = NULL;
x509->isBlacklisted = 0;
x509->not_before = x509->not_after = 0;
x509->prev = x509->next = NULL;
@ -57,7 +57,8 @@ int cli_crt_init(cli_crt *x509) {
return 0;
}
void cli_crt_clear(cli_crt *x509) {
void cli_crt_clear(cli_crt *x509)
{
UNUSEDPARAM(x509);
mp_clear_multi(&x509->n, &x509->e, &x509->sig, NULL);
}
@ -77,28 +78,30 @@ void cli_crt_clear(cli_crt *x509) {
* lookup. That way, certs with more specific values can get added to the
* whitelist by functions like crtmgr_add and increase the probability of
* successful signature verification. */
cli_crt *crtmgr_whitelist_lookup(crtmgr *m, cli_crt *x509) {
cli_crt *crtmgr_whitelist_lookup(crtmgr *m, cli_crt *x509)
{
cli_crt *i;
for(i = m->crts; i; i = i->next) {
if(!i->isBlacklisted &&
x509->not_before >= i->not_before &&
x509->not_after <= i->not_after &&
(i->certSign | x509->certSign) == i->certSign &&
(i->codeSign | x509->codeSign) == i->codeSign &&
(i->timeSign | x509->timeSign) == i->timeSign &&
!memcmp(x509->subject, i->subject, sizeof(i->subject)) &&
!memcmp(x509->serial, i->serial, sizeof(i->serial)) &&
!memcmp(x509->issuer, i->issuer, sizeof(i->issuer)) &&
x509->hashtype == i->hashtype &&
!mp_cmp(&x509->n, &i->n) &&
!mp_cmp(&x509->e, &i->e)) {
for (i = m->crts; i; i = i->next) {
if (!i->isBlacklisted &&
x509->not_before >= i->not_before &&
x509->not_after <= i->not_after &&
(i->certSign | x509->certSign) == i->certSign &&
(i->codeSign | x509->codeSign) == i->codeSign &&
(i->timeSign | x509->timeSign) == i->timeSign &&
!memcmp(x509->subject, i->subject, sizeof(i->subject)) &&
!memcmp(x509->serial, i->serial, sizeof(i->serial)) &&
!memcmp(x509->issuer, i->issuer, sizeof(i->issuer)) &&
x509->hashtype == i->hashtype &&
!mp_cmp(&x509->n, &i->n) &&
!mp_cmp(&x509->e, &i->e)) {
return i;
}
}
return NULL;
}
cli_crt *crtmgr_blacklist_lookup(crtmgr *m, cli_crt *x509) {
cli_crt *crtmgr_blacklist_lookup(crtmgr *m, cli_crt *x509)
{
cli_crt *i;
for (i = m->crts; i; i = i->next) {
// The CRB rules are based on subject, serial, and public key,
@ -120,7 +123,8 @@ cli_crt *crtmgr_blacklist_lookup(crtmgr *m, cli_crt *x509) {
/* Determine whether x509 already exists in m. The fields compared depend on
* whether x509 is a blacklist entry or a trusted certificate */
cli_crt *crtmgr_lookup(crtmgr *m, cli_crt *x509) {
cli_crt *crtmgr_lookup(crtmgr *m, cli_crt *x509)
{
if (x509->isBlacklisted) {
return crtmgr_blacklist_lookup(m, x509);
} else {
@ -128,7 +132,8 @@ cli_crt *crtmgr_lookup(crtmgr *m, cli_crt *x509) {
}
}
int crtmgr_add(crtmgr *m, cli_crt *x509) {
int crtmgr_add(crtmgr *m, cli_crt *x509)
{
cli_crt *i;
int ret = 0;
@ -145,15 +150,15 @@ int crtmgr_add(crtmgr *m, cli_crt *x509) {
}
i = cli_malloc(sizeof(*i));
if(!i)
if (!i)
return 1;
if((ret = mp_init_multi(&i->n, &i->e, &i->sig, NULL))) {
if ((ret = mp_init_multi(&i->n, &i->e, &i->sig, NULL))) {
cli_warnmsg("crtmgr_add: failed to mp_init failed with %d\n", ret);
free(i);
return 1;
}
if((ret = mp_copy(&x509->n, &i->n)) || (ret = mp_copy(&x509->e, &i->e)) || (ret = mp_copy(&x509->sig, &i->sig))) {
if ((ret = mp_copy(&x509->n, &i->n)) || (ret = mp_copy(&x509->e, &i->e)) || (ret = mp_copy(&x509->sig, &i->sig))) {
cli_warnmsg("crtmgr_add: failed to mp_init failed with %d\n", ret);
cli_crt_clear(i);
free(i);
@ -172,16 +177,16 @@ int crtmgr_add(crtmgr *m, cli_crt *x509) {
memcpy(i->serial, x509->serial, sizeof(i->serial));
memcpy(i->issuer, x509->issuer, sizeof(i->issuer));
memcpy(i->tbshash, x509->tbshash, sizeof(i->tbshash));
i->not_before = x509->not_before;
i->not_after = x509->not_after;
i->hashtype = x509->hashtype;
i->certSign = x509->certSign;
i->codeSign = x509->codeSign;
i->timeSign = x509->timeSign;
i->not_before = x509->not_before;
i->not_after = x509->not_after;
i->hashtype = x509->hashtype;
i->certSign = x509->certSign;
i->codeSign = x509->codeSign;
i->timeSign = x509->timeSign;
i->isBlacklisted = x509->isBlacklisted;
i->next = m->crts;
i->prev = NULL;
if(m->crts)
i->next = m->crts;
i->prev = NULL;
if (m->crts)
m->crts->prev = i;
m->crts = i;
@ -189,20 +194,22 @@ int crtmgr_add(crtmgr *m, cli_crt *x509) {
return 0;
}
void crtmgr_init(crtmgr *m) {
m->crts = NULL;
void crtmgr_init(crtmgr *m)
{
m->crts = NULL;
m->items = 0;
}
void crtmgr_del(crtmgr *m, cli_crt *x509) {
void crtmgr_del(crtmgr *m, cli_crt *x509)
{
cli_crt *i;
for(i = m->crts; i; i = i->next) {
if(i==x509) {
if(i->prev)
for (i = m->crts; i; i = i->next) {
if (i == x509) {
if (i->prev)
i->prev->next = i->next;
else
m->crts = i->next;
if(i->next)
if (i->next)
i->next->prev = i->prev;
cli_crt_clear(x509);
if ((x509->name))
@ -214,12 +221,14 @@ void crtmgr_del(crtmgr *m, cli_crt *x509) {
}
}
void crtmgr_free(crtmgr *m) {
while(m->items)
void crtmgr_free(crtmgr *m)
{
while (m->items)
crtmgr_del(m, m->crts);
}
static int crtmgr_rsa_verify(cli_crt *x509, mp_int *sig, cli_crt_hashtype hashtype, const uint8_t *refhash) {
static int crtmgr_rsa_verify(cli_crt *x509, mp_int *sig, cli_crt_hashtype hashtype, const uint8_t *refhash)
{
int keylen = mp_unsigned_bin_size(&x509->n), siglen = mp_unsigned_bin_size(sig);
int ret, j, objlen, hashlen;
uint8_t d[513];
@ -240,46 +249,46 @@ static int crtmgr_rsa_verify(cli_crt *x509, mp_int *sig, cli_crt_hashtype hashty
return 1;
}
if((ret = mp_init(&x))) {
if ((ret = mp_init(&x))) {
cli_errmsg("crtmgr_rsa_verify: mp_init failed with %d\n", ret);
return 1;
}
do {
if(MAX(keylen, siglen) - MIN(keylen, siglen) > 1) {
if (MAX(keylen, siglen) - MIN(keylen, siglen) > 1) {
cli_dbgmsg("crtmgr_rsa_verify: keylen and siglen differ by more than one\n");
break;
}
if((ret = mp_exptmod(sig, &x509->e, &x509->n, &x))) {
if ((ret = mp_exptmod(sig, &x509->e, &x509->n, &x))) {
cli_warnmsg("crtmgr_rsa_verify: verification failed: mp_exptmod failed with %d\n", ret);
break;
}
if(mp_unsigned_bin_size(&x) != keylen - 1){
if (mp_unsigned_bin_size(&x) != keylen - 1) {
cli_dbgmsg("crtmgr_rsa_verify: keylen-1 doesn't match expected size of exptmod result\n");
break;
}
if(((unsigned int) mp_unsigned_bin_size(&x)) > sizeof(d)) {
if (((unsigned int)mp_unsigned_bin_size(&x)) > sizeof(d)) {
cli_dbgmsg("crtmgr_rsa_verify: exptmod result would overrun working buffer\n");
break;
}
if((ret = mp_to_unsigned_bin(&x, d))) {
if ((ret = mp_to_unsigned_bin(&x, d))) {
cli_warnmsg("crtmgr_rsa_verify: mp_unsigned_bin_size failed with %d\n", ret);
break;
}
if(*d != 1) {/* block type 1 */
if (*d != 1) { /* block type 1 */
cli_dbgmsg("crtmgr_rsa_verify: expected block type 1 at d[0]\n");
break;
}
keylen -= 1; /* 0xff padding */
for(j=1; j<keylen-2; j++)
if(d[j] != 0xff)
for (j = 1; j < keylen - 2; j++)
if (d[j] != 0xff)
break;
if(j == keylen - 2) {
if (j == keylen - 2) {
cli_dbgmsg("crtmgr_rsa_verify: only encountered 0xFF padding parsing cert\n");
break;
}
if(d[j] != 0) { /* 0x00 separator */
if (d[j] != 0) { /* 0x00 separator */
cli_dbgmsg("crtmgr_rsa_verify: expected 0x00 separator\n");
break;
}
@ -287,46 +296,46 @@ static int crtmgr_rsa_verify(cli_crt *x509, mp_int *sig, cli_crt_hashtype hashty
j++;
keylen -= j; /* asn1 size */
if(keylen < hashlen) {
if (keylen < hashlen) {
cli_dbgmsg("crtmgr_rsa_verify: encountered keylen less than hashlen\n");
break;
}
if(keylen > hashlen) {
if (keylen > hashlen) {
/* hash is asn1 der encoded */
/* SEQ { SEQ { OID, NULL }, OCTET STRING */
if(keylen < 2 || d[j] != 0x30 || d[j+1] + 2 != keylen) {
if (keylen < 2 || d[j] != 0x30 || d[j + 1] + 2 != keylen) {
cli_dbgmsg("crtmgr_rsa_verify: unexpected hash to be ASN1 DER encoded\n");
break;
}
keylen -= 2;
j+=2;
j += 2;
if(keylen <2 || d[j] != 0x30) {
if (keylen < 2 || d[j] != 0x30) {
cli_dbgmsg("crtmgr_rsa_verify: expected SEQUENCE at beginning of cert AlgorithmIdentifier\n");
break;
}
objlen = d[j+1];
objlen = d[j + 1];
keylen -= 2;
j+=2;
if(keylen < objlen) {
j += 2;
if (keylen < objlen) {
cli_dbgmsg("crtmgr_rsa_verify: key length mismatch in ASN1 DER hash encoding\n");
break;
}
if(objlen == 9) {
if (objlen == 9) {
// Check for OID type indicating a length of 5, OID_sha1, and the NULL type/value
if(hashtype != CLI_SHA1RSA || memcmp(&d[j], "\x06\x05" OID_sha1 "\x05\x00", 9)) {
if (hashtype != CLI_SHA1RSA || memcmp(&d[j], "\x06\x05" OID_sha1 "\x05\x00", 9)) {
cli_errmsg("crtmgr_rsa_verify: FIXME ACAB - CRYPTO MISSING?\n");
break;
}
} else if(objlen == 12) {
} else if (objlen == 12) {
// Check for OID type indicating a length of 8, OID_md5, and the NULL type/value
if(hashtype != CLI_MD5RSA || memcmp(&d[j], "\x06\x08" OID_md5 "\x05\x00", 12)) {
if (hashtype != CLI_MD5RSA || memcmp(&d[j], "\x06\x08" OID_md5 "\x05\x00", 12)) {
cli_errmsg("crtmgr_rsa_verify: FIXME ACAB - CRYPTO MISSING?\n");
break;
}
} else if(objlen == 13) {
} else if (objlen == 13) {
if (hashtype == CLI_SHA256RSA) {
// Check for OID type indicating a length of 9, OID_sha256, and the NULL type/value
if (0 != memcmp(&d[j], "\x06\x09" OID_sha256 "\x05\x00", 13)) {
@ -359,18 +368,18 @@ static int crtmgr_rsa_verify(cli_crt *x509, mp_int *sig, cli_crt_hashtype hashty
keylen -= objlen;
j += objlen;
if(keylen < 2 || d[j] != 0x04 || d[j+1] != hashlen) {
if (keylen < 2 || d[j] != 0x04 || d[j + 1] != hashlen) {
cli_dbgmsg("crtmgr_rsa_verify: hash length mismatch in ASN1 DER hash encoding\n");
break;
}
keylen -= 2;
j+=2;
if(keylen != hashlen) {
j += 2;
if (keylen != hashlen) {
cli_dbgmsg("crtmgr_rsa_verify: extra data in the ASN1 DER hash encoding\n");
break;
}
}
if(memcmp(&d[j], refhash, hashlen)) {
if (memcmp(&d[j], refhash, hashlen)) {
// This is a common error case if we are using crtmgr_rsa_verify to
// determine whether we've found the right issuer certificate based
// (as is done by crtmgr_verify_crt). If we are pretty sure that
@ -382,7 +391,7 @@ static int crtmgr_rsa_verify(cli_crt *x509, mp_int *sig, cli_crt_hashtype hashty
mp_clear(&x);
return 0;
} while(0);
} while (0);
mp_clear(&x);
return 1;
@ -392,9 +401,10 @@ static int crtmgr_rsa_verify(cli_crt *x509, mp_int *sig, cli_crt_hashtype hashty
* is present. Otherwise returns a pointer to the signer x509 certificate if
* one is found in the crtmgr and it's signature can be validated (NULL is
* returned otherwise.) */
cli_crt *crtmgr_verify_crt(crtmgr *m, cli_crt *x509) {
cli_crt *crtmgr_verify_crt(crtmgr *m, cli_crt *x509)
{
cli_crt *i = m->crts, *best = NULL;
int score = 0;
int score = 0;
unsigned int possible = 0;
if (NULL != (i = crtmgr_blacklist_lookup(m, x509))) {
@ -408,18 +418,18 @@ cli_crt *crtmgr_verify_crt(crtmgr *m, cli_crt *x509) {
// that way, but the cert doesn't HAVE to be embedded. This case seems
// unlikely enough to ignore, though.
for(i = m->crts; i; i = i->next) {
if(i->certSign &&
!i->isBlacklisted &&
!memcmp(i->subject, x509->issuer, sizeof(i->subject)) &&
!crtmgr_rsa_verify(i, &x509->sig, x509->hashtype, x509->tbshash)) {
for (i = m->crts; i; i = i->next) {
if (i->certSign &&
!i->isBlacklisted &&
!memcmp(i->subject, x509->issuer, sizeof(i->subject)) &&
!crtmgr_rsa_verify(i, &x509->sig, x509->hashtype, x509->tbshash)) {
int curscore;
if((x509->codeSign & i->codeSign) == x509->codeSign && (x509->timeSign & i->timeSign) == x509->timeSign)
if ((x509->codeSign & i->codeSign) == x509->codeSign && (x509->timeSign & i->timeSign) == x509->timeSign)
return i;
possible++;
curscore = (x509->codeSign & i->codeSign) + (x509->timeSign & i->timeSign);
if(curscore > score) {
best = i;
if (curscore > score) {
best = i;
score = curscore;
}
}
@ -433,33 +443,34 @@ cli_crt *crtmgr_verify_crt(crtmgr *m, cli_crt *x509) {
return best;
}
cli_crt *crtmgr_verify_pkcs7(crtmgr *m, const uint8_t *issuer, const uint8_t *serial, const void *signature, unsigned int signature_len, cli_crt_hashtype hashtype, const uint8_t *refhash, cli_vrfy_type vrfytype) {
cli_crt *crtmgr_verify_pkcs7(crtmgr *m, const uint8_t *issuer, const uint8_t *serial, const void *signature, unsigned int signature_len, cli_crt_hashtype hashtype, const uint8_t *refhash, cli_vrfy_type vrfytype)
{
cli_crt *i;
mp_int sig;
int ret;
if(signature_len < 1024/8 || signature_len > 4096/8+1) {
if (signature_len < 1024 / 8 || signature_len > 4096 / 8 + 1) {
cli_dbgmsg("crtmgr_verify_pkcs7: unsupported sig len: %u\n", signature_len);
return NULL;
}
if((ret = mp_init(&sig))) {
if ((ret = mp_init(&sig))) {
cli_dbgmsg("crtmgr_verify_pkcs7: mp_init failed with %d\n", ret);
return NULL;
}
if((ret=mp_read_unsigned_bin(&sig, signature, signature_len))) {
if ((ret = mp_read_unsigned_bin(&sig, signature, signature_len))) {
cli_dbgmsg("crtmgr_verify_pkcs7: mp_read_unsigned_bin failed with %d\n", ret);
return NULL;
}
for(i = m->crts; i; i = i->next) {
if(vrfytype == VRFY_CODE && !i->codeSign)
for (i = m->crts; i; i = i->next) {
if (vrfytype == VRFY_CODE && !i->codeSign)
continue;
if(vrfytype == VRFY_TIME && !i->timeSign)
if (vrfytype == VRFY_TIME && !i->timeSign)
continue;
if(!memcmp(i->issuer, issuer, sizeof(i->issuer)) &&
!memcmp(i->serial, serial, sizeof(i->serial))) {
if(!crtmgr_rsa_verify(i, &sig, hashtype, refhash)) {
if (!memcmp(i->issuer, issuer, sizeof(i->issuer)) &&
!memcmp(i->serial, serial, sizeof(i->serial))) {
if (!crtmgr_rsa_verify(i, &sig, hashtype, refhash)) {
break;
}
cli_dbgmsg("crtmgr_verify_pkcs7: found cert with matching issuer and serial but RSA verification failed\n");
@ -469,20 +480,21 @@ cli_crt *crtmgr_verify_pkcs7(crtmgr *m, const uint8_t *issuer, const uint8_t *se
return i;
}
int crtmgr_add_roots(struct cl_engine *engine, crtmgr *m) {
int crtmgr_add_roots(struct cl_engine *engine, crtmgr *m)
{
cli_crt *crt;
/*
* Certs are cached in engine->cmgr. Copy from there.
*/
if (m != &(engine->cmgr)) {
for (crt = engine->cmgr.crts; crt != NULL; crt = crt->next) {
if (crtmgr_add(m, crt)) {
crtmgr_free(m);
return 1;
}
}
for (crt = engine->cmgr.crts; crt != NULL; crt = crt->next) {
if (crtmgr_add(m, crt)) {
crtmgr_free(m);
return 1;
}
}
return 0;
return 0;
}
return 0;

View file

@ -26,8 +26,15 @@
#include "bignum.h"
typedef enum {CLI_SHA1RSA, CLI_MD5RSA, CLI_MD2RSA, CLI_RSA, CLI_SHA256RSA, CLI_SHA384RSA, CLI_SHA512RSA } cli_crt_hashtype;
typedef enum {VRFY_CODE, VRFY_TIME} cli_vrfy_type;
typedef enum { CLI_SHA1RSA,
CLI_MD5RSA,
CLI_MD2RSA,
CLI_RSA,
CLI_SHA256RSA,
CLI_SHA384RSA,
CLI_SHA512RSA } cli_crt_hashtype;
typedef enum { VRFY_CODE,
VRFY_TIME } cli_vrfy_type;
#define CRT_RAWMAXLEN 64
typedef struct cli_crt_t {
@ -61,7 +68,6 @@ typedef struct {
unsigned int items;
} crtmgr;
int cli_crt_init(cli_crt *x509);
void cli_crt_clear(cli_crt *x509);
void crtmgr_init(crtmgr *m);
@ -73,5 +79,4 @@ cli_crt *crtmgr_verify_crt(crtmgr *m, cli_crt *x509);
cli_crt *crtmgr_verify_pkcs7(crtmgr *m, const uint8_t *issuer, const uint8_t *serial, const void *signature, unsigned int signature_len, cli_crt_hashtype hashtype, const uint8_t *refhash, cli_vrfy_type vrfytype);
int crtmgr_add_roots(struct cl_engine *engine, crtmgr *m);
#endif

View file

@ -65,21 +65,24 @@
#include "iowrap.h"
#if defined(_WIN32)
char * strptime(const char *buf, const char *fmt, struct tm *tm);
char *strptime(const char *buf, const char *fmt, struct tm *tm);
#endif
#if defined(_WIN32)
#define EXCEPTION_PREAMBLE __try {
#define EXCEPTION_POSTAMBLE } __except (filter_memcpy(GetExceptionCode(), GetExceptionInformation())) { \
winres=1; \
}
#define EXCEPTION_POSTAMBLE \
} \
__except (filter_memcpy(GetExceptionCode(), GetExceptionInformation())) \
{ \
winres = 1; \
}
#else
#define EXCEPTION_PREAMBLE
#define EXCEPTION_POSTAMBLE
#endif
#if !defined(MIN)
#define MIN(x,y) ((x)<(y)?(x):(y))
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#endif
#if !defined(HAVE_TIMEGM) && !defined(_WIN32)
@ -92,24 +95,22 @@ time_t timegm(struct tm *t)
time_t tl, tb;
struct tm *tg;
tl = mktime (t);
if (tl == -1)
{
tl = mktime(t);
if (tl == -1) {
t->tm_hour--;
tl = mktime (t);
tl = mktime(t);
if (tl == -1)
return -1; /* can't deal with output from strptime */
tl += 3600;
}
tg = gmtime (&tl);
tg = gmtime(&tl);
tg->tm_isdst = 0;
tb = mktime (tg);
tb = mktime(tg);
if (tb == -1)
{
if (tb == -1) {
tg->tm_hour--;
tb = mktime (tg);
tb = mktime(tg);
if (tb == -1)
return -1; /* can't deal with output from gmtime */
@ -120,7 +121,6 @@ time_t timegm(struct tm *t)
}
#endif
/**
* @brief This function initializes the openssl crypto system
*
@ -162,7 +162,7 @@ unsigned char *cl_hash_data(const char *alg, const void *buf, size_t len, unsign
const EVP_MD *md;
unsigned int i;
size_t cur;
int winres=0;
int winres = 0;
md = EVP_get_digestbyname(alg);
if (!(md))
@ -198,12 +198,12 @@ unsigned char *cl_hash_data(const char *alg, const void *buf, size_t len, unsign
return NULL;
}
cur=0;
cur = 0;
while (cur < len) {
size_t todo = MIN((unsigned long)EVP_MD_block_size(md), (unsigned long)(len-cur));
size_t todo = MIN((unsigned long)EVP_MD_block_size(md), (unsigned long)(len - cur));
EXCEPTION_PREAMBLE
if (!EVP_DigestUpdate(ctx, (void *)(((unsigned char *)buf)+cur), todo)) {
if (!EVP_DigestUpdate(ctx, (void *)(((unsigned char *)buf) + cur), todo)) {
if (!(obuf))
free(ret);
@ -285,9 +285,9 @@ unsigned char *cl_hash_file_fd_ctx(EVP_MD_CTX *ctx, int fd, unsigned int *olen)
int mdsz;
unsigned int hashlen;
STATBUF sb;
int winres=0;
int winres = 0;
unsigned int blocksize;
unsigned int blocksize;
#ifdef _WIN32
int nread;
@ -302,9 +302,9 @@ unsigned char *cl_hash_file_fd_ctx(EVP_MD_CTX *ctx, int fd, unsigned int *olen)
}
#ifdef _WIN32
blocksize = 8192;
blocksize = 8192;
#else
blocksize = sb.st_blksize;
blocksize = sb.st_blksize;
#endif
buf = (unsigned char *)malloc(blocksize);
@ -488,7 +488,7 @@ int cl_verify_signature(EVP_PKEY *pkey, const char *alg, unsigned char *sig, uns
if (!(newsig))
return -1;
sig = newsig;
sig = newsig;
siglen = newsiglen;
}
@ -765,7 +765,7 @@ unsigned char *cl_sign_data(EVP_PKEY *pkey, const char *alg, unsigned char *hash
}
free(sig);
sig = newsig;
sig = newsig;
siglen = (unsigned int)strlen((const char *)newsig);
}
@ -831,8 +831,8 @@ X509 *cl_get_x509_from_mem(void *data, unsigned int len)
int cl_validate_certificate_chain_ts_dir(char *tsdir, char *certpath)
{
char **authorities=NULL, **t;
size_t nauths = 0;
char **authorities = NULL, **t;
size_t nauths = 0;
int res;
DIR *dp;
struct dirent *dirent;
@ -872,7 +872,7 @@ int cl_validate_certificate_chain_ts_dir(char *tsdir, char *certpath)
return -1;
}
authorities = t;
authorities = t;
authorities[nauths] = (char *)malloc(strlen(tsdir) + strlen(dirent->d_name) + 2);
if (!authorities[nauths]) {
if (nauths) {
@ -886,7 +886,7 @@ int cl_validate_certificate_chain_ts_dir(char *tsdir, char *certpath)
return -1;
}
sprintf(authorities[nauths], "%s"PATHSEP"%s", tsdir, dirent->d_name);
sprintf(authorities[nauths], "%s" PATHSEP "%s", tsdir, dirent->d_name);
nauths++;
}
@ -903,7 +903,7 @@ int cl_validate_certificate_chain_ts_dir(char *tsdir, char *certpath)
return -1;
}
authorities = t;
authorities = t;
authorities[nauths] = NULL;
res = cl_validate_certificate_chain(authorities, NULL, certpath);
@ -918,11 +918,11 @@ int cl_validate_certificate_chain_ts_dir(char *tsdir, char *certpath)
int cl_validate_certificate_chain(char **authorities, char *crlpath, char *certpath)
{
X509_STORE *store=NULL;
X509_STORE *store = NULL;
X509_STORE_CTX *store_ctx;
X509_LOOKUP *lookup=NULL;
X509_CRL *crl=NULL;
X509_VERIFY_PARAM *param=NULL;
X509_LOOKUP *lookup = NULL;
X509_CRL *crl = NULL;
X509_VERIFY_PARAM *param = NULL;
X509 *cert;
unsigned long i;
int res;
@ -960,7 +960,7 @@ int cl_validate_certificate_chain(char **authorities, char *crlpath, char *certp
}
/* Support multi-tiered setups */
for (i=0; authorities[i]; i++) {
for (i = 0; authorities[i]; i++) {
if (!X509_LOOKUP_load_file(lookup, authorities[i], X509_FILETYPE_PEM)) {
X509_STORE_free(store);
if ((crl))
@ -1058,8 +1058,8 @@ X509 *cl_load_cert(const char *certpath)
struct tm *cl_ASN1_GetTimeT(ASN1_TIME *timeobj)
{
struct tm *t;
char* str;
const char *fmt=NULL;
char *str;
const char *fmt = NULL;
time_t localt;
#ifdef _WIN32
struct tm localtm, *ltm;
@ -1087,8 +1087,7 @@ struct tm *cl_ASN1_GetTimeT(ASN1_TIME *timeobj)
} else {
str[3]--;
}
}
else if (timeobj->type == V_ASN1_GENERALIZEDTIME) {
} else if (timeobj->type == V_ASN1_GENERALIZEDTIME) {
/* four digit year */
fmt = "%Y%m%d%H%M%S";
if (str[5] == '0') {
@ -1123,7 +1122,7 @@ struct tm *cl_ASN1_GetTimeT(ASN1_TIME *timeobj)
X509_CRL *cl_load_crl(const char *file)
{
X509_CRL *x=NULL;
X509_CRL *x = NULL;
FILE *fp;
if (!(file))
@ -1138,13 +1137,13 @@ X509_CRL *cl_load_crl(const char *file)
fclose(fp);
if ((x)) {
ASN1_TIME *tme;
ASN1_TIME *tme;
tme = X509_CRL_get_nextUpdate(x);
if (!tme || X509_cmp_current_time(tme) < 0) {
X509_CRL_free(x);
return NULL;
}
tme = X509_CRL_get_nextUpdate(x);
if (!tme || X509_cmp_current_time(tme) < 0) {
X509_CRL_free(x);
return NULL;
}
}
return x;
@ -1179,7 +1178,7 @@ void *cl_hash_init(const char *alg)
int cl_update_hash(void *ctx, const void *data, size_t sz)
{
int winres=0;
int winres = 0;
if (!(ctx) || !(data))
return -1;
@ -1197,7 +1196,7 @@ int cl_update_hash(void *ctx, const void *data, size_t sz)
int cl_finish_hash(void *ctx, void *buf)
{
int res=0;
int res = 0;
if (!(ctx) || !(buf))
return -1;

File diff suppressed because it is too large Load diff

View file

@ -39,10 +39,10 @@
#include "mpool.h"
struct dconf_module {
const char *mname; /* module name */
const char *sname; /* submodule name */
uint32_t bflag; /* bit flag */
uint8_t state; /* default state (on/off) */
const char *mname; /* module name */
const char *sname; /* submodule name */
uint32_t bflag; /* bit flag */
uint8_t state; /* default state (on/off) */
};
#ifdef CL_EXPERIMENTAL
@ -53,103 +53,102 @@ struct dconf_module {
static struct dconf_module modules[] = {
{ "PE", "PARITE", PE_CONF_PARITE, 1 },
{ "PE", "KRIZ", PE_CONF_KRIZ, 1 },
{ "PE", "MAGISTR", PE_CONF_MAGISTR, 1 },
{ "PE", "POLIPOS", PE_CONF_POLIPOS, 1 },
{ "PE", "MD5SECT", PE_CONF_MD5SECT, 1 },
{ "PE", "UPX", PE_CONF_UPX, 1 },
{ "PE", "FSG", PE_CONF_FSG, 1 },
{ "PE", "SWIZZOR", PE_CONF_SWIZZOR, 0 },
{"PE", "PARITE", PE_CONF_PARITE, 1},
{"PE", "KRIZ", PE_CONF_KRIZ, 1},
{"PE", "MAGISTR", PE_CONF_MAGISTR, 1},
{"PE", "POLIPOS", PE_CONF_POLIPOS, 1},
{"PE", "MD5SECT", PE_CONF_MD5SECT, 1},
{"PE", "UPX", PE_CONF_UPX, 1},
{"PE", "FSG", PE_CONF_FSG, 1},
{"PE", "SWIZZOR", PE_CONF_SWIZZOR, 0},
{ "PE", "PETITE", PE_CONF_PETITE, 1 },
{ "PE", "PESPIN", PE_CONF_PESPIN, 1 },
{ "PE", "YC", PE_CONF_YC, 1 },
{ "PE", "WWPACK", PE_CONF_WWPACK, 1 },
{"PE", "PETITE", PE_CONF_PETITE, 1},
{"PE", "PESPIN", PE_CONF_PESPIN, 1},
{"PE", "YC", PE_CONF_YC, 1},
{"PE", "WWPACK", PE_CONF_WWPACK, 1},
{ "PE", "NSPACK", PE_CONF_NSPACK, 1 },
{ "PE", "MEW", PE_CONF_MEW, 1 },
{ "PE", "UPACK", PE_CONF_UPACK, 1 },
{ "PE", "ASPACK", PE_CONF_ASPACK, 1 },
{ "PE", "CATALOG", PE_CONF_CATALOG, 1 },
{ "PE", "CERTS", PE_CONF_CERTS, 1 },
{ "PE", "MATCHICON", PE_CONF_MATCHICON, 1 },
{ "PE", "IMPTBL", PE_CONF_IMPTBL, 1 },
{"PE", "NSPACK", PE_CONF_NSPACK, 1},
{"PE", "MEW", PE_CONF_MEW, 1},
{"PE", "UPACK", PE_CONF_UPACK, 1},
{"PE", "ASPACK", PE_CONF_ASPACK, 1},
{"PE", "CATALOG", PE_CONF_CATALOG, 1},
{"PE", "CERTS", PE_CONF_CERTS, 1},
{"PE", "MATCHICON", PE_CONF_MATCHICON, 1},
{"PE", "IMPTBL", PE_CONF_IMPTBL, 1},
{ "ELF", NULL, 0x1, 1 },
{"ELF", NULL, 0x1, 1},
{ "MACHO", NULL, 0x1, 1 },
{"MACHO", NULL, 0x1, 1},
{ "ARCHIVE", "RAR", ARCH_CONF_RAR, 1 },
{ "ARCHIVE", "ZIP", ARCH_CONF_ZIP, 1 },
{ "ARCHIVE", "GZIP", ARCH_CONF_GZ, 1 },
{ "ARCHIVE", "BZIP", ARCH_CONF_BZ, 1 },
{ "ARCHIVE", "ARJ", ARCH_CONF_ARJ, 1 },
{ "ARCHIVE", "SZDD", ARCH_CONF_SZDD, 1 },
{ "ARCHIVE", "CAB", ARCH_CONF_CAB, 1 },
{ "ARCHIVE", "CHM", ARCH_CONF_CHM, 1 },
{ "ARCHIVE", "OLE2", ARCH_CONF_OLE2, 1 },
{ "ARCHIVE", "TAR", ARCH_CONF_TAR, 1 },
{ "ARCHIVE", "CPIO", ARCH_CONF_CPIO, 1 },
{ "ARCHIVE", "BINHEX", ARCH_CONF_BINHEX, 1 },
{ "ARCHIVE", "SIS", ARCH_CONF_SIS, 1 },
{ "ARCHIVE", "NSIS", ARCH_CONF_NSIS, 1 },
{ "ARCHIVE", "AUTOIT", ARCH_CONF_AUTOIT, 1 },
{ "ARCHIVE", "ISHIELD", ARCH_CONF_ISHIELD, 1 },
{ "ARCHIVE", "7zip", ARCH_CONF_7Z, 1 },
{ "ARCHIVE", "ISO9660", ARCH_CONF_ISO9660, 1 },
{ "ARCHIVE", "DMG", ARCH_CONF_DMG, 1 },
{ "ARCHIVE", "XAR", ARCH_CONF_XAR, 1 },
{ "ARCHIVE", "HFSPLUS", ARCH_CONF_HFSPLUS, 1 },
{ "ARCHIVE", "XZ", ARCH_CONF_XZ, 1 },
{ "ARCHIVE", "PASSWD", ARCH_CONF_PASSWD, 1 },
{ "ARCHIVE", "MBR", ARCH_CONF_MBR, 1 },
{ "ARCHIVE", "GPT", ARCH_CONF_GPT, 1 },
{ "ARCHIVE", "APM", ARCH_CONF_APM, 1 },
{"ARCHIVE", "RAR", ARCH_CONF_RAR, 1},
{"ARCHIVE", "ZIP", ARCH_CONF_ZIP, 1},
{"ARCHIVE", "GZIP", ARCH_CONF_GZ, 1},
{"ARCHIVE", "BZIP", ARCH_CONF_BZ, 1},
{"ARCHIVE", "ARJ", ARCH_CONF_ARJ, 1},
{"ARCHIVE", "SZDD", ARCH_CONF_SZDD, 1},
{"ARCHIVE", "CAB", ARCH_CONF_CAB, 1},
{"ARCHIVE", "CHM", ARCH_CONF_CHM, 1},
{"ARCHIVE", "OLE2", ARCH_CONF_OLE2, 1},
{"ARCHIVE", "TAR", ARCH_CONF_TAR, 1},
{"ARCHIVE", "CPIO", ARCH_CONF_CPIO, 1},
{"ARCHIVE", "BINHEX", ARCH_CONF_BINHEX, 1},
{"ARCHIVE", "SIS", ARCH_CONF_SIS, 1},
{"ARCHIVE", "NSIS", ARCH_CONF_NSIS, 1},
{"ARCHIVE", "AUTOIT", ARCH_CONF_AUTOIT, 1},
{"ARCHIVE", "ISHIELD", ARCH_CONF_ISHIELD, 1},
{"ARCHIVE", "7zip", ARCH_CONF_7Z, 1},
{"ARCHIVE", "ISO9660", ARCH_CONF_ISO9660, 1},
{"ARCHIVE", "DMG", ARCH_CONF_DMG, 1},
{"ARCHIVE", "XAR", ARCH_CONF_XAR, 1},
{"ARCHIVE", "HFSPLUS", ARCH_CONF_HFSPLUS, 1},
{"ARCHIVE", "XZ", ARCH_CONF_XZ, 1},
{"ARCHIVE", "PASSWD", ARCH_CONF_PASSWD, 1},
{"ARCHIVE", "MBR", ARCH_CONF_MBR, 1},
{"ARCHIVE", "GPT", ARCH_CONF_GPT, 1},
{"ARCHIVE", "APM", ARCH_CONF_APM, 1},
{ "DOCUMENT", "HTML", DOC_CONF_HTML, 1 },
{ "DOCUMENT", "RTF", DOC_CONF_RTF, 1 },
{ "DOCUMENT", "PDF", DOC_CONF_PDF, 1 },
{ "DOCUMENT", "SCRIPT", DOC_CONF_SCRIPT, 1 },
{ "DOCUMENT", "HTMLSKIPRAW", DOC_CONF_HTML_SKIPRAW, 1 },
{ "DOCUMENT", "JSNORM", DOC_CONF_JSNORM, 1 },
{ "DOCUMENT", "SWF", DOC_CONF_SWF, 1 },
{ "DOCUMENT", "OOXML", DOC_CONF_OOXML, 1 },
{ "DOCUMENT", "MSPML", DOC_CONF_MSXML, 1 },
{ "DOCUMENT", "HWP", DOC_CONF_HWP, 1 },
{"DOCUMENT", "HTML", DOC_CONF_HTML, 1},
{"DOCUMENT", "RTF", DOC_CONF_RTF, 1},
{"DOCUMENT", "PDF", DOC_CONF_PDF, 1},
{"DOCUMENT", "SCRIPT", DOC_CONF_SCRIPT, 1},
{"DOCUMENT", "HTMLSKIPRAW", DOC_CONF_HTML_SKIPRAW, 1},
{"DOCUMENT", "JSNORM", DOC_CONF_JSNORM, 1},
{"DOCUMENT", "SWF", DOC_CONF_SWF, 1},
{"DOCUMENT", "OOXML", DOC_CONF_OOXML, 1},
{"DOCUMENT", "MSPML", DOC_CONF_MSXML, 1},
{"DOCUMENT", "HWP", DOC_CONF_HWP, 1},
{ "MAIL", "MBOX", MAIL_CONF_MBOX, 1 },
{ "MAIL", "TNEF", MAIL_CONF_TNEF, 1 },
{"MAIL", "MBOX", MAIL_CONF_MBOX, 1},
{"MAIL", "TNEF", MAIL_CONF_TNEF, 1},
{ "OTHER", "UUENCODED", OTHER_CONF_UUENC, 1 },
{ "OTHER", "SCRENC", OTHER_CONF_SCRENC, 1 },
{ "OTHER", "RIFF", OTHER_CONF_RIFF, 1 },
{ "OTHER", "JPEG", OTHER_CONF_JPEG, 1 },
{ "OTHER", "CRYPTFF", OTHER_CONF_CRYPTFF, 1 },
{ "OTHER", "DLP", OTHER_CONF_DLP, 1 },
{ "OTHER", "MYDOOMLOG", OTHER_CONF_MYDOOMLOG, 1 },
{ "OTHER", "PREFILTERING", OTHER_CONF_PREFILTERING,1 },
{ "OTHER", "PDFNAMEOBJ", OTHER_CONF_PDFNAMEOBJ, 1 },
{ "OTHER", "PRTNINTXN", OTHER_CONF_PRTNINTXN, 1 },
{ "OTHER", "LZW", OTHER_CONF_LZW, 1 },
{"OTHER", "UUENCODED", OTHER_CONF_UUENC, 1},
{"OTHER", "SCRENC", OTHER_CONF_SCRENC, 1},
{"OTHER", "RIFF", OTHER_CONF_RIFF, 1},
{"OTHER", "JPEG", OTHER_CONF_JPEG, 1},
{"OTHER", "CRYPTFF", OTHER_CONF_CRYPTFF, 1},
{"OTHER", "DLP", OTHER_CONF_DLP, 1},
{"OTHER", "MYDOOMLOG", OTHER_CONF_MYDOOMLOG, 1},
{"OTHER", "PREFILTERING", OTHER_CONF_PREFILTERING, 1},
{"OTHER", "PDFNAMEOBJ", OTHER_CONF_PDFNAMEOBJ, 1},
{"OTHER", "PRTNINTXN", OTHER_CONF_PRTNINTXN, 1},
{"OTHER", "LZW", OTHER_CONF_LZW, 1},
{ "PHISHING", "ENGINE", PHISHING_CONF_ENGINE, 1 },
{ "PHISHING", "ENTCONV", PHISHING_CONF_ENTCONV, 1 },
{"PHISHING", "ENGINE", PHISHING_CONF_ENGINE, 1},
{"PHISHING", "ENTCONV", PHISHING_CONF_ENTCONV, 1},
{ "BYTECODE", "INTERPRETER", BYTECODE_INTERPRETER, 1 },
{ "BYTECODE", "JIT X86", BYTECODE_JIT_X86, 1 },
{ "BYTECODE", "JIT PPC", BYTECODE_JIT_PPC, 1 },
{ "BYTECODE", "JIT ARM", BYTECODE_JIT_ARM, 0 },
{"BYTECODE", "INTERPRETER", BYTECODE_INTERPRETER, 1},
{"BYTECODE", "JIT X86", BYTECODE_JIT_X86, 1},
{"BYTECODE", "JIT PPC", BYTECODE_JIT_PPC, 1},
{"BYTECODE", "JIT ARM", BYTECODE_JIT_ARM, 0},
{ "STATS", "DISABLED", DCONF_STATS_DISABLED, 0 },
{ "STATS", "PESECTION DISABLED", DCONF_STATS_PE_SECTION_DISABLED, 0 },
{"STATS", "DISABLED", DCONF_STATS_DISABLED, 0},
{"STATS", "PESECTION DISABLED", DCONF_STATS_PE_SECTION_DISABLED, 0},
{ "PCRE", "SUPPORT", PCRE_CONF_SUPPORT, 1 },
{ "PCRE", "OPTIONS", PCRE_CONF_OPTIONS, 1 },
{ "PCRE", "GLOBAL", PCRE_CONF_GLOBAL, 1 },
{"PCRE", "SUPPORT", PCRE_CONF_SUPPORT, 1},
{"PCRE", "OPTIONS", PCRE_CONF_OPTIONS, 1},
{"PCRE", "GLOBAL", PCRE_CONF_GLOBAL, 1},
{ NULL, NULL, 0, 0 }
};
{NULL, NULL, 0, 0}};
#ifdef USE_MPOOL
struct cli_dconf *cli_dconf_init(mpool_t *mempool)
@ -160,42 +159,42 @@ struct cli_dconf *cli_dconf_init(void)
unsigned int i;
struct cli_dconf *dconf;
dconf = (struct cli_dconf *) mpool_calloc(mempool, sizeof(struct cli_dconf), 1);
if(!dconf)
dconf = (struct cli_dconf *)mpool_calloc(mempool, sizeof(struct cli_dconf), 1);
if (!dconf)
return NULL;
for(i = 0; modules[i].mname; i++) {
if(!strcmp(modules[i].mname, "PE")) {
if(modules[i].state)
for (i = 0; modules[i].mname; i++) {
if (!strcmp(modules[i].mname, "PE")) {
if (modules[i].state)
dconf->pe |= modules[i].bflag;
} else if(!strcmp(modules[i].mname, "ELF")) {
if(modules[i].state)
} else if (!strcmp(modules[i].mname, "ELF")) {
if (modules[i].state)
dconf->elf |= modules[i].bflag;
} else if(!strcmp(modules[i].mname, "MACHO")) {
if(modules[i].state)
} else if (!strcmp(modules[i].mname, "MACHO")) {
if (modules[i].state)
dconf->macho |= modules[i].bflag;
} else if(!strcmp(modules[i].mname, "ARCHIVE")) {
if(modules[i].state)
} else if (!strcmp(modules[i].mname, "ARCHIVE")) {
if (modules[i].state)
dconf->archive |= modules[i].bflag;
} else if(!strcmp(modules[i].mname, "DOCUMENT")) {
if(modules[i].state)
} else if (!strcmp(modules[i].mname, "DOCUMENT")) {
if (modules[i].state)
dconf->doc |= modules[i].bflag;
} else if(!strcmp(modules[i].mname, "MAIL")) {
if(modules[i].state)
} else if (!strcmp(modules[i].mname, "MAIL")) {
if (modules[i].state)
dconf->mail |= modules[i].bflag;
} else if(!strcmp(modules[i].mname, "OTHER")) {
if(modules[i].state)
} else if (!strcmp(modules[i].mname, "OTHER")) {
if (modules[i].state)
dconf->other |= modules[i].bflag;
} else if(!strcmp(modules[i].mname, "PHISHING")) {
if(modules[i].state)
} else if (!strcmp(modules[i].mname, "PHISHING")) {
if (modules[i].state)
dconf->phishing |= modules[i].bflag;
} else if(!strcmp(modules[i].mname, "BYTECODE")) {
} else if (!strcmp(modules[i].mname, "BYTECODE")) {
if (modules[i].state)
dconf->bytecode |= modules[i].bflag;
} else if (!strcmp(modules[i].mname, "STATS")) {
@ -213,90 +212,89 @@ struct cli_dconf *cli_dconf_init(void)
void cli_dconf_print(struct cli_dconf *dconf)
{
unsigned int pe = 0, elf = 0, macho = 0, arch = 0, doc = 0, mail = 0;
unsigned int other = 0, phishing = 0, i, bytecode=0, stats=0, pcre=0;
unsigned int other = 0, phishing = 0, i, bytecode = 0, stats = 0, pcre = 0;
cli_dbgmsg("Dynamic engine configuration settings:\n");
cli_dbgmsg("--------------------------------------\n");
for(i = 0; modules[i].mname; i++) {
if(!strcmp(modules[i].mname, "PE")) {
if(!pe) {
for (i = 0; modules[i].mname; i++) {
if (!strcmp(modules[i].mname, "PE")) {
if (!pe) {
cli_dbgmsg("Module PE: %s\n", dconf->pe ? "On" : "Off");
pe = 1;
}
if(dconf->pe)
if (dconf->pe)
cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->pe & modules[i].bflag) ? "On" : "** Off **");
else
continue;
} else if(!strcmp(modules[i].mname, "ELF")) {
if(!elf) {
} else if (!strcmp(modules[i].mname, "ELF")) {
if (!elf) {
cli_dbgmsg("Module ELF: %s\n", dconf->elf ? "On" : "Off");
elf = 1;
}
} else if(!strcmp(modules[i].mname, "MACHO")) {
if(!macho) {
} else if (!strcmp(modules[i].mname, "MACHO")) {
if (!macho) {
cli_dbgmsg("Module MACHO: %s\n", dconf->elf ? "On" : "Off");
macho = 1;
}
} else if(!strcmp(modules[i].mname, "ARCHIVE")) {
if(!arch) {
} else if (!strcmp(modules[i].mname, "ARCHIVE")) {
if (!arch) {
cli_dbgmsg("Module ARCHIVE: %s\n", dconf->archive ? "On" : "Off");
arch = 1;
}
if(dconf->archive)
if (dconf->archive)
cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->archive & modules[i].bflag) ? "On" : "** Off **");
else
continue;
} else if(!strcmp(modules[i].mname, "DOCUMENT")) {
if(!doc) {
} else if (!strcmp(modules[i].mname, "DOCUMENT")) {
if (!doc) {
cli_dbgmsg("Module DOCUMENT: %s\n", dconf->doc ? "On" : "Off");
doc = 1;
}
if(dconf->doc)
if (dconf->doc)
cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->doc & modules[i].bflag) ? "On" : "** Off **");
else
continue;
} else if(!strcmp(modules[i].mname, "MAIL")) {
if(!mail) {
} else if (!strcmp(modules[i].mname, "MAIL")) {
if (!mail) {
cli_dbgmsg("Module MAIL: %s\n", dconf->mail ? "On" : "Off");
mail = 1;
}
if(dconf->mail)
if (dconf->mail)
cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->mail & modules[i].bflag) ? "On" : "** Off **");
else
continue;
} else if(!strcmp(modules[i].mname, "OTHER")) {
if(!other) {
} else if (!strcmp(modules[i].mname, "OTHER")) {
if (!other) {
cli_dbgmsg("Module OTHER: %s\n", dconf->other ? "On" : "Off");
other = 1;
}
if(dconf->other)
if (dconf->other)
cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->other & modules[i].bflag) ? "On" : "** Off **");
else
continue;
} else if(!strcmp(modules[i].mname, "PHISHING")) {
if(!phishing) {
} else if (!strcmp(modules[i].mname, "PHISHING")) {
if (!phishing) {
cli_dbgmsg("Module PHISHING %s\n", dconf->phishing ? "On" : "Off");
phishing = 1;
}
if(dconf->phishing)
if (dconf->phishing)
cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->phishing & modules[i].bflag) ? "On" : "** Off **");
else
continue;
} else if(!strcmp(modules[i].mname, "BYTECODE")) {
if(!bytecode) {
} else if (!strcmp(modules[i].mname, "BYTECODE")) {
if (!bytecode) {
cli_dbgmsg("Module BYTECODE %s\n", dconf->bytecode ? "On" : "Off");
bytecode = 1;
}
if(dconf->bytecode)
if (dconf->bytecode)
cli_dbgmsg(" * Submodule %10s:\t%s\n", modules[i].sname, (dconf->bytecode & modules[i].bflag) ? "On" : "** Off **");
else
continue;
@ -337,27 +335,26 @@ static int chkflevel(const char *entry, int field)
{
char *pt;
if((pt = cli_strtok(entry, field, ":"))) { /* min version */
if(!isdigit(*pt)) {
if ((pt = cli_strtok(entry, field, ":"))) { /* min version */
if (!isdigit(*pt)) {
free(pt);
return 0;
}
if((unsigned int) atoi(pt) > CL_FLEVEL_DCONF) {
if ((unsigned int)atoi(pt) > CL_FLEVEL_DCONF) {
free(pt);
return 0;
}
free(pt);
if((pt = cli_strtok(entry, field + 1, ":"))) { /* max version */
if(!isdigit(*pt)) {
if ((pt = cli_strtok(entry, field + 1, ":"))) { /* max version */
if (!isdigit(*pt)) {
free(pt);
return 0;
}
if((unsigned int) atoi(pt) < CL_FLEVEL_DCONF) {
if ((unsigned int)atoi(pt) < CL_FLEVEL_DCONF) {
free(pt);
return 0;
}
@ -373,17 +370,17 @@ int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, str
{
char buffer[FILEBUFF];
unsigned int line = 0;
int ret = 0;
int ret = 0;
uint32_t val;
UNUSEDPARAM(options);
while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
while (cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
line++;
cli_chomp(buffer);
if(!strncmp(buffer, "PE:", 3) && chkflevel(buffer, 2)) {
if(sscanf(buffer + 3, "0x%x", &val) == 1) {
if (!strncmp(buffer, "PE:", 3) && chkflevel(buffer, 2)) {
if (sscanf(buffer + 3, "0x%x", &val) == 1) {
engine->dconf->pe = val;
} else {
ret = CL_EMALFDB;
@ -391,8 +388,8 @@ int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, str
}
}
if(!strncmp(buffer, "ELF:", 4) && chkflevel(buffer, 2)) {
if(sscanf(buffer + 4, "0x%x", &val) == 1) {
if (!strncmp(buffer, "ELF:", 4) && chkflevel(buffer, 2)) {
if (sscanf(buffer + 4, "0x%x", &val) == 1) {
engine->dconf->elf = val;
} else {
ret = CL_EMALFDB;
@ -400,8 +397,8 @@ int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, str
}
}
if(!strncmp(buffer, "MACHO:", 6) && chkflevel(buffer, 2)) {
if(sscanf(buffer + 6, "0x%x", &val) == 1) {
if (!strncmp(buffer, "MACHO:", 6) && chkflevel(buffer, 2)) {
if (sscanf(buffer + 6, "0x%x", &val) == 1) {
engine->dconf->macho = val;
} else {
ret = CL_EMALFDB;
@ -409,8 +406,8 @@ int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, str
}
}
if(!strncmp(buffer, "ARCHIVE:", 8) && chkflevel(buffer, 2)) {
if(sscanf(buffer + 8, "0x%x", &val) == 1) {
if (!strncmp(buffer, "ARCHIVE:", 8) && chkflevel(buffer, 2)) {
if (sscanf(buffer + 8, "0x%x", &val) == 1) {
engine->dconf->archive = val;
} else {
ret = CL_EMALFDB;
@ -418,8 +415,8 @@ int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, str
}
}
if(!strncmp(buffer, "DOCUMENT:", 9) && chkflevel(buffer, 2)) {
if(sscanf(buffer + 9, "0x%x", &val) == 1) {
if (!strncmp(buffer, "DOCUMENT:", 9) && chkflevel(buffer, 2)) {
if (sscanf(buffer + 9, "0x%x", &val) == 1) {
engine->dconf->doc = val;
} else {
ret = CL_EMALFDB;
@ -427,8 +424,8 @@ int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, str
}
}
if(!strncmp(buffer, "MAIL:", 5) && chkflevel(buffer, 2)) {
if(sscanf(buffer + 5, "0x%x", &val) == 1) {
if (!strncmp(buffer, "MAIL:", 5) && chkflevel(buffer, 2)) {
if (sscanf(buffer + 5, "0x%x", &val) == 1) {
engine->dconf->mail = val;
} else {
ret = CL_EMALFDB;
@ -436,8 +433,8 @@ int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, str
}
}
if(!strncmp(buffer, "OTHER:", 6) && chkflevel(buffer, 2)) {
if(sscanf(buffer + 6, "0x%x", &val) == 1) {
if (!strncmp(buffer, "OTHER:", 6) && chkflevel(buffer, 2)) {
if (sscanf(buffer + 6, "0x%x", &val) == 1) {
engine->dconf->other = val;
} else {
ret = CL_EMALFDB;
@ -445,8 +442,8 @@ int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, str
}
}
if(!strncmp(buffer, "PHISHING:", 9) && chkflevel(buffer, 2)) {
if(sscanf(buffer + 9, "0x%x", &val) == 1) {
if (!strncmp(buffer, "PHISHING:", 9) && chkflevel(buffer, 2)) {
if (sscanf(buffer + 9, "0x%x", &val) == 1) {
engine->dconf->phishing = val;
} else {
ret = CL_EMALFDB;
@ -454,8 +451,8 @@ int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, str
}
}
if(!strncmp(buffer, "BYTECODE:", 9) && chkflevel(buffer, 2)) {
if(sscanf(buffer + 9, "0x%x", &val) == 1) {
if (!strncmp(buffer, "BYTECODE:", 9) && chkflevel(buffer, 2)) {
if (sscanf(buffer + 9, "0x%x", &val) == 1) {
engine->dconf->bytecode = val;
} else {
ret = CL_EMALFDB;
@ -463,8 +460,8 @@ int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, str
}
}
if(!strncmp(buffer, "STATS:", 6) && chkflevel(buffer, 2)) {
if(sscanf(buffer + 6, "0x%x", &val) == 1) {
if (!strncmp(buffer, "STATS:", 6) && chkflevel(buffer, 2)) {
if (sscanf(buffer + 6, "0x%x", &val) == 1) {
engine->dconf->stats = val;
} else {
ret = CL_EMALFDB;
@ -472,8 +469,8 @@ int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, str
}
}
if(!strncmp(buffer, "PCRE:", 5) && chkflevel(buffer, 2)) {
if(sscanf(buffer + 5, "0x%x", &val) == 1) {
if (!strncmp(buffer, "PCRE:", 5) && chkflevel(buffer, 2)) {
if (sscanf(buffer + 5, "0x%x", &val) == 1) {
engine->dconf->pcre = val;
} else {
ret = CL_EMALFDB;
@ -482,7 +479,7 @@ int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, str
}
}
if(ret) {
if (ret) {
cli_errmsg("Problem parsing configuration file at line %u\n", line);
return ret;
}

View file

@ -25,327 +25,374 @@
/** @file */
/** X86 opcode */
enum X86OPS {
OP_INVALID,
OP_AAA,/**< Ascii Adjust after Addition */
OP_AAD,/**< Ascii Adjust AX before Division */
OP_AAM,/**< Ascii Adjust AX after Multiply */
OP_AAS,/**< Ascii Adjust AL after Subtraction */
OP_ADD,/**< Add */
OP_ADC,/**< Add with Carry */
OP_AND,/**< Logical And */
OP_ARPL,/**< Adjust Requested Privilege Level */
OP_BOUND,/**< Check Array Index Against Bounds */
OP_BSF,/**< Bit Scan Forward */
OP_BSR,/**< Bit Scan Reverse */
OP_BSWAP,/**< Byte Swap */
OP_BT,/**< Bit Test */
OP_BTC,/**< Bit Test and Complement */
OP_BTR,/**< Bit Test and Reset */
OP_BTS,/**< Bit Test and Set */
OP_CALL,/**< Call */
OP_CDQ,/**< Convert DoubleWord to QuadWord*/
OP_CWD,
OP_CWDE,/**< Convert Word to DoubleWord */
OP_CBW,/**< Convert Byte to Word */
OP_CLC,/**< Clear Carry Flag */
OP_CLD,/**< Clear Direction Flag */
OP_CLI,/**< Clear Interrupt Flag */
OP_CLTS,/**< Clear Task-Switched Flag in CR0 */
OP_CMC,/**< Complement Carry Flag */
OP_CMOVO,/**< Conditional Move if Overflow */
OP_CMOVNO,/**< Conditional Move if Not Overflow */
OP_CMOVC,/**< Conditional Move if Carry */
OP_CMOVNC,/**< Conditional Move if Not Carry */
OP_CMOVZ,/**< Conditional Move if Zero */
OP_CMOVNZ,/**< Conditional Move if Non-Zero */
OP_CMOVBE,/**< Conditional Move if Below or Equal */
OP_CMOVA,/**< Conditional Move if Above */
OP_CMOVS,/**< Conditional Move if Sign */
OP_CMOVNS,/**< Conditional Move if Not Sign */
OP_CMOVP,/**< Conditional Move if Parity */
OP_CMOVNP,/**< Conditional Move if Not Parity */
OP_CMOVL,/**< Conditional Move if Less */
OP_CMOVGE,/**< Conditional Move if Greater or Equal */
OP_CMOVLE,/**< Conditional Move if Less than or Equal */
OP_CMOVG,/**< Conditional Move if Greater */
OP_CMP,/**< Compare */
OP_CMPSD,/**< Compare String DoubleWord */
OP_CMPSW,/**< Compare String Word */
OP_CMPSB,/**< Compare String Byte */
OP_CMPXCHG,/**< Compare and Exchange */
OP_CMPXCHG8B,/**< Compare and Exchange Bytes */
OP_CPUID,/**< CPU Identification */
OP_DAA,/**< Decimal Adjust AL after Addition */
OP_DAS,/**< Decimal Adjust AL after Subtraction */
OP_DEC,/**< Decrement by 1 */
OP_DIV,/**< Unsigned Divide */
OP_ENTER,/**< Make Stack Frame for Procedure Parameters */
OP_FWAIT,/**< Wait */
OP_HLT,/**< Halt */
OP_IDIV,/**< Signed Divide */
OP_IMUL,/**< Signed Multiply */
OP_INC,/**< Increment by 1 */
OP_IN,/**< INput from port */
OP_INSD,/**< INput from port to String Doubleword */
OP_INSW,/**< INput from port to String Word */
OP_INSB,/**< INput from port to String Byte */
OP_INT,/**< INTerrupt */
OP_INT3,/**< INTerrupt 3 (breakpoint) */
OP_INTO,/**< INTerrupt 4 if Overflow */
OP_INVD,/**< Invalidate Internal Caches */
OP_INVLPG,/**< Invalidate TLB Entry */
OP_IRET,/**< Interrupt Return */
OP_JO,/**< Jump if Overflow */
OP_JNO,/**< Jump if Not Overflow */
OP_JC,/**< Jump if Carry */
OP_JNC,/**< Jump if Not Carry */
OP_JZ,/**< Jump if Zero */
OP_JNZ,/**< Jump if Not Zero */
OP_JBE,/**< Jump if Below or Equal */
OP_JA,/**< Jump if Above */
OP_JS,/**< Jump if Sign */
OP_JNS,/**< Jump if Not Sign */
OP_JP,/**< Jump if Parity */
OP_JNP,/**< Jump if Not Parity */
OP_JL,/**< Jump if Less */
OP_JGE,/**< Jump if Greater or Equal */
OP_JLE,/**< Jump if Less or Equal */
OP_JG,/**< Jump if Greater */
OP_JMP,/**< Jump (unconditional) */
OP_LAHF,/**< Load Status Flags into AH Register */
OP_LAR,/**< load Access Rights Byte */
OP_LDS,/**< Load Far Pointer into DS */
OP_LES,/**< Load Far Pointer into ES */
OP_LFS,/**< Load Far Pointer into FS */
OP_LGS,/**< Load Far Pointer into GS */
OP_LEA,/**< Load Effective Address */
OP_LEAVE,/**< High Level Procedure Exit */
OP_LGDT,/**< Load Global Descript Table Register */
OP_LIDT,/**< Load Interrupt Descriptor Table Register */
OP_LLDT,/**< Load Local Descriptor Table Register */
OP_PREFIX_LOCK,/**< Assert LOCK# Signal Prefix */
OP_LODSD,/**< Load String Dword*/
OP_LODSW,/**< Load String Word */
OP_LODSB,/**< Load String Byte */
OP_LOOP,/**< Loop According to ECX Counter */
OP_LOOPE,/**< Loop According to ECX Counter and ZF=1 */
OP_LOOPNE,/**< Loop According to ECX Counter and ZF=0 */
OP_JECXZ,/**< Jump if ECX is Zero */
OP_LSL,/**< Load Segment Limit */
OP_LSS,/**< Load Far Pointer into SS */
OP_LTR,/**< Load Task Register */
OP_MOV,/**< Move */
OP_MOVSD,/**< Move Data from String to String Doubleword */
OP_MOVSW,/**< Move Data from String to String Word */
OP_MOVSB,/**< Move Data from String to String Byte */
OP_MOVSX,/**< Move with Sign-Extension */
OP_MOVZX,/**< Move with Zero-Extension */
OP_MUL,/**< Unsigned Multiply */
OP_NEG,/**< Two's Complement Negation */
OP_NOP,/**< No Operation */
OP_NOT,/**< One's Complement Negation */
OP_OR,/**< Logical Inclusive OR */
OP_OUT,/**< Output to Port */
OP_OUTSD,/**< Output String to Port Doubleword */
OP_OUTSW,/**< Output String to Port Word */
OP_OUTSB,/**< Output String to Port Bytes */
OP_PUSH,/**< Push Onto the Stack */
OP_PUSHAD,/**< Push All Double General Purpose Registers */
OP_PUSHA,
OP_PUSHFD,/**< Push EFLAGS Register onto the Stack */
OP_PUSHF,
OP_POP,/**< Pop a Value from the Stack */
OP_POPAD,/**< Pop All Double General Purpose Registers from the Stack */
OP_POPFD,/**< Pop Stack into EFLAGS Register */
OP_POPF,
OP_RCL,/**< Rotate Carry Left */
OP_RCR,/**< Rotate Carry Right */
OP_RDMSR,/**< Read from Model Specific Register */
OP_RDPMC,/**< Read Performance Monitoring Counters */
OP_RDTSC,/**< Read Time-Stamp Counter */
OP_PREFIX_REPE,/**< Repeat String Operation Prefix while Equal */
OP_PREFIX_REPNE,/**< Repeat String Operation Prefix while Not Equal */
OP_RETF,/**< Return from Far Procedure */
OP_RETN,/**< Return from Near Procedure */
OP_ROL,/**< Rotate Left */
OP_ROR,/**< Rotate Right */
OP_RSM,/**< Resume from System Management Mode */
OP_SAHF,/**< Store AH into Flags */
OP_SAR,/**< Shift Arithmetic Right */
OP_SBB,/**< Subtract with Borrow */
OP_SCASD,/**< Scan String Doubleword */
OP_SCASW,/**< Scan String Word */
OP_SCASB,/**< Scan String Byte */
OP_SETO,/**< Set Byte on Overflow */
OP_SETNO,/**< Set Byte on Not Overflow */
OP_SETC,/**< Set Byte on Carry */
OP_SETNC,/**< Set Byte on Not Carry */
OP_SETZ,/**< Set Byte on Zero */
OP_SETNZ,/**< Set Byte on Not Zero */
OP_SETBE,/**< Set Byte on Below or Equal */
OP_SETA,/**< Set Byte on Above */
OP_SETS,/**< Set Byte on Sign */
OP_SETNS,/**< Set Byte on Not Sign */
OP_SETP,/**< Set Byte on Parity */
OP_SETNP,/**< Set Byte on Not Parity */
OP_SETL,/**< Set Byte on Less */
OP_SETGE,/**< Set Byte on Greater or Equal */
OP_SETLE,/**< Set Byte on Less or Equal */
OP_SETG,/**< Set Byte on Greater */
OP_SGDT,/**< Store Global Descriptor Table Register */
OP_SIDT,/**< Store Interrupt Descriptor Table Register */
OP_SHL,/**< Shift Left */
OP_SHLD,/**< Double Precision Shift Left */
OP_SHR,/**< Shift Right */
OP_SHRD,/**< Double Precision Shift Right */
OP_SLDT,/**< Store Local Descriptor Table Register */
OP_STOSD,/**< Store String Doubleword */
OP_STOSW,/**< Store String Word */
OP_STOSB,/**< Store String Byte */
OP_STR,/**< Store Task Register */
OP_STC,/**< Set Carry Flag */
OP_STD,/**< Set Direction Flag */
OP_STI,/**< Set Interrupt Flag */
OP_SUB,/**< Subtract */
OP_SYSCALL,/**< Fast System Call */
OP_SYSENTER,/**< Fast System Call */
OP_SYSEXIT,/**< Fast Return from Fast System Call */
OP_SYSRET,/**< Return from Fast System Call */
OP_TEST,/**< Logical Compare */
OP_UD2,/**< Undefined Instruction */
OP_VERR,/**< Verify a Segment for Reading */
OP_VERRW,/**< Verify a Segment for Writing */
OP_WBINVD,/**< Write Back and Invalidate Cache */
OP_WRMSR,/**< Write to Model Specific Register */
OP_XADD,/**< Exchange and Add */
OP_XCHG,/**< Exchange Register/Memory with Register */
OP_XLAT,/**< Table Look-up Translation */
OP_XOR,/**< Logical Exclusive OR */
OP_PREFIX_OPSIZE,
OP_PREFIX_ADDRSIZE,
OP_PREFIX_SEGMENT,
OP_2BYTE,
OP_INVALID,
OP_AAA, /**< Ascii Adjust after Addition */
OP_AAD, /**< Ascii Adjust AX before Division */
OP_AAM, /**< Ascii Adjust AX after Multiply */
OP_AAS, /**< Ascii Adjust AL after Subtraction */
OP_ADD, /**< Add */
OP_ADC, /**< Add with Carry */
OP_AND, /**< Logical And */
OP_ARPL, /**< Adjust Requested Privilege Level */
OP_BOUND, /**< Check Array Index Against Bounds */
OP_BSF, /**< Bit Scan Forward */
OP_BSR, /**< Bit Scan Reverse */
OP_BSWAP, /**< Byte Swap */
OP_BT, /**< Bit Test */
OP_BTC, /**< Bit Test and Complement */
OP_BTR, /**< Bit Test and Reset */
OP_BTS, /**< Bit Test and Set */
OP_CALL, /**< Call */
OP_CDQ, /**< Convert DoubleWord to QuadWord*/
OP_CWD,
OP_CWDE, /**< Convert Word to DoubleWord */
OP_CBW, /**< Convert Byte to Word */
OP_CLC, /**< Clear Carry Flag */
OP_CLD, /**< Clear Direction Flag */
OP_CLI, /**< Clear Interrupt Flag */
OP_CLTS, /**< Clear Task-Switched Flag in CR0 */
OP_CMC, /**< Complement Carry Flag */
OP_CMOVO, /**< Conditional Move if Overflow */
OP_CMOVNO, /**< Conditional Move if Not Overflow */
OP_CMOVC, /**< Conditional Move if Carry */
OP_CMOVNC, /**< Conditional Move if Not Carry */
OP_CMOVZ, /**< Conditional Move if Zero */
OP_CMOVNZ, /**< Conditional Move if Non-Zero */
OP_CMOVBE, /**< Conditional Move if Below or Equal */
OP_CMOVA, /**< Conditional Move if Above */
OP_CMOVS, /**< Conditional Move if Sign */
OP_CMOVNS, /**< Conditional Move if Not Sign */
OP_CMOVP, /**< Conditional Move if Parity */
OP_CMOVNP, /**< Conditional Move if Not Parity */
OP_CMOVL, /**< Conditional Move if Less */
OP_CMOVGE, /**< Conditional Move if Greater or Equal */
OP_CMOVLE, /**< Conditional Move if Less than or Equal */
OP_CMOVG, /**< Conditional Move if Greater */
OP_CMP, /**< Compare */
OP_CMPSD, /**< Compare String DoubleWord */
OP_CMPSW, /**< Compare String Word */
OP_CMPSB, /**< Compare String Byte */
OP_CMPXCHG, /**< Compare and Exchange */
OP_CMPXCHG8B, /**< Compare and Exchange Bytes */
OP_CPUID, /**< CPU Identification */
OP_DAA, /**< Decimal Adjust AL after Addition */
OP_DAS, /**< Decimal Adjust AL after Subtraction */
OP_DEC, /**< Decrement by 1 */
OP_DIV, /**< Unsigned Divide */
OP_ENTER, /**< Make Stack Frame for Procedure Parameters */
OP_FWAIT, /**< Wait */
OP_HLT, /**< Halt */
OP_IDIV, /**< Signed Divide */
OP_IMUL, /**< Signed Multiply */
OP_INC, /**< Increment by 1 */
OP_IN, /**< INput from port */
OP_INSD, /**< INput from port to String Doubleword */
OP_INSW, /**< INput from port to String Word */
OP_INSB, /**< INput from port to String Byte */
OP_INT, /**< INTerrupt */
OP_INT3, /**< INTerrupt 3 (breakpoint) */
OP_INTO, /**< INTerrupt 4 if Overflow */
OP_INVD, /**< Invalidate Internal Caches */
OP_INVLPG, /**< Invalidate TLB Entry */
OP_IRET, /**< Interrupt Return */
OP_JO, /**< Jump if Overflow */
OP_JNO, /**< Jump if Not Overflow */
OP_JC, /**< Jump if Carry */
OP_JNC, /**< Jump if Not Carry */
OP_JZ, /**< Jump if Zero */
OP_JNZ, /**< Jump if Not Zero */
OP_JBE, /**< Jump if Below or Equal */
OP_JA, /**< Jump if Above */
OP_JS, /**< Jump if Sign */
OP_JNS, /**< Jump if Not Sign */
OP_JP, /**< Jump if Parity */
OP_JNP, /**< Jump if Not Parity */
OP_JL, /**< Jump if Less */
OP_JGE, /**< Jump if Greater or Equal */
OP_JLE, /**< Jump if Less or Equal */
OP_JG, /**< Jump if Greater */
OP_JMP, /**< Jump (unconditional) */
OP_LAHF, /**< Load Status Flags into AH Register */
OP_LAR, /**< load Access Rights Byte */
OP_LDS, /**< Load Far Pointer into DS */
OP_LES, /**< Load Far Pointer into ES */
OP_LFS, /**< Load Far Pointer into FS */
OP_LGS, /**< Load Far Pointer into GS */
OP_LEA, /**< Load Effective Address */
OP_LEAVE, /**< High Level Procedure Exit */
OP_LGDT, /**< Load Global Descript Table Register */
OP_LIDT, /**< Load Interrupt Descriptor Table Register */
OP_LLDT, /**< Load Local Descriptor Table Register */
OP_PREFIX_LOCK, /**< Assert LOCK# Signal Prefix */
OP_LODSD, /**< Load String Dword*/
OP_LODSW, /**< Load String Word */
OP_LODSB, /**< Load String Byte */
OP_LOOP, /**< Loop According to ECX Counter */
OP_LOOPE, /**< Loop According to ECX Counter and ZF=1 */
OP_LOOPNE, /**< Loop According to ECX Counter and ZF=0 */
OP_JECXZ, /**< Jump if ECX is Zero */
OP_LSL, /**< Load Segment Limit */
OP_LSS, /**< Load Far Pointer into SS */
OP_LTR, /**< Load Task Register */
OP_MOV, /**< Move */
OP_MOVSD, /**< Move Data from String to String Doubleword */
OP_MOVSW, /**< Move Data from String to String Word */
OP_MOVSB, /**< Move Data from String to String Byte */
OP_MOVSX, /**< Move with Sign-Extension */
OP_MOVZX, /**< Move with Zero-Extension */
OP_MUL, /**< Unsigned Multiply */
OP_NEG, /**< Two's Complement Negation */
OP_NOP, /**< No Operation */
OP_NOT, /**< One's Complement Negation */
OP_OR, /**< Logical Inclusive OR */
OP_OUT, /**< Output to Port */
OP_OUTSD, /**< Output String to Port Doubleword */
OP_OUTSW, /**< Output String to Port Word */
OP_OUTSB, /**< Output String to Port Bytes */
OP_PUSH, /**< Push Onto the Stack */
OP_PUSHAD, /**< Push All Double General Purpose Registers */
OP_PUSHA,
OP_PUSHFD, /**< Push EFLAGS Register onto the Stack */
OP_PUSHF,
OP_POP, /**< Pop a Value from the Stack */
OP_POPAD, /**< Pop All Double General Purpose Registers from the Stack */
OP_POPFD, /**< Pop Stack into EFLAGS Register */
OP_POPF,
OP_RCL, /**< Rotate Carry Left */
OP_RCR, /**< Rotate Carry Right */
OP_RDMSR, /**< Read from Model Specific Register */
OP_RDPMC, /**< Read Performance Monitoring Counters */
OP_RDTSC, /**< Read Time-Stamp Counter */
OP_PREFIX_REPE, /**< Repeat String Operation Prefix while Equal */
OP_PREFIX_REPNE, /**< Repeat String Operation Prefix while Not Equal */
OP_RETF, /**< Return from Far Procedure */
OP_RETN, /**< Return from Near Procedure */
OP_ROL, /**< Rotate Left */
OP_ROR, /**< Rotate Right */
OP_RSM, /**< Resume from System Management Mode */
OP_SAHF, /**< Store AH into Flags */
OP_SAR, /**< Shift Arithmetic Right */
OP_SBB, /**< Subtract with Borrow */
OP_SCASD, /**< Scan String Doubleword */
OP_SCASW, /**< Scan String Word */
OP_SCASB, /**< Scan String Byte */
OP_SETO, /**< Set Byte on Overflow */
OP_SETNO, /**< Set Byte on Not Overflow */
OP_SETC, /**< Set Byte on Carry */
OP_SETNC, /**< Set Byte on Not Carry */
OP_SETZ, /**< Set Byte on Zero */
OP_SETNZ, /**< Set Byte on Not Zero */
OP_SETBE, /**< Set Byte on Below or Equal */
OP_SETA, /**< Set Byte on Above */
OP_SETS, /**< Set Byte on Sign */
OP_SETNS, /**< Set Byte on Not Sign */
OP_SETP, /**< Set Byte on Parity */
OP_SETNP, /**< Set Byte on Not Parity */
OP_SETL, /**< Set Byte on Less */
OP_SETGE, /**< Set Byte on Greater or Equal */
OP_SETLE, /**< Set Byte on Less or Equal */
OP_SETG, /**< Set Byte on Greater */
OP_SGDT, /**< Store Global Descriptor Table Register */
OP_SIDT, /**< Store Interrupt Descriptor Table Register */
OP_SHL, /**< Shift Left */
OP_SHLD, /**< Double Precision Shift Left */
OP_SHR, /**< Shift Right */
OP_SHRD, /**< Double Precision Shift Right */
OP_SLDT, /**< Store Local Descriptor Table Register */
OP_STOSD, /**< Store String Doubleword */
OP_STOSW, /**< Store String Word */
OP_STOSB, /**< Store String Byte */
OP_STR, /**< Store Task Register */
OP_STC, /**< Set Carry Flag */
OP_STD, /**< Set Direction Flag */
OP_STI, /**< Set Interrupt Flag */
OP_SUB, /**< Subtract */
OP_SYSCALL, /**< Fast System Call */
OP_SYSENTER, /**< Fast System Call */
OP_SYSEXIT, /**< Fast Return from Fast System Call */
OP_SYSRET, /**< Return from Fast System Call */
OP_TEST, /**< Logical Compare */
OP_UD2, /**< Undefined Instruction */
OP_VERR, /**< Verify a Segment for Reading */
OP_VERRW, /**< Verify a Segment for Writing */
OP_WBINVD, /**< Write Back and Invalidate Cache */
OP_WRMSR, /**< Write to Model Specific Register */
OP_XADD, /**< Exchange and Add */
OP_XCHG, /**< Exchange Register/Memory with Register */
OP_XLAT, /**< Table Look-up Translation */
OP_XOR, /**< Logical Exclusive OR */
OP_PREFIX_OPSIZE,
OP_PREFIX_ADDRSIZE,
OP_PREFIX_SEGMENT,
OP_2BYTE,
OP_FPU,/**< FPU operation */
OP_FPU, /**< FPU operation */
OP_F2XM1,/**< Compute 2x-1 */
OP_FABS,/**< Absolute Value */
OP_FADD,/**< Floating Point Add */
OP_FADDP,/**< Floating Point Add, Pop */
OP_FBLD,/**< Load Binary Coded Decimal */
OP_FBSTP,/**< Store BCD Integer and Pop */
OP_FCHS,/**< Change Sign */
OP_FCLEX,/**< Clear Exceptions */
OP_FCMOVB,/**< Floating Point Move on Below */
OP_FCMOVBE,/**< Floating Point Move on Below or Equal */
OP_FCMOVE,/**< Floating Point Move on Equal */
OP_FCMOVNB,/**< Floating Point Move on Not Below */
OP_FCMOVNBE,/**< Floating Point Move on Not Below or Equal */
OP_FCMOVNE,/**< Floating Point Move on Not Equal */
OP_FCMOVNU,/**< Floating Point Move on Not Unordered */
OP_FCMOVU,/**< Floating Point Move on Unordered */
OP_FCOM,/**< Compare Floating Pointer Values and Set FPU Flags */
OP_FCOMI,/**< Compare Floating Pointer Values and Set EFLAGS */
OP_FCOMIP,/**< Compare Floating Pointer Values and Set EFLAGS, Pop */
OP_FCOMP,/**< Compare Floating Pointer Values and Set FPU Flags, Pop */
OP_FCOMPP,/**< Compare Floating Pointer Values and Set FPU Flags, Pop Twice */
OP_FCOS,/**< Cosine */
OP_FDECSTP,/**< Decrement Stack Top Pointer */
OP_FDIV,/**< Floating Point Divide */
OP_FDIVP,/**< Floating Point Divide, Pop */
OP_FDIVR,/**< Floating Point Reverse Divide */
OP_FDIVRP,/**< Floating Point Reverse Divide, Pop */
OP_FFREE,/**< Free Floating Point Register */
OP_FIADD,/**< Floating Point Add */
OP_FICOM,/**< Compare Integer */
OP_FICOMP,/**< Compare Integer, Pop */
OP_FIDIV,/**< Floating Point Divide by Integer */
OP_FIDIVR,/**< Floating Point Reverse Divide by Integer */
OP_FILD,/**< Load Integer */
OP_FIMUL,/**< Floating Point Multiply with Integer */
OP_FINCSTP,/**< Increment Stack-Top Pointer */
OP_FINIT,/**< Initialize Floating-Point Unit */
OP_FIST,/**< Store Integer */
OP_FISTP,/**< Store Integer, Pop */
OP_FISTTP,/**< Store Integer with Truncation */
OP_FISUB,/**< Floating Point Integer Subtract */
OP_FISUBR,/**< Floating Point Reverse Integer Subtract */
OP_FLD,/**< Load Floating Point Value */
OP_FLD1,/**< Load Constant 1 */
OP_FLDCW,/**< Load x87 FPU Control Word */
OP_FLDENV,/**< Load x87 FPU Environment */
OP_FLDL2E,/**< Load Constant log_2(e) */
OP_FLDL2T,/**< Load Constant log_2(10) */
OP_FLDLG2,/**< Load Constant log_10(2) */
OP_FLDLN2,/**< Load Constant log_e(2) */
OP_FLDPI,/**< Load Constant PI */
OP_FLDZ,/**< Load Constant Zero */
OP_FMUL,/**< Floating Point Multiply */
OP_FMULP,/**< Floating Point Multiply, Pop */
OP_FNOP,/**< No Operation */
OP_FPATAN,/**< Partial Arctangent */
OP_FPREM,/**< Partial Remainder */
OP_FPREM1,/**< Partial Remainder */
OP_FPTAN,/**< Partial Tangent */
OP_FRNDINT,/**< Round to Integer */
OP_FRSTOR,/**< Restore x86 FPU State */
OP_FSCALE,/**< Scale */
OP_FSIN,/* Sine */
OP_FSINCOS,/**< Sine and Cosine */
OP_FSQRT,/**< Square Root */
OP_FSAVE,/**< Store x87 FPU State */
OP_FST,/**< Store Floating Point Value */
OP_FSTCW,/**< Store x87 FPU Control Word */
OP_FSTENV,/**< Store x87 FPU Environment */
OP_FSTP,/**< Store Floating Point Value, Pop */
OP_FSTSW,/**< Store x87 FPU Status Word */
OP_FSUB,/**< Floating Point Subtract */
OP_FSUBP,/**< Floating Point Subtract, Pop */
OP_FSUBR,/**< Floating Point Reverse Subtract */
OP_FSUBRP,/**< Floating Point Reverse Subtract, Pop */
OP_FTST,/**< Floating Point Test */
OP_FUCOM,/**< Floating Point Unordered Compare */
OP_FUCOMI,/**< Floating Point Unordered Compare with Integer */
OP_FUCOMIP,/**< Floating Point Unorder Compare with Integer, Pop */
OP_FUCOMP,/**< Floating Point Unorder Compare, Pop */
OP_FUCOMPP,/**< Floating Point Unorder Compare, Pop Twice */
OP_FXAM,/**< Examine ModR/M */
OP_FXCH,/**< Exchange Register Contents */
OP_FXTRACT,/**< Extract Exponent and Significand */
OP_FYL2X,/**< Compute y*log2x */
OP_FYL2XP1 /**< Compute y*log2(x+1) */
OP_F2XM1, /**< Compute 2x-1 */
OP_FABS, /**< Absolute Value */
OP_FADD, /**< Floating Point Add */
OP_FADDP, /**< Floating Point Add, Pop */
OP_FBLD, /**< Load Binary Coded Decimal */
OP_FBSTP, /**< Store BCD Integer and Pop */
OP_FCHS, /**< Change Sign */
OP_FCLEX, /**< Clear Exceptions */
OP_FCMOVB, /**< Floating Point Move on Below */
OP_FCMOVBE, /**< Floating Point Move on Below or Equal */
OP_FCMOVE, /**< Floating Point Move on Equal */
OP_FCMOVNB, /**< Floating Point Move on Not Below */
OP_FCMOVNBE, /**< Floating Point Move on Not Below or Equal */
OP_FCMOVNE, /**< Floating Point Move on Not Equal */
OP_FCMOVNU, /**< Floating Point Move on Not Unordered */
OP_FCMOVU, /**< Floating Point Move on Unordered */
OP_FCOM, /**< Compare Floating Pointer Values and Set FPU Flags */
OP_FCOMI, /**< Compare Floating Pointer Values and Set EFLAGS */
OP_FCOMIP, /**< Compare Floating Pointer Values and Set EFLAGS, Pop */
OP_FCOMP, /**< Compare Floating Pointer Values and Set FPU Flags, Pop */
OP_FCOMPP, /**< Compare Floating Pointer Values and Set FPU Flags, Pop Twice */
OP_FCOS, /**< Cosine */
OP_FDECSTP, /**< Decrement Stack Top Pointer */
OP_FDIV, /**< Floating Point Divide */
OP_FDIVP, /**< Floating Point Divide, Pop */
OP_FDIVR, /**< Floating Point Reverse Divide */
OP_FDIVRP, /**< Floating Point Reverse Divide, Pop */
OP_FFREE, /**< Free Floating Point Register */
OP_FIADD, /**< Floating Point Add */
OP_FICOM, /**< Compare Integer */
OP_FICOMP, /**< Compare Integer, Pop */
OP_FIDIV, /**< Floating Point Divide by Integer */
OP_FIDIVR, /**< Floating Point Reverse Divide by Integer */
OP_FILD, /**< Load Integer */
OP_FIMUL, /**< Floating Point Multiply with Integer */
OP_FINCSTP, /**< Increment Stack-Top Pointer */
OP_FINIT, /**< Initialize Floating-Point Unit */
OP_FIST, /**< Store Integer */
OP_FISTP, /**< Store Integer, Pop */
OP_FISTTP, /**< Store Integer with Truncation */
OP_FISUB, /**< Floating Point Integer Subtract */
OP_FISUBR, /**< Floating Point Reverse Integer Subtract */
OP_FLD, /**< Load Floating Point Value */
OP_FLD1, /**< Load Constant 1 */
OP_FLDCW, /**< Load x87 FPU Control Word */
OP_FLDENV, /**< Load x87 FPU Environment */
OP_FLDL2E, /**< Load Constant log_2(e) */
OP_FLDL2T, /**< Load Constant log_2(10) */
OP_FLDLG2, /**< Load Constant log_10(2) */
OP_FLDLN2, /**< Load Constant log_e(2) */
OP_FLDPI, /**< Load Constant PI */
OP_FLDZ, /**< Load Constant Zero */
OP_FMUL, /**< Floating Point Multiply */
OP_FMULP, /**< Floating Point Multiply, Pop */
OP_FNOP, /**< No Operation */
OP_FPATAN, /**< Partial Arctangent */
OP_FPREM, /**< Partial Remainder */
OP_FPREM1, /**< Partial Remainder */
OP_FPTAN, /**< Partial Tangent */
OP_FRNDINT, /**< Round to Integer */
OP_FRSTOR, /**< Restore x86 FPU State */
OP_FSCALE, /**< Scale */
OP_FSIN, /* Sine */
OP_FSINCOS, /**< Sine and Cosine */
OP_FSQRT, /**< Square Root */
OP_FSAVE, /**< Store x87 FPU State */
OP_FST, /**< Store Floating Point Value */
OP_FSTCW, /**< Store x87 FPU Control Word */
OP_FSTENV, /**< Store x87 FPU Environment */
OP_FSTP, /**< Store Floating Point Value, Pop */
OP_FSTSW, /**< Store x87 FPU Status Word */
OP_FSUB, /**< Floating Point Subtract */
OP_FSUBP, /**< Floating Point Subtract, Pop */
OP_FSUBR, /**< Floating Point Reverse Subtract */
OP_FSUBRP, /**< Floating Point Reverse Subtract, Pop */
OP_FTST, /**< Floating Point Test */
OP_FUCOM, /**< Floating Point Unordered Compare */
OP_FUCOMI, /**< Floating Point Unordered Compare with Integer */
OP_FUCOMIP, /**< Floating Point Unorder Compare with Integer, Pop */
OP_FUCOMP, /**< Floating Point Unorder Compare, Pop */
OP_FUCOMPP, /**< Floating Point Unorder Compare, Pop Twice */
OP_FXAM, /**< Examine ModR/M */
OP_FXCH, /**< Exchange Register Contents */
OP_FXTRACT, /**< Extract Exponent and Significand */
OP_FYL2X, /**< Compute y*log2x */
OP_FYL2XP1 /**< Compute y*log2(x+1) */
};
/** Access type */
enum DIS_ACCESS {
ACCESS_NOARG, /**< arg not present */
ACCESS_IMM, /**< immediate */
ACCESS_REL, /**< +/- immediate */
ACCESS_REG, /**< register */
ACCESS_MEM /**< [memory] */
ACCESS_NOARG, /**< arg not present */
ACCESS_IMM, /**< immediate */
ACCESS_REL, /**< +/- immediate */
ACCESS_REG, /**< register */
ACCESS_MEM /**< [memory] */
};
/** for mem access, immediate and relative */
enum DIS_SIZE {
SIZEB,/**< Byte size access */
SIZEW,/**< Word size access */
SIZED,/**< Doubleword size access */
SIZEF,/**< 6-byte access (seg+reg pair)*/
SIZEQ,/**< Quadword access */
SIZET,/**< 10-byte access */
SIZEPTR /** ptr */
SIZEB, /**< Byte size access */
SIZEW, /**< Word size access */
SIZED, /**< Doubleword size access */
SIZEF, /**< 6-byte access (seg+reg pair)*/
SIZEQ, /**< Quadword access */
SIZET, /**< 10-byte access */
SIZEPTR /** ptr */
};
/** X86 registers */
enum X86REGS {
X86_REG_EAX, X86_REG_ECX, X86_REG_EDX, X86_REG_EBX, X86_REG_ESP, X86_REG_EBP, X86_REG_ESI, X86_REG_EDI,
X86_REG_AX, X86_REG_CX, X86_REG_DX, X86_REG_BX, X86_REG_SP, X86_REG_BP, X86_REG_SI, X86_REG_DI,
X86_REG_AH, X86_REG_CH, X86_REG_DH, X86_REG_BH, X86_REG_AL, X86_REG_CL, X86_REG_DL, X86_REG_BL,
X86_REG_ES, X86_REG_CS, X86_REG_SS, X86_REG_DS, X86_REG_FS, X86_REG_GS,
X86_REG_CR0, X86_REG_CR1, X86_REG_CR2, X86_REG_CR3, X86_REG_CR4, X86_REG_CR5, X86_REG_CR6, X86_REG_CR7,
X86_REG_DR0, X86_REG_DR1, X86_REG_DR2, X86_REG_DR3, X86_REG_DR4, X86_REG_DR5, X86_REG_DR6, X86_REG_DR7,
X86_REG_ST0, X86_REG_ST1, X86_REG_ST2, X86_REG_ST3, X86_REG_ST4, X86_REG_ST5, X86_REG_ST6, X86_REG_ST7,
X86_REG_INVALID
X86_REG_EAX,
X86_REG_ECX,
X86_REG_EDX,
X86_REG_EBX,
X86_REG_ESP,
X86_REG_EBP,
X86_REG_ESI,
X86_REG_EDI,
X86_REG_AX,
X86_REG_CX,
X86_REG_DX,
X86_REG_BX,
X86_REG_SP,
X86_REG_BP,
X86_REG_SI,
X86_REG_DI,
X86_REG_AH,
X86_REG_CH,
X86_REG_DH,
X86_REG_BH,
X86_REG_AL,
X86_REG_CL,
X86_REG_DL,
X86_REG_BL,
X86_REG_ES,
X86_REG_CS,
X86_REG_SS,
X86_REG_DS,
X86_REG_FS,
X86_REG_GS,
X86_REG_CR0,
X86_REG_CR1,
X86_REG_CR2,
X86_REG_CR3,
X86_REG_CR4,
X86_REG_CR5,
X86_REG_CR6,
X86_REG_CR7,
X86_REG_DR0,
X86_REG_DR1,
X86_REG_DR2,
X86_REG_DR3,
X86_REG_DR4,
X86_REG_DR5,
X86_REG_DR6,
X86_REG_DR7,
X86_REG_ST0,
X86_REG_ST1,
X86_REG_ST2,
X86_REG_ST3,
X86_REG_ST4,
X86_REG_ST5,
X86_REG_ST6,
X86_REG_ST7,
X86_REG_INVALID
};
/** disassembly result, 64-byte, matched by type-8 signatures */
@ -358,4 +405,3 @@ struct DISASM_RESULT {
uint8_t extra[29];
};
#endif

Some files were not shown because too many files have changed in this diff Show more