95 changes: 57 additions & 38 deletions clamd/server-th.c
Expand Up @@ -718,7 +718,7 @@ static int handle_stream(client_conn_t *conn, struct fd_buf *buf, const struct o
int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsigned int dboptions, const struct optstruct *opts)
{
int max_threads, max_queue, readtimeout, ret = 0;
unsigned int options = 0;
struct cl_scan_options options;
char timestr[32];
#ifndef _WIN32
struct sigaction sigact;
Expand All @@ -742,7 +742,7 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi
threadpool_t *thr_pool;

#if defined(FANOTIFY) || defined(CLAMAUTH)
pthread_t fan_pid;
pthread_t fan_pid = 0;
pthread_attr_t fan_attr;
struct thrarg *tharg = NULL; /* shut up gcc */
#endif
Expand All @@ -751,6 +751,9 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi
memset(&sigact, 0, sizeof(struct sigaction));
#endif

/* Initalize scan options struct */
memset(&options, 0, sizeof(struct cl_scan_options));

/* set up limits */
if((opt = optget(opts, "MaxScanSize"))->active) {
if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCANSIZE, opt->numarg))) {
Expand Down Expand Up @@ -922,11 +925,11 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi

if(optget(opts, "ScanArchive")->enabled) {
logg("Archive support enabled.\n");
options |= CL_SCAN_ARCHIVE;
options.parse |= CL_SCAN_PARSE_ARCHIVE;

if(optget(opts, "ArchiveBlockEncrypted")->enabled) {
logg("Archive: Blocking encrypted archives.\n");
options |= CL_SCAN_BLOCKENCRYPTED;
options.heuristic |= CL_SCAN_HEURISTIC_ENCRYPTED;
}

} else {
Expand All @@ -935,46 +938,46 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi

if (optget(opts, "BlockMax")->enabled) {
logg("BlockMax heuristic detection enabled.\n");
options |= CL_SCAN_BLOCKMAX;
options.heuristic |= CL_SCAN_HEURISTIC_EXCEEDS_MAX;
} else {
logg("BlockMax heuristic detection disabled.\n");
}

if(optget(opts, "AlgorithmicDetection")->enabled) {
logg("Algorithmic detection enabled.\n");
options |= CL_SCAN_ALGORITHMIC;
options.general |= CL_SCAN_GENERAL_HEURISTICS;
} else {
logg("Algorithmic detection disabled.\n");
}

if(optget(opts, "ScanPE")->enabled) {
logg("Portable Executable support enabled.\n");
options |= CL_SCAN_PE;
options.parse |= CL_SCAN_PARSE_PE;
} else {
logg("Portable Executable support disabled.\n");
}

if(optget(opts, "ScanELF")->enabled) {
logg("ELF support enabled.\n");
options |= CL_SCAN_ELF;
options.parse |= CL_SCAN_PARSE_ELF;
} else {
logg("ELF support disabled.\n");
}

if(optget(opts, "ScanPE")->enabled || optget(opts, "ScanELF")->enabled) {
if(optget(opts, "DetectBrokenExecutables")->enabled) {
logg("Detection of broken executables enabled.\n");
options |= CL_SCAN_BLOCKBROKEN;
options.heuristic |= CL_SCAN_HEURISTIC_BROKEN;
}
}

if(optget(opts, "ScanMail")->enabled) {
logg("Mail files support enabled.\n");
options |= CL_SCAN_MAIL;
options.parse |= CL_SCAN_PARSE_MAIL;

if(optget(opts, "ScanPartialMessages")->enabled) {
logg("Mail: RFC1341 handling enabled.\n");
options |= CL_SCAN_PARTIAL_MESSAGE;
options.mail |= CL_SCAN_MAIL_PARTIAL_MESSAGE;
}

} else {
Expand All @@ -983,75 +986,75 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi

if(optget(opts, "ScanOLE2")->enabled) {
logg("OLE2 support enabled.\n");
options |= CL_SCAN_OLE2;
options.parse |= CL_SCAN_PARSE_OLE2;
if(optget(opts, "OLE2BlockMacros")->enabled) {
logg("OLE2: Blocking all VBA macros.\n");
options |= CL_SCAN_BLOCKMACROS;
options.heuristic |= CL_SCAN_HEURISTIC_MACROS;
}
} else {
logg("OLE2 support disabled.\n");
}

if(optget(opts, "ScanPDF")->enabled) {
logg("PDF support enabled.\n");
options |= CL_SCAN_PDF;
options.parse |= CL_SCAN_PARSE_PDF;
} else {
logg("PDF support disabled.\n");
}

if(optget(opts, "ScanSWF")->enabled) {
logg("SWF support enabled.\n");
options |= CL_SCAN_SWF;
options.parse |= CL_SCAN_PARSE_SWF;
} else {
logg("SWF support disabled.\n");
}

if(optget(opts, "ScanHTML")->enabled) {
logg("HTML support enabled.\n");
options |= CL_SCAN_HTML;
options.parse |= CL_SCAN_PARSE_HTML;
} else {
logg("HTML support disabled.\n");
}

if(optget(opts, "ScanXMLDOCS")->enabled) {
logg("XMLDOCS support enabled.\n");
options |= CL_SCAN_XMLDOCS;
options.parse |= CL_SCAN_PARSE_XMLDOCS;
} else {
logg("XMLDOCS support disabled.\n");
}

if(optget(opts, "ScanHWP3")->enabled) {
logg("HWP3 support enabled.\n");
options |= CL_SCAN_HWP3;
options.parse |= CL_SCAN_PARSE_HWP3;
} else {
logg("HWP3 support disabled.\n");
}

if(optget(opts,"PhishingScanURLs")->enabled) {

if(optget(opts,"PhishingAlwaysBlockCloak")->enabled) {
options |= CL_SCAN_PHISHING_BLOCKCLOAK;
options.heuristic |= CL_SCAN_HEURISTIC_PHISHING_CLOAK;
logg("Phishing: Always checking for cloaked urls\n");
}

if(optget(opts,"PhishingAlwaysBlockSSLMismatch")->enabled) {
options |= CL_SCAN_PHISHING_BLOCKSSL;
options.heuristic |= CL_SCAN_HEURISTIC_PHISHING_SSL_MISMATCH;
logg("Phishing: Always checking for ssl mismatches\n");
}
}

if(optget(opts,"PartitionIntersection")->enabled) {
options |= CL_SCAN_PARTITION_INTXN;
options.heuristic |= CL_SCAN_HEURISTIC_PARTITION_INTXN;
logg("Raw DMG: Always checking for partitions intersections\n");
}

if(optget(opts,"HeuristicScanPrecedence")->enabled) {
options |= CL_SCAN_HEURISTIC_PRECEDENCE;
options.general |= CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE;
logg("Heuristic: precedence enabled\n");
}

if(optget(opts, "StructuredDataDetection")->enabled) {
options |= CL_SCAN_STRUCTURED;
options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED;

if((opt = optget(opts, "StructuredMinCreditCardCount"))->enabled) {
if((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_CC_COUNT, opt->numarg))) {
Expand All @@ -1074,15 +1077,15 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi
logg("Structured: Minimum Social Security Number Count set to %u\n", (unsigned int) val);

if(optget(opts, "StructuredSSNFormatNormal")->enabled)
options |= CL_SCAN_STRUCTURED_SSN_NORMAL;
options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL;

if(optget(opts, "StructuredSSNFormatStripped")->enabled)
options |= CL_SCAN_STRUCTURED_SSN_STRIPPED;
options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED;
}

#ifdef HAVE__INTERNAL__SHA_COLLECT
if(optget(opts, "DevCollectHashes")->enabled)
options |= CL_SCAN_INTERNAL_COLLECT_SHA;
options.dev |= CL_SCAN_DEV_COLLECT_SHA;
#endif

selfchk = optget(opts, "SelfCheck")->numarg;
Expand Down Expand Up @@ -1209,18 +1212,34 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi

#if defined(FANOTIFY) || defined(CLAMAUTH)
{
int thread_started = 1;
do {
if(pthread_attr_init(&fan_attr)) break;
pthread_attr_setdetachstate(&fan_attr, PTHREAD_CREATE_JOINABLE);
if(!(tharg = (struct thrarg *) malloc(sizeof(struct thrarg)))) break;
tharg->opts = opts;
tharg->engine = engine;
tharg->options = options;
if(!pthread_create(&fan_pid, &fan_attr, onas_fan_th, tharg)) break;
free(tharg);
tharg=NULL;
} while(0);
if (!tharg) logg("!Unable to start on-access scan\n");
if(pthread_attr_init(&fan_attr)) break;
pthread_attr_setdetachstate(&fan_attr, PTHREAD_CREATE_JOINABLE);

/* Allocate memory for arguments. Thread is responsible for freeing it. */
if (!(tharg = (struct thrarg *) calloc(sizeof(struct thrarg), 1))) break;
if (!(tharg->options = (struct cl_scan_options *) calloc(sizeof(struct cl_scan_options), 1))) break;

(void) memcpy(tharg->options, &options, sizeof(struct cl_scan_options));
tharg->opts = opts;
tharg->engine = engine;

thread_started = pthread_create(&fan_pid, &fan_attr, onas_fan_th, tharg);
} while(0);

if (0 != thread_started) {
/* Failed to create thread. Free anything we may have allocated. */
logg("!Unable to start on-access scan.\n");
if (NULL != tharg) {
if (NULL != tharg->options) {
free(tharg->options);
tharg->options = NULL;
}
free(tharg);
tharg = NULL;
}
}
}
#else
logg("!On-access scan is not available\n");
Expand Down Expand Up @@ -1384,7 +1403,7 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi
conn.scanfd = buf->recvfd;
buf->recvfd = -1;
conn.sd = buf->fd;
conn.options = options;
conn.options = &options;
conn.opts = opts;
conn.thrpool = thr_pool;
conn.engine = engine;
Expand Down
12 changes: 1 addition & 11 deletions clamd/server.h
Expand Up @@ -32,19 +32,9 @@
#include "session.h"
struct thrarg {
int sid;
int options;
struct cl_scan_options *options;
const struct optstruct *opts;
const struct cl_engine *engine;
const struct cl_limits *limits;
};

/* thread watcher arguments */
struct thrwarg {
int socketd;
struct cl_engine **engine;
const struct optstruct *opts;
const struct cl_limits *limits;
unsigned int options;
};

int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsigned int dboptions, const struct optstruct *opts);
Expand Down
4 changes: 2 additions & 2 deletions clamd/session.c
Expand Up @@ -191,7 +191,7 @@ int command(client_conn_t *conn, int *virus)
{
int desc = conn->sd;
struct cl_engine *engine = conn->engine;
unsigned int options = conn->options;
struct cl_scan_options *options = conn->options;
const struct optstruct *opts = conn->opts;
enum scan_type type = TYPE_INIT;
int maxdirrec;
Expand Down Expand Up @@ -369,7 +369,7 @@ int command(client_conn_t *conn, int *virus)
return 1;
}
thrmgr_setactivetask(NULL, "ALLMATCHSCAN");
scandata.options |= CL_SCAN_ALLMATCHES;
scandata.options->general |= CL_SCAN_GENERAL_ALLMATCHES;
type = TYPE_SCAN;
break;
default:
Expand Down
2 changes: 1 addition & 1 deletion clamd/session.h
Expand Up @@ -82,7 +82,7 @@ typedef struct client_conn_tag {
char *filename;
int scanfd;
int sd;
unsigned int options;
struct cl_scan_options *options;
const struct optstruct *opts;
struct cl_engine *engine;
time_t engine_timestamp;
Expand Down
82 changes: 43 additions & 39 deletions clamscan/manager.c
Expand Up @@ -289,7 +289,7 @@ static void clamscan_virus_found_cb(int fd, const char *virname, void *context)
return;
}

static void scanfile(const char *filename, struct cl_engine *engine, const struct optstruct *opts, unsigned int options)
static void scanfile(const char *filename, struct cl_engine *engine, const struct optstruct *opts, struct cl_scan_options *options)
{
int ret = 0, fd, included;
unsigned i;
Expand Down Expand Up @@ -427,7 +427,7 @@ static void scanfile(const char *filename, struct cl_engine *engine, const struc
action(filename);
}

static void scandirs(const char *dirname, struct cl_engine *engine, const struct optstruct *opts, unsigned int options, unsigned int depth, dev_t dev)
static void scandirs(const char *dirname, struct cl_engine *engine, const struct optstruct *opts, struct cl_scan_options *options, unsigned int depth, dev_t dev)
{
DIR *dd;
struct dirent *dent;
Expand Down Expand Up @@ -540,7 +540,7 @@ static void scandirs(const char *dirname, struct cl_engine *engine, const struct
}
}

static int scanstdin(const struct cl_engine *engine, const struct optstruct *opts, int options)
static int scanstdin(const struct cl_engine *engine, const struct optstruct *opts, struct cl_scan_options *options)
{
int ret;
unsigned int fsize = 0;
Expand Down Expand Up @@ -615,7 +615,8 @@ static int scanstdin(const struct cl_engine *engine, const struct optstruct *opt
int scanmanager(const struct optstruct *opts)
{
int ret = 0, i;
unsigned int options = 0, dboptions = 0, dirlnk = 1, filelnk = 1;
struct cl_scan_options options;
unsigned int dboptions = 0, dirlnk = 1, filelnk = 1;
struct cl_engine *engine;
STATBUF sb;
char *file, cwd[1024], *pua_cats = NULL;
Expand All @@ -625,6 +626,9 @@ int scanmanager(const struct optstruct *opts)
struct rlimit rlim;
#endif

/* Initalize scan options struct */
memset(&options, 0, sizeof(struct cl_scan_options));

dirlnk = optget(opts, "follow-dir-symlinks")->numarg;
if(dirlnk > 2) {
logg("!--follow-dir-symlinks: Invalid argument\n");
Expand Down Expand Up @@ -794,7 +798,7 @@ int scanmanager(const struct optstruct *opts)
/* JSON check to prevent engine loading if specified without libjson-c */
#if HAVE_JSON
if (optget(opts, "gen-json")->enabled)
options |= CL_SCAN_FILE_PROPERTIES;
options.general |= CL_SCAN_GENERAL_COLLECT_METADATA;
#else
if (optget(opts, "gen-json")->enabled) {
logg("!Can't generate json (gen-json). libjson-c dev library was missing or misconfigured when ClamAV was built.\n");
Expand Down Expand Up @@ -1010,95 +1014,95 @@ int scanmanager(const struct optstruct *opts)

/* set scan options */
if(optget(opts, "allmatch")->enabled) {
options |= CL_SCAN_ALLMATCHES;
options.general |= CL_SCAN_GENERAL_ALLMATCHES;
}

if(optget(opts,"phishing-ssl")->enabled)
options |= CL_SCAN_PHISHING_BLOCKSSL;
options.heuristic |= CL_SCAN_HEURISTIC_PHISHING_SSL_MISMATCH;

if(optget(opts,"phishing-cloak")->enabled)
options |= CL_SCAN_PHISHING_BLOCKCLOAK;
options.heuristic |= CL_SCAN_HEURISTIC_PHISHING_CLOAK;

if(optget(opts,"partition-intersection")->enabled)
options |= CL_SCAN_PARTITION_INTXN;
options.heuristic |= CL_SCAN_HEURISTIC_PARTITION_INTXN;

if(optget(opts,"heuristic-scan-precedence")->enabled)
options |= CL_SCAN_HEURISTIC_PRECEDENCE;
options.general |= CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE;

if(optget(opts, "scan-archive")->enabled)
options |= CL_SCAN_ARCHIVE;
options.parse |= CL_SCAN_PARSE_ARCHIVE;

if(optget(opts, "detect-broken")->enabled)
options |= CL_SCAN_BLOCKBROKEN;
options.heuristic |= CL_SCAN_HEURISTIC_BROKEN;

if(optget(opts, "block-encrypted")->enabled)
options |= CL_SCAN_BLOCKENCRYPTED;
options.heuristic |= CL_SCAN_HEURISTIC_ENCRYPTED;

if(optget(opts, "block-macros")->enabled)
options |= CL_SCAN_BLOCKMACROS;
options.heuristic |= CL_SCAN_HEURISTIC_MACROS;

if(optget(opts, "scan-pe")->enabled)
options |= CL_SCAN_PE;
options.parse |= CL_SCAN_PARSE_PE;

if(optget(opts, "scan-elf")->enabled)
options |= CL_SCAN_ELF;
options.parse |= CL_SCAN_PARSE_ELF;

if(optget(opts, "scan-ole2")->enabled)
options |= CL_SCAN_OLE2;
options.parse |= CL_SCAN_PARSE_OLE2;

if(optget(opts, "scan-pdf")->enabled)
options |= CL_SCAN_PDF;
options.parse |= CL_SCAN_PARSE_PDF;

if(optget(opts, "scan-swf")->enabled)
options |= CL_SCAN_SWF;
options.parse |= CL_SCAN_PARSE_SWF;

if(optget(opts, "scan-html")->enabled && optget(opts, "normalize")->enabled)
options |= CL_SCAN_HTML;
options.parse |= CL_SCAN_PARSE_HTML;

if(optget(opts, "scan-mail")->enabled)
options |= CL_SCAN_MAIL;
options.parse |= CL_SCAN_PARSE_MAIL;

if(optget(opts, "scan-xmldocs")->enabled)
options |= CL_SCAN_XMLDOCS;
options.parse |= CL_SCAN_PARSE_XMLDOCS;

if(optget(opts, "scan-hwp3")->enabled)
options |= CL_SCAN_HWP3;
options.parse |= CL_SCAN_PARSE_HWP3;

if(optget(opts, "algorithmic-detection")->enabled)
options |= CL_SCAN_ALGORITHMIC;
options.general |= CL_SCAN_GENERAL_HEURISTICS;

if(optget(opts, "block-max")->enabled) {
options |= CL_SCAN_BLOCKMAX;
options.heuristic |= CL_SCAN_HEURISTIC_EXCEEDS_MAX;
}

#ifdef HAVE__INTERNAL__SHA_COLLECT
if(optget(opts, "dev-collect-hashes")->enabled)
options |= CL_SCAN_INTERNAL_COLLECT_SHA;
options.dev |= CL_SCAN_DEV_COLLECT_SHA;
#endif

if(optget(opts, "dev-performance")->enabled)
options |= CL_SCAN_PERFORMANCE_INFO;
options.general |= CL_SCAN_DEV_COLLECT_PERFORMANCE_INFO;

if(optget(opts, "detect-structured")->enabled) {
options |= CL_SCAN_STRUCTURED;
options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED;

if((opt = optget(opts, "structured-ssn-format"))->enabled) {
switch(opt->numarg) {
case 0:
options |= CL_SCAN_STRUCTURED_SSN_NORMAL;
options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL;
break;
case 1:
options |= CL_SCAN_STRUCTURED_SSN_STRIPPED;
options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED;
break;
case 2:
options |= (CL_SCAN_STRUCTURED_SSN_NORMAL | CL_SCAN_STRUCTURED_SSN_STRIPPED);
options.heuristic |= (CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL | CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED);
break;
default:
logg("!Invalid argument for --structured-ssn-format\n");
return 2;
}
} else {
options |= CL_SCAN_STRUCTURED_SSN_NORMAL;
options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL;
}

if((opt = optget(opts, "structured-ssn-count"))->active) {
Expand All @@ -1118,7 +1122,7 @@ int scanmanager(const struct optstruct *opts)
}
}
} else {
options &= ~CL_SCAN_STRUCTURED;
options.heuristic &= ~CL_SCAN_HEURISTIC_STRUCTURED;
}

#ifdef C_LINUX
Expand All @@ -1135,11 +1139,11 @@ int scanmanager(const struct optstruct *opts)
ret = 2;
} else {
CLAMSTAT(cwd, &sb);
scandirs(cwd, engine, opts, options, 1, sb.st_dev);
scandirs(cwd, engine, opts, &options, 1, sb.st_dev);
}

} else if(opts->filename && !optget(opts, "file-list")->enabled && !strcmp(opts->filename[0], "-")) { /* read data from stdin */
ret = scanstdin(engine, opts, options);
ret = scanstdin(engine, opts, &options);
} else {
if(opts->filename && optget(opts, "file-list")->enabled)
logg("^Only scanning files from --file-list (files passed at cmdline are ignored)\n");
Expand All @@ -1163,18 +1167,18 @@ int scanmanager(const struct optstruct *opts)
logg("%s: Symbolic link\n", file);
} else if(CLAMSTAT(file, &sb) != -1) {
if(S_ISREG(sb.st_mode) && filelnk) {
scanfile(file, engine, opts, options);
scanfile(file, engine, opts, &options);
} else if(S_ISDIR(sb.st_mode) && dirlnk) {
scandirs(file, engine, opts, options, 1, sb.st_dev);
scandirs(file, engine, opts, &options, 1, sb.st_dev);
} else {
if(!printinfected)
logg("%s: Symbolic link\n", file);
}
}
} else if(S_ISREG(sb.st_mode)) {
scanfile(file, engine, opts, options);
scanfile(file, engine, opts, &options);
} else if(S_ISDIR(sb.st_mode)) {
scandirs(file, engine, opts, options, 1, sb.st_dev);
scandirs(file, engine, opts, &options, 1, sb.st_dev);
} else {
logg("^%s: Not supported file type\n", file);
ret = 2;
Expand Down
5 changes: 4 additions & 1 deletion contrib/old-clamav-milter/clamav-milter.c
Expand Up @@ -382,7 +382,10 @@ uint32_t maxreclevel;
uint32_t maxfiles;

static struct cl_stat dbstat;
static int options = CL_SCAN_STDOPT;
static struct cl_scan_options options;

memset(&options, 0, sizeof(struct cl_scan_options));
options.parse |= ~0; /* enable all parsers */

#ifdef BOUNCE
static int bflag = 0; /*
Expand Down
131 changes: 88 additions & 43 deletions docs/UserManual/libclamav.md
Expand Up @@ -250,59 +250,104 @@ The first argument points to the database directory, the second one specifies wh
It’s possible to scan a file or descriptor using:

```c
int cl_scanfile(const char *filename, const char **virname,
unsigned long int *scanned, const struct cl_engine *engine,
unsigned int options);
int cl_scanfile(
const char *filename,
const char **virname,
unsigned long int *scanned,
const struct cl_engine *engine,
struct cl_scan_options *options);
int cl_scandesc(
int desc,
const char **virname,
unsigned long int *scanned,
const struct cl_engine *engine,
struct cl_scan_options *options);
```

Both functions will store a virus name under the pointer `virname`, the virus name is part of the engine structure and must not be released directly. If the third argument (`scanned`) is not NULL, the functions will increase its value with the size of scanned data (in `CL_COUNT_PRECISION` units). The last argument (`options`) requires a pointer to a data structure that specifies the scan options. The data structure should be `memset()` Each variable in the structure is a bit-flag field. The structure definition is:

int cl_scandesc(int desc, const char **virname, unsigned
long int *scanned, const struct cl_engine *engine,
unsigned int options);
```c
struct cl_scan_options {
uint32_t general;
uint32_t parse;
uint32_t alert;
uint32_t heuristic_alert;
uint32_t mail;
uint32_t dev;
};
```

Both functions will store a virus name under the pointer `virname`, the virus name is part of the engine structure and must not be released directly. If the third argument (`scanned`) is not NULL, the functions will increase its value with the size of scanned data (in `CL_COUNT_PRECISION` units). The last argument (`options`) specified the scan options and supports the following flags (which can be combined using bit operators):
Supported flags for each of the fields are as follows:

`general` - General scanning options.

- **CL_SCAN_GENERAL_ALLMATCHES**
Scan in all-match mode
- **CL_SCAN_GENERAL_COLLECT_METADATA**
Collect metadata (--gen-json)
- **CL_SCAN_GENERAL_HEURISTICS**
Option to enable heuristic alerts. Required for any of the heuristic alerting options to work.

`parse` - Options to enable/disable specific parsing capabilities. Generally you will want to enable all parsers. The easiest way to do this is to set the parse flags to ~0.

- **CL_SCAN_STDOPT**
This is an alias for a recommended set of scan options. You should use it to make your software ready for new features in the future versions of libclamav.
- **CL_SCAN_RAW**
Use it alone if you want to disable support for special files.
- **CL_SCAN_ARCHIVE**
- **CL_SCAN_PARSE_ARCHIVE**
This flag enables transparent scanning of various archive formats.
- **CL_SCAN_BLOCKENCRYPTED**
With this flag the library will mark encrypted archives as viruses (Encrypted.Zip, Encrypted.RAR).
- **CL_SCAN_MAIL**
Enable support for mail files.
- **CL_SCAN_OLE2**
Enables support for OLE2 containers (used by MS Office and .msi files).
- **CL_SCAN_PDF**
- **CL_SCAN_PARSE_ELF**
Enable support for ELF files.
- **CL_SCAN_PARSE_PDF**
Enables scanning within PDF files.
- **CL_SCAN_SWF**
- **CL_SCAN_PARSE_SWF**
Enables scanning within SWF files, notably compressed SWF.
- **CL_SCAN_PE**
- **CL_SCAN_PARSE_HWP**
Enables scanning of Hangul Word Processor (HWP) files.
- **CL_SCAN_PARSE_XMLDOCS**
Enables scanning of XML-formatted documents (e.g. Word, Excel, Powerpoint, HWP).
- **CL_SCAN_PARSE_MAIL**
Enable support for mail files.
- **CL_SCAN_PARSE_OLE2**
Enables support for OLE2 containers (used by MS Office and .msi files).
- **CL_SCAN_PARSE_HTML**
This flag enables HTML normalisation (including ScrEnc decryption).
- **CL_SCAN_PARSE_PE**
This flag enables deep scanning of Portable Executable files and allows libclamav to unpack executables compressed with run-time unpackers.
- **CL_SCAN_ELF**
Enable support for ELF files.
- **CL_SCAN_BLOCKBROKEN**

`heuristic` - Options to enable specific heuristic alerts

- **CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE**
Allow heuristic match to take precedence. When enabled, if a heuristic scan (such as phishingScan) detects a possible virus/phish it will stop scan immediately. Recommended, saves CPU scan-time. When *disabled*, virus/phish detected by heuristic scans will be reported only at the end of a scan. If an archive contains both a heuristically detected virus/phishing, and a real malware, the real malware will be reported.
- **CL_SCAN_HEURISTIC_ENCRYPTED**
With this flag the library will mark encrypted archives as viruses (Encrypted.Zip, Encrypted.RAR).
- **CL_SCAN_HEURISTIC_BROKEN**
libclamav will try to detect broken executables and mark them as Broken.Executable.
- **CL_SCAN_HTML**
This flag enables HTML normalisation (including ScrEnc decryption).
- **CL_SCAN_ALGORITHMIC**
Enable algorithmic detection of viruses.
- **CL_SCAN_PHISHING_BLOCKSSL**
Phishing module: always block SSL mismatches in URLs.
- **CL_SCAN_PHISHING_BLOCKCLOAK**
- **CL_SCAN_HEURISTIC_EXCEEDS_MAX**
Alert when the scan of any file exceeds maximums such as max filesize, max scansize, max recursion level.
- **CL_SCAN_HEURISTIC_PHISHING_SSL_MISMATCH**
Heuristic for Phishing module: always block SSL mismatches in URLs.
- **CL_SCAN_HEURISTIC_PHISHING_CLOAK**
Phishing module: always block cloaked URLs.
- **CL_SCAN_STRUCTURED**
Enable the DLP module which scans for credit card and SSN numbers.
- **CL_SCAN_STRUCTURED_SSN_NORMAL**
Search for SSNs formatted as xx-yy-zzzz.
- **CL_SCAN_STRUCTURED_SSN_STRIPPED**
Search for SSNs formatted as xxyyzzzz.
- **CL_SCAN_PARTIAL_MESSAGE**
Scan RFC1341 messages split over many emails. You will need to periodically clean up `$TemporaryDirectory/clamav-partial` directory.
- **CL_SCAN_HEURISTIC_PRECEDENCE**
Allow heuristic match to take precedence. When enabled, if a heuristic scan (such as phishingScan) detects a possible virus/phish it will stop scan immediately. Recommended, saves CPU scan-time. When disabled, virus/phish detected by heuristic scans will be reported only at the end of a scan. If an archive contains both a heuristically detected virus/phishing, and a real malware, the real malware will be reported.
- **CL_SCAN_BLOCKMACROS**
- **CL_SCAN_HEURISTIC_MACROS**
OLE2 containers, which contain VBA macros will be marked infected (Heuristics.OLE2.ContainsMacros).
- **CL_SCAN_HEURISTIC_PARTITION_INTXN**
alert if partition table size doesn't make sense
- **CL_SCAN_HEURISTIC_STRUCTURED**
Enable the data loss prevention (DLP) module which scans for credit card and SSN numbers. i.e. alert when detecting personal information
- **CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL**
Search for [and alert when detecting] SSNs formatted as xx-yy-zzzz.
- **CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED**
Search for [and alert when detecting] SSNs formatted as xxyyzzzz.

`mail` - Options to enable specific mail parsing features

- **CL_SCAN_MAIL_PARTIAL_MESSAGE**
Scan RFC1341 messages split over many emails. You will need to periodically clean up `$TemporaryDirectory/clamav-partial` directory.

`dev` - Options designed for use by ClamAV developers

- **CL_SCAN_DEV_COLLECT_SHA**
Enables hash output in sha-collect builds - for internal use only
- **CL_SCAN_DEV_COLLECT_PERFORMANCE_INFO**
Collect performance timings

All functions return `CL_CLEAN` when the file seems clean, `CL_VIRUS` when a virus is detected and another value on failure.

Expand All @@ -311,7 +356,7 @@ All functions return `CL_CLEAN` when the file seems clean, `CL_VIRUS` when a vir
const char *virname;
if((ret = cl_scanfile("/tmp/test.exe", &virname, NULL, engine,
CL_SCAN_STDOPT)) == CL_VIRUS) {
&options)) == CL_VIRUS) {
printf("Virus detected: %s\n", virname);
} else {
printf("No virus detected.\n");
Expand Down
2 changes: 1 addition & 1 deletion etc/clamd.conf.sample
Expand Up @@ -591,7 +591,7 @@ Example

# When BlockMax is set, files exceeding the MaxFileSize, MaxScanSize, or
# MaxRecursion limit will be flagged with the virus
# "Heuristic.Limits.Exceeded".
# "Heuristics.Limits.Exceeded".
# Default: no
#BlockMax yes

Expand Down
7 changes: 6 additions & 1 deletion examples/ex1.c
Expand Up @@ -45,6 +45,7 @@ int main(int argc, char **argv)
long double mb;
const char *virname;
struct cl_engine *engine;
struct cl_scan_options options;

if(argc != 2) {
printf("Usage: %s file\n", argv[0]);
Expand Down Expand Up @@ -85,7 +86,11 @@ int main(int argc, char **argv)
}

/* scan file descriptor */
if((ret = cl_scandesc(fd, &virname, &size, engine, CL_SCAN_STDOPT)) == CL_VIRUS) {
memset(&options, 0, sizeof(struct cl_scan_options));
options.parse |= ~0; /* enable all parsers */
options.general |= CL_SCAN_GENERAL_HEURISTICS; /* enable heuristic alert options */

if((ret = cl_scandesc(fd, &virname, &size, engine, &options)) == CL_VIRUS) {
printf("Virus detected: %s\n", virname);
} else {
if(ret == CL_CLEAN) {
Expand Down
12 changes: 6 additions & 6 deletions libclamav/7z_iface.c
Expand Up @@ -106,7 +106,7 @@ int cli_7unz (cli_ctx *ctx, size_t offset) {

SzArEx_Init(&db);
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
if(res == SZ_ERROR_ENCRYPTED && DETECT_ENCRYPTED) {
if(res == SZ_ERROR_ENCRYPTED && SCAN_HEURISTIC_ENCRYPTED) {
cli_dbgmsg("cli_7unz: Encrypted header found in archive.\n");
found = cli_append_virus(ctx, "Heuristics.Encrypted.7Zip");
} else if(res == SZ_OK) {
Expand Down Expand Up @@ -158,12 +158,12 @@ int cli_7unz (cli_ctx *ctx, size_t offset) {
res = SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp);
if(res == SZ_ERROR_ENCRYPTED) {
encrypted = 1;
if(DETECT_ENCRYPTED) {
if(SCAN_HEURISTIC_ENCRYPTED) {
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_ALL)
if (SCAN_ALLMATCHES)
viruses_found++;
} else
break;
Expand All @@ -173,7 +173,7 @@ int cli_7unz (cli_ctx *ctx, size_t offset) {
if(cli_matchmeta(ctx, name, 0, f->Size, encrypted, i, f->CrcDefined ? f->Crc : 0, NULL)) {
found = CL_VIRUS;
viruses_found++;
if (!SCAN_ALL)
if (!SCAN_ALLMATCHES)
break;
}
if (res != SZ_OK)
Expand All @@ -194,7 +194,7 @@ int cli_7unz (cli_ctx *ctx, size_t offset) {

free(name);
if(found != CL_CLEAN)
if (!(SCAN_ALL && found == CL_VIRUS))
if (!(SCAN_ALLMATCHES && found == CL_VIRUS))
break;
}
}
Expand All @@ -217,7 +217,7 @@ int cli_7unz (cli_ctx *ctx, size_t offset) {
else
cli_dbgmsg("cli_7unz: error %d\n", res);

if (SCAN_ALL && viruses_found)
if (SCAN_ALLMATCHES && viruses_found)
return CL_VIRUS;
return found;
}
8 changes: 4 additions & 4 deletions libclamav/apm.c
Expand Up @@ -133,10 +133,10 @@ int cli_scanapm(cli_ctx *ctx)
}

/* check that the partition table fits in the space specified - HEURISTICS */
if ((ctx->options & CL_SCAN_PARTITION_INTXN) && (ctx->dconf->other & OTHER_CONF_PRTNINTXN)) {
if (SCAN_HEURISTIC_PARTITION_INTXN && (ctx->dconf->other & OTHER_CONF_PRTNINTXN)) {
ret = apm_prtn_intxn(ctx, &aptable, sectorsize, old_school);
if (ret != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
Expand Down Expand Up @@ -226,7 +226,7 @@ int cli_scanapm(cli_ctx *ctx)
/* send the partition to cli_map_scan */
ret = cli_map_scan(*ctx->fmap, partoff, partsize, ctx, CL_TYPE_PART_ANY);
if (ret != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
Expand Down Expand Up @@ -296,7 +296,7 @@ static int apm_prtn_intxn(cli_ctx *ctx, struct apm_partition_info *aptable, size
ret = cli_append_virus(ctx, PRTN_INTXN_DETECTION);
if (ret == CL_VIRUS)
virus_found = 1;
if (SCAN_ALL || ret == CL_CLEAN)
if (SCAN_ALLMATCHES || ret == CL_CLEAN)
tmp = 0;
else
goto leave;
Expand Down
4 changes: 2 additions & 2 deletions libclamav/autoit.c
Expand Up @@ -394,7 +394,7 @@ static int ea05(cli_ctx *ctx, const uint8_t *base, char *tmpd) {
return CL_ESEEK;
}
if(cli_magic_scandesc(i, ctx) == CL_VIRUS) {
if (!SCAN_ALL) {
if (!SCAN_ALLMATCHES) {
close(i);
if(!ctx->engine->keeptmp)
if(cli_unlink(tempfile)) return CL_EUNLINK;
Expand Down Expand Up @@ -921,7 +921,7 @@ static int ea06(cli_ctx *ctx, const uint8_t *base, char *tmpd) {
return CL_ESEEK;
}
if(cli_magic_scandesc(i, ctx) == CL_VIRUS) {
if (!SCAN_ALL) {
if (!SCAN_ALLMATCHES) {
close(i);
if(!ctx->engine->keeptmp)
if (cli_unlink(tempfile)) return CL_EUNLINK;
Expand Down
5 changes: 3 additions & 2 deletions libclamav/blob.c
Expand Up @@ -618,8 +618,9 @@ int
fileblobScan(const fileblob *fb)
{
int rc;
cli_ctx *ctx = fb->ctx;
STATBUF sb;
int virus_found = 0;
int virus_found = 0;

if(fb->isInfected)
return CL_VIRUS;
Expand All @@ -638,7 +639,7 @@ fileblobScan(const fileblob *fb)
lseek(fb->fd, 0, SEEK_SET);
FSTAT(fb->fd, &sb);
if(cli_matchmeta(fb->ctx, fb->b.name, sb.st_size, sb.st_size, 0, 0, 0, NULL) == CL_VIRUS) {
if (!(fb->ctx->options & CL_SCAN_ALLMATCHES))
if (!SCAN_ALLMATCHES)
return CL_VIRUS;
virus_found = 1;
}
Expand Down
8 changes: 4 additions & 4 deletions libclamav/bytecode.c
Expand Up @@ -1834,7 +1834,7 @@ int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, stru

/* need to be called here to catch any extracted but not yet scanned files
*/
if (ctx->outfd && (ret != CL_VIRUS || cctx->options & CL_SCAN_ALLMATCHES))
if (ctx->outfd && (ret != CL_VIRUS || cctx->options->general & CL_SCAN_GENERAL_ALLMATCHES))
cli_bcapi_extract_new(ctx, -1);
}
if (bc->state == bc_jit || test_mode) {
Expand All @@ -1854,7 +1854,7 @@ int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, stru

/* need to be called here to catch any extracted but not yet scanned files
*/
if (ctx->outfd && (ret != CL_VIRUS || cctx->options & CL_SCAN_ALLMATCHES))
if (ctx->outfd && (ret != CL_VIRUS || cctx->options->general & CL_SCAN_GENERAL_ALLMATCHES))
cli_bcapi_extract_new(ctx, -1);
}
cli_event_time_stop(g_sigevents, bc->sigtime_id);
Expand Down Expand Up @@ -2866,7 +2866,7 @@ int cli_bytecode_runhook(cli_ctx *cctx, const struct cl_engine *engine, struct c
if (ctx->virname) {
cli_dbgmsg("Bytecode runhook found virus: %s\n", ctx->virname);
cli_append_virus(cctx, ctx->virname);
if (!(cctx->options & CL_SCAN_ALLMATCHES)) {
if (!(cctx->options->general & CL_SCAN_GENERAL_ALLMATCHES)) {
cli_bytecode_context_clear(ctx);
return CL_VIRUS;
}
Expand Down Expand Up @@ -2906,7 +2906,7 @@ int cli_bytecode_runhook(cli_ctx *cctx, const struct cl_engine *engine, struct c
if (ret != CL_CLEAN) {
if (ret == CL_VIRUS) {
cli_dbgmsg("Scanning unpacked file by bytecode %u found a virus\n", bc->id);
if (cctx->options & CL_SCAN_ALLMATCHES) {
if (cctx->options->general & CL_SCAN_GENERAL_ALLMATCHES) {
cli_bytecode_context_reset(ctx);
continue;
}
Expand Down
193 changes: 192 additions & 1 deletion libclamav/bytecode_api.c
Expand Up @@ -1275,7 +1275,198 @@ uint32_t cli_bcapi_engine_dconf_level(struct cli_bc_ctx *ctx)
uint32_t cli_bcapi_engine_scan_options(struct cli_bc_ctx *ctx)
{
cli_ctx *cctx = (cli_ctx*)ctx->ctx;
return cctx->options;
uint32_t options = CL_SCAN_RAW;

if (cctx->options->general & CL_SCAN_GENERAL_ALLMATCHES)
options |= CL_SCAN_ALLMATCHES;
if (cctx->options->general & CL_SCAN_GENERAL_HEURISTICS)
options |= CL_SCAN_ALGORITHMIC;
if (cctx->options->general & CL_SCAN_GENERAL_COLLECT_METADATA)
options |= CL_SCAN_FILE_PROPERTIES;
if (cctx->options->general & CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE)
options |= CL_SCAN_HEURISTIC_PRECEDENCE;

if (cctx->options->parse & CL_SCAN_PARSE_ARCHIVE)
options |= CL_SCAN_ARCHIVE;
if (cctx->options->parse & CL_SCAN_PARSE_ELF)
options |= CL_SCAN_ELF;
if (cctx->options->parse & CL_SCAN_PARSE_PDF)
options |= CL_SCAN_PDF;
if (cctx->options->parse & CL_SCAN_PARSE_SWF)
options |= CL_SCAN_SWF;
if (cctx->options->parse & CL_SCAN_PARSE_HWP3)
options |= CL_SCAN_HWP3;
if (cctx->options->parse & CL_SCAN_PARSE_XMLDOCS)
options |= CL_SCAN_XMLDOCS;
if (cctx->options->parse & CL_SCAN_PARSE_MAIL)
options |= CL_SCAN_MAIL;
if (cctx->options->parse & CL_SCAN_PARSE_OLE2)
options |= CL_SCAN_OLE2;
if (cctx->options->parse & CL_SCAN_PARSE_HTML)
options |= CL_SCAN_HTML;
if (cctx->options->parse & CL_SCAN_PARSE_PE)
options |= CL_SCAN_PE;
// if (cctx->options->parse & CL_SCAN_MAIL_URL)
// options |= CL_SCAN_MAILURL; /* deprecated circa 2009 */

if (cctx->options->heuristic & CL_SCAN_HEURISTIC_BROKEN)
options |= CL_SCAN_BLOCKBROKEN;
if (cctx->options->heuristic & CL_SCAN_HEURISTIC_EXCEEDS_MAX)
options |= CL_SCAN_BLOCKMAX;
if (cctx->options->heuristic & CL_SCAN_HEURISTIC_PHISHING_SSL_MISMATCH)
options |= CL_SCAN_PHISHING_BLOCKSSL;
if (cctx->options->heuristic & CL_SCAN_HEURISTIC_PHISHING_CLOAK)
options |= CL_SCAN_PHISHING_BLOCKCLOAK;
if (cctx->options->heuristic & CL_SCAN_HEURISTIC_MACROS)
options |= CL_SCAN_BLOCKMACROS;
if (cctx->options->heuristic & CL_SCAN_HEURISTIC_ENCRYPTED)
options |= CL_SCAN_BLOCKENCRYPTED;
if (cctx->options->heuristic & CL_SCAN_HEURISTIC_PARTITION_INTXN)
options |= CL_SCAN_PARTITION_INTXN;
if (cctx->options->heuristic & CL_SCAN_HEURISTIC_STRUCTURED)
options |= CL_SCAN_STRUCTURED;
if (cctx->options->heuristic & CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL)
options |= CL_SCAN_STRUCTURED_SSN_NORMAL;
if (cctx->options->heuristic & CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED)
options |= CL_SCAN_STRUCTURED_SSN_STRIPPED;

if (cctx->options->mail & CL_SCAN_MAIL_PARTIAL_MESSAGE)
options |= CL_SCAN_PARTIAL_MESSAGE;

if (cctx->options->dev & CL_SCAN_DEV_COLLECT_SHA)
options |= CL_SCAN_INTERNAL_COLLECT_SHA;
if (cctx->options->dev & CL_SCAN_DEV_COLLECT_PERFORMANCE_INFO)
options |= CL_SCAN_PERFORMANCE_INFO;

return options;
}

uint32_t cli_bcapi_engine_scan_options_ex(struct cli_bc_ctx *ctx, const uint8_t *option_name, uint32_t name_len)
{
uint32_t i = 0;
char *option_name_l = NULL;

if (ctx == NULL || option_name == NULL || name_len == 0) {
cli_warnmsg("engine_scan_options_ex: Invalid arguments!");
return 0;
}

cli_ctx *cctx = (cli_ctx*)ctx->ctx;
if (cctx == NULL || cctx->options == NULL) {
cli_warnmsg("engine_scan_options_ex: Invalid arguments!");
return 0;
}

option_name_l = malloc(name_len + 1);
for (i = 0; i < name_len; i++) {
option_name_l[0] = tolower(option_name[i]);
}
option_name_l[name_len] = '\0';

if (strncmp(option_name_l, "general", MIN(name_len, sizeof("general")))) {
if (cli_memstr(option_name_l, name_len, "allmatch", sizeof("allmatch"))) {
return (cctx->options->general & CL_SCAN_GENERAL_ALLMATCHES) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "collect metadata", sizeof("collect metadata"))) {
return (cctx->options->general & CL_SCAN_GENERAL_COLLECT_METADATA) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "heuristics", sizeof("heuristics"))) {
return (cctx->options->general & CL_SCAN_GENERAL_HEURISTICS) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "precedence", sizeof("precedence"))) {
return (cctx->options->general & CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE) ? 1 : 0;
}
/* else unknown option */
return 0;
}
else if (strncmp(option_name_l, "parse", MIN(name_len, sizeof("parse")))) {
if (cli_memstr(option_name_l, name_len, "archive", sizeof("archive"))) {
return (cctx->options->parse & CL_SCAN_PARSE_ARCHIVE) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "elf", sizeof("elf"))) {
return (cctx->options->parse & CL_SCAN_PARSE_ELF) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "pdf", sizeof("pdf"))) {
return (cctx->options->parse & CL_SCAN_PARSE_PDF) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "swf", sizeof("swf"))) {
return (cctx->options->parse & CL_SCAN_PARSE_SWF) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "hwp3", sizeof("hwp3"))) {
return (cctx->options->parse & CL_SCAN_PARSE_HWP3) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "xmldocs", sizeof("xmldocs"))) {
return (cctx->options->parse & CL_SCAN_PARSE_XMLDOCS) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "mail", sizeof("mail"))) {
return (cctx->options->parse & CL_SCAN_PARSE_MAIL) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "ole2", sizeof("ole2"))) {
return (cctx->options->parse & CL_SCAN_PARSE_OLE2) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "html", sizeof("html"))) {
return (cctx->options->parse & CL_SCAN_PARSE_HTML) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "pe", sizeof("pe"))) {
return (cctx->options->parse & CL_SCAN_PARSE_PE) ? 1 : 0;
}
/* else unknown option */
return 0;
}
else if (strncmp(option_name_l, "heuristic", MIN(name_len, sizeof("heuristic")))) {
if (cli_memstr(option_name_l, name_len, "broken", sizeof("broken"))) {
return (cctx->options->heuristic & CL_SCAN_HEURISTIC_BROKEN) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "exceeds max", sizeof("exceeds max"))) {
return (cctx->options->heuristic & CL_SCAN_HEURISTIC_EXCEEDS_MAX) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "phishing ssl mismatch", sizeof("phishing ssl mismatch"))) {
return (cctx->options->heuristic & CL_SCAN_HEURISTIC_PHISHING_SSL_MISMATCH) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "phishing cloak", sizeof("phishing cloak"))) {
return (cctx->options->heuristic & CL_SCAN_HEURISTIC_PHISHING_CLOAK) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "macros", sizeof("macros"))) {
return (cctx->options->heuristic & CL_SCAN_HEURISTIC_MACROS) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "encrypted", sizeof("encrypted"))) {
return (cctx->options->heuristic & CL_SCAN_HEURISTIC_ENCRYPTED) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "partition intxn", sizeof("partition intxn"))) {
return (cctx->options->heuristic & CL_SCAN_HEURISTIC_PARTITION_INTXN) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "structured", sizeof("structured"))) {
return (cctx->options->heuristic & CL_SCAN_HEURISTIC_STRUCTURED) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "structured ssn normal", sizeof("structured ssn normal"))) {
return (cctx->options->heuristic & CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "structured ssn stripped", sizeof("structured ssn stripped"))) {
return (cctx->options->heuristic & CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED) ? 1 : 0;
}
/* else unknown option */
return 0;
}
else if (strncmp(option_name_l, "mail", MIN(name_len, sizeof("mail")))) {
if (cli_memstr(option_name_l, name_len, "partial message", sizeof("partial message"))) {
return (cctx->options->mail & CL_SCAN_MAIL_PARTIAL_MESSAGE) ? 1 : 0;
}
/* else unknown option */
return 0;
}
else if (strncmp(option_name_l, "dev", MIN(name_len, sizeof("dev")))) {
if (cli_memstr(option_name_l, name_len, "collect sha", sizeof("collect sha"))) {
return (cctx->options->dev & CL_SCAN_DEV_COLLECT_SHA) ? 1 : 0;
}
if (cli_memstr(option_name_l, name_len, "collect performance info", sizeof("collect performance info"))) {
return (cctx->options->dev & CL_SCAN_DEV_COLLECT_PERFORMANCE_INFO) ? 1 : 0;
}
/* else unknown option */
return 0;
} else {
/* else unknown option */
return 0;
}
}

uint32_t cli_bcapi_engine_db_options(struct cli_bc_ctx *ctx)
Expand Down
87 changes: 85 additions & 2 deletions libclamav/bytecode_api.h
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2014-2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2009-2013 Sourcefire, Inc.
* All rights reserved.
* Authors: Török Edvin, Kevin Lin
Expand Down Expand Up @@ -203,6 +203,45 @@ enum bc_json_type {
JSON_TYPE_STRING /* */
};

/**
\group_engine
* Scan option flag values for engine_scan_options(). *DEPRECATED*
*/
#define CL_SCAN_RAW 0x0
#define CL_SCAN_ARCHIVE 0x1
#define CL_SCAN_MAIL 0x2
#define CL_SCAN_OLE2 0x4
#define CL_SCAN_BLOCKENCRYPTED 0x8
#define CL_SCAN_HTML 0x10
#define CL_SCAN_PE 0x20
#define CL_SCAN_BLOCKBROKEN 0x40
#define CL_SCAN_MAILURL 0x80 /* deprecated circa 2009 */
#define CL_SCAN_BLOCKMAX 0x100
#define CL_SCAN_ALGORITHMIC 0x200
//#define UNUSED 0x400
#define CL_SCAN_PHISHING_BLOCKSSL 0x800 /* ssl mismatches, not ssl by itself*/
#define CL_SCAN_PHISHING_BLOCKCLOAK 0x1000
#define CL_SCAN_ELF 0x2000
#define CL_SCAN_PDF 0x4000
#define CL_SCAN_STRUCTURED 0x8000
#define CL_SCAN_STRUCTURED_SSN_NORMAL 0x10000
#define CL_SCAN_STRUCTURED_SSN_STRIPPED 0x20000
#define CL_SCAN_PARTIAL_MESSAGE 0x40000
#define CL_SCAN_HEURISTIC_PRECEDENCE 0x80000
#define CL_SCAN_BLOCKMACROS 0x100000
#define CL_SCAN_ALLMATCHES 0x200000
#define CL_SCAN_SWF 0x400000
#define CL_SCAN_PARTITION_INTXN 0x800000
#define CL_SCAN_XMLDOCS 0x1000000
#define CL_SCAN_HWP3 0x2000000
//#define UNUSED 0x4000000
//#define UNUSED 0x8000000
#define CL_SCAN_FILE_PROPERTIES 0x10000000
//#define UNUSED 0x20000000
#define CL_SCAN_PERFORMANCE_INFO 0x40000000 /* Collect performance timings */
#define CL_SCAN_INTERNAL_COLLECT_SHA 0x80000000 /* Enables hash output in sha-collect builds - for internal use only */


#ifdef __CLAMBC__

/* --------------- BEGIN GLOBALS -------------------------------------------- */
Expand Down Expand Up @@ -885,7 +924,7 @@ uint32_t engine_dconf_level(void);

/**
\group_engine
* Returns the current engine's scan options.
* Returns the current engine's scan options. **DEPRECATED**
* @return CL_SCAN* flags
*/
uint32_t engine_scan_options(void);
Expand Down Expand Up @@ -1222,5 +1261,49 @@ int32_t json_get_int(int32_t objid);
//double json_get_double(int32_t objid);

/* ----------------- END 0.98.4 APIs ---------------------------------- */
/* ----------------- BEGIN 0.100.0 APIs ------------------------------- */
/* ----------------- Scan Options APIs -------------------------------- */
/**
\group_engine
* Check if any given scan option is enabled.
* Returns non-zero if the following named options are set:
*
* "general allmatch" - all-match mode is enabled
* "general collect metadata" - --gen-json is enabled
* "general heuristics" - --gen-json is enabled
*
* "parse archive" - archive parsing is enabled
* "parse pdf" - pdf parsing is enabled
* "parse swf" - swf parsing is enabled
* "parse hwp3" - hwp3 parsing is enabled
* "parse xmldocs" - xmldocs parsing is enabled
* "parse mail" - mail parsing is enabled
* "parse ole2" - ole2 parsing is enabled
* "parse html" - html parsing is enabled
* "parse pe" - pe parsing is enabled
*
* "heuristic precedence" - heuristic signatures are set to take precedence
* "heuristic broken" - broken pe heuristic is enabled
* "heuristic exceeds max" - heuristic for when max settings are exceeded is enabled
* "heuristic phishing ssl mismatch" - phishing ssl mismatch heuristic is enabled
* "heuristic phishing cloak" - phishing cloak heuristic is enabled
* "heuristic macros" - macros heuristic is enabled
* "heuristic encrypted" - encrypted heuristic is enabled
* "heuristic partition intxn" - macpartition intxnros heuristic is enabled
* "heuristic structured" - structured heuristic is enabled
* "heuristic structured ssn normal" - structured ssn normal heuristic is enabled
* "heuristic structured ssn stripped" - structured ssn stripped heuristic is enabled
*
* "mail partial message" - parsing of partial mail messages is enabled
*
* "dev collect sha" - --dev-collect-hashes is enabled
* "dev collect performance info" - --dev-performance is enabled
*
* @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);

/* ----------------- END 0.101 APIs ---------------------------------- */
#endif
#endif
249 changes: 126 additions & 123 deletions libclamav/bytecode_api_decl.c
Expand Up @@ -2,7 +2,7 @@
* ClamAV bytecode internal API
* This is an automatically generated file!
*
* Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2014-2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2009-2013 Sourcefire, Inc.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -133,6 +133,7 @@ int32_t cli_bcapi_json_get_string_length(struct cli_bc_ctx *ctx , int32_t);
int32_t cli_bcapi_json_get_string(struct cli_bc_ctx *ctx , int8_t*, int32_t, int32_t);
int32_t cli_bcapi_json_get_boolean(struct cli_bc_ctx *ctx , int32_t);
int32_t cli_bcapi_json_get_int(struct cli_bc_ctx *ctx , int32_t);
uint32_t cli_bcapi_engine_scan_options_ex(struct cli_bc_ctx *ctx , const uint8_t*, uint32_t);

const struct cli_apiglobal cli_globals[] = {
/* Bytecode globals BEGIN */
Expand All @@ -157,18 +158,18 @@ static uint16_t cli_tmp4[]={16, 8, 8, 32, 32, 32, 32, 32, 32, 32, 32, 32, 16, 16
static uint16_t cli_tmp5[]={32, 16, 16, 32, 32, 32, 16, 16};
static uint16_t cli_tmp6[]={32};
static uint16_t cli_tmp7[]={32};
static uint16_t cli_tmp8[]={32, 32};
static uint16_t cli_tmp9[]={32, 65, 32, 32};
static uint16_t cli_tmp10[]={32, 32, 32};
static uint16_t cli_tmp11[]={32};
static uint16_t cli_tmp12[]={32, 65, 32, 65, 32};
static uint16_t cli_tmp13[]={65, 32, 32};
static uint16_t cli_tmp14[]={32, 32, 32, 32};
static uint16_t cli_tmp15[]={32, 85, 32};
static uint16_t cli_tmp16[]={86};
static uint16_t cli_tmp17[]={32, 32, 32, 32, 32, 32, 32, 87, 87, 87, 87, 87, 87, 87, 8, 8, 8, 8, 8, 8, 8, 8, 8};
static uint16_t cli_tmp18[]={8};
static uint16_t cli_tmp19[]={32, 65, 32};
static uint16_t cli_tmp8[]={32, 65, 32};
static uint16_t cli_tmp9[]={32, 32};
static uint16_t cli_tmp10[]={32, 65, 32, 32};
static uint16_t cli_tmp11[]={32, 32, 32};
static uint16_t cli_tmp12[]={32};
static uint16_t cli_tmp13[]={32, 65, 32, 65, 32};
static uint16_t cli_tmp14[]={65, 32, 32};
static uint16_t cli_tmp15[]={32, 32, 32, 32};
static uint16_t cli_tmp16[]={32, 86, 32};
static uint16_t cli_tmp17[]={87};
static uint16_t cli_tmp18[]={32, 32, 32, 32, 32, 32, 32, 88, 88, 88, 88, 88, 88, 88, 8, 8, 8, 8, 8, 8, 8, 8, 8};
static uint16_t cli_tmp19[]={8};
static uint16_t cli_tmp20[]={32, 65, 32, 32, 32, 32};
static uint16_t cli_tmp21[]={32, 91, 32};
static uint16_t cli_tmp22[]={92};
Expand All @@ -190,18 +191,18 @@ const struct cli_bc_type cli_apicall_types[]={
{DStructType, cli_tmp5, 8, 0, 0},
{DArrayType, cli_tmp6, 1, 0, 0},
{DArrayType, cli_tmp7, 64, 0, 0},
{DFunctionType, cli_tmp8, 2, 0, 0},
{DFunctionType, cli_tmp9, 4, 0, 0},
{DFunctionType, cli_tmp10, 3, 0, 0},
{DFunctionType, cli_tmp11, 1, 0, 0},
{DFunctionType, cli_tmp12, 5, 0, 0},
{DFunctionType, cli_tmp13, 3, 0, 0},
{DFunctionType, cli_tmp14, 4, 0, 0},
{DFunctionType, cli_tmp15, 3, 0, 0},
{DPointerType, cli_tmp16, 1, 0, 0},
{DStructType, cli_tmp17, 23, 0, 0},
{DArrayType, cli_tmp18, 65, 0, 0},
{DFunctionType, cli_tmp19, 3, 0, 0},
{DFunctionType, cli_tmp8, 3, 0, 0},
{DFunctionType, cli_tmp9, 2, 0, 0},
{DFunctionType, cli_tmp10, 4, 0, 0},
{DFunctionType, cli_tmp11, 3, 0, 0},
{DFunctionType, cli_tmp12, 1, 0, 0},
{DFunctionType, cli_tmp13, 5, 0, 0},
{DFunctionType, cli_tmp14, 3, 0, 0},
{DFunctionType, cli_tmp15, 4, 0, 0},
{DFunctionType, cli_tmp16, 3, 0, 0},
{DPointerType, cli_tmp17, 1, 0, 0},
{DStructType, cli_tmp18, 23, 0, 0},
{DArrayType, cli_tmp19, 65, 0, 0},
{DFunctionType, cli_tmp20, 6, 0, 0},
{DFunctionType, cli_tmp21, 3, 0, 0},
{DPointerType, cli_tmp22, 1, 0, 0},
Expand All @@ -214,110 +215,111 @@ const struct cli_bc_type cli_apicall_types[]={
{DArrayType, cli_tmp29, 3, 0, 0},
{DArrayType, cli_tmp30, 10, 0, 0}
};
const unsigned cli_apicall_maxtypes=sizeof(cli_apicall_types)/sizeof(cli_apicall_types[0]);

const unsigned cli_apicall_maxtypes=sizeof(cli_apicall_types)/sizeof(cli_apicall_types[0]);
const struct cli_apicall cli_apicalls[]={
/* Bytecode APIcalls BEGIN */
{"test1", 10, 0, 0},
{"read", 19, 0, 1},
{"write", 19, 1, 1},
{"seek", 10, 1, 0},
{"setvirusname", 19, 2, 1},
{"debug_print_str", 19, 3, 1},
{"debug_print_uint", 8, 0, 2},
{"test1", 11, 0, 0},
{"read", 8, 0, 1},
{"write", 8, 1, 1},
{"seek", 11, 1, 0},
{"setvirusname", 8, 2, 1},
{"debug_print_str", 8, 3, 1},
{"debug_print_uint", 9, 0, 2},
{"disasm_x86", 25, 4, 1},
{"trace_directory", 19, 5, 1},
{"trace_scope", 19, 6, 1},
{"trace_source", 19, 7, 1},
{"trace_op", 19, 8, 1},
{"trace_value", 19, 9, 1},
{"trace_ptr", 19, 10, 1},
{"pe_rawaddr", 8, 1, 2},
{"file_find", 19, 11, 1},
{"file_byteat", 8, 2, 2},
{"trace_directory", 8, 5, 1},
{"trace_scope", 8, 6, 1},
{"trace_source", 8, 7, 1},
{"trace_op", 8, 8, 1},
{"trace_value", 8, 9, 1},
{"trace_ptr", 8, 10, 1},
{"pe_rawaddr", 9, 1, 2},
{"file_find", 8, 11, 1},
{"file_byteat", 9, 2, 2},
{"malloc", 24, 0, 3},
{"test2", 8, 3, 2},
{"test2", 9, 3, 2},
{"get_pe_section", 21, 12, 1},
{"fill_buffer", 20, 0, 4},
{"extract_new", 8, 4, 2},
{"read_number", 8, 5, 2},
{"hashset_new", 11, 0, 5},
{"hashset_add", 10, 2, 0},
{"hashset_remove", 10, 3, 0},
{"hashset_contains", 10, 4, 0},
{"hashset_done", 8, 6, 2},
{"hashset_empty", 8, 7, 2},
{"buffer_pipe_new", 8, 8, 2},
{"buffer_pipe_new_fromfile", 8, 9, 2},
{"buffer_pipe_read_avail", 8, 10, 2},
{"buffer_pipe_read_get", 13, 0, 6},
{"buffer_pipe_read_stopped", 10, 5, 0},
{"buffer_pipe_write_avail", 8, 11, 2},
{"buffer_pipe_write_get", 13, 1, 6},
{"buffer_pipe_write_stopped", 10, 6, 0},
{"buffer_pipe_done", 8, 12, 2},
{"inflate_init", 14, 0, 7},
{"inflate_process", 8, 13, 2},
{"inflate_done", 8, 14, 2},
{"bytecode_rt_error", 8, 15, 2},
{"jsnorm_init", 8, 16, 2},
{"jsnorm_process", 8, 17, 2},
{"jsnorm_done", 8, 18, 2},
{"ilog2", 10, 7, 0},
{"ipow", 14, 1, 7},
{"iexp", 14, 2, 7},
{"isin", 14, 3, 7},
{"icos", 14, 4, 7},
{"memstr", 12, 0, 8},
{"hex2ui", 10, 8, 0},
{"atoi", 19, 13, 1},
{"debug_print_str_start", 19, 14, 1},
{"debug_print_str_nonl", 19, 15, 1},
{"entropy_buffer", 19, 16, 1},
{"map_new", 10, 9, 0},
{"map_addkey", 9, 0, 9},
{"map_setvalue", 9, 1, 9},
{"map_remove", 9, 2, 9},
{"map_find", 9, 3, 9},
{"map_getvaluesize", 8, 19, 2},
{"map_getvalue", 13, 2, 6},
{"map_done", 8, 20, 2},
{"file_find_limit", 9, 4, 9},
{"engine_functionality_level", 11, 1, 5},
{"engine_dconf_level", 11, 2, 5},
{"engine_scan_options", 11, 3, 5},
{"engine_db_options", 11, 4, 5},
{"extract_set_container", 8, 21, 2},
{"input_switch", 8, 22, 2},
{"get_environment", 15, 17, 1},
{"disable_bytecode_if", 9, 5, 9},
{"disable_jit_if", 9, 6, 9},
{"version_compare", 12, 1, 8},
{"check_platform", 14, 5, 7},
{"pdf_get_obj_num", 11, 5, 5},
{"pdf_get_flags", 11, 6, 5},
{"pdf_set_flags", 8, 23, 2},
{"pdf_lookupobj", 8, 24, 2},
{"pdf_getobjsize", 8, 25, 2},
{"pdf_getobj", 13, 3, 6},
{"pdf_getobjid", 8, 26, 2},
{"pdf_getobjflags", 8, 27, 2},
{"pdf_setobjflags", 10, 10, 0},
{"pdf_get_offset", 8, 28, 2},
{"pdf_get_phase", 11, 7, 5},
{"pdf_get_dumpedobjid", 11, 8, 5},
{"matchicon", 12, 2, 8},
{"running_on_jit", 11, 9, 5},
{"get_file_reliability", 11, 10, 5},
{"json_is_active", 11, 11, 5},
{"json_get_object", 9, 7, 9},
{"json_get_type", 8, 29, 2},
{"json_get_array_length", 8, 30, 2},
{"json_get_array_idx", 10, 11, 0},
{"json_get_string_length", 8, 31, 2},
{"json_get_string", 9, 8, 9},
{"json_get_boolean", 8, 32, 2},
{"json_get_int", 8, 33, 2}
{"extract_new", 9, 4, 2},
{"read_number", 9, 5, 2},
{"hashset_new", 12, 0, 5},
{"hashset_add", 11, 2, 0},
{"hashset_remove", 11, 3, 0},
{"hashset_contains", 11, 4, 0},
{"hashset_done", 9, 6, 2},
{"hashset_empty", 9, 7, 2},
{"buffer_pipe_new", 9, 8, 2},
{"buffer_pipe_new_fromfile", 9, 9, 2},
{"buffer_pipe_read_avail", 9, 10, 2},
{"buffer_pipe_read_get", 14, 0, 6},
{"buffer_pipe_read_stopped", 11, 5, 0},
{"buffer_pipe_write_avail", 9, 11, 2},
{"buffer_pipe_write_get", 14, 1, 6},
{"buffer_pipe_write_stopped", 11, 6, 0},
{"buffer_pipe_done", 9, 12, 2},
{"inflate_init", 15, 0, 7},
{"inflate_process", 9, 13, 2},
{"inflate_done", 9, 14, 2},
{"bytecode_rt_error", 9, 15, 2},
{"jsnorm_init", 9, 16, 2},
{"jsnorm_process", 9, 17, 2},
{"jsnorm_done", 9, 18, 2},
{"ilog2", 11, 7, 0},
{"ipow", 15, 1, 7},
{"iexp", 15, 2, 7},
{"isin", 15, 3, 7},
{"icos", 15, 4, 7},
{"memstr", 13, 0, 8},
{"hex2ui", 11, 8, 0},
{"atoi", 8, 13, 1},
{"debug_print_str_start", 8, 14, 1},
{"debug_print_str_nonl", 8, 15, 1},
{"entropy_buffer", 8, 16, 1},
{"map_new", 11, 9, 0},
{"map_addkey", 10, 0, 9},
{"map_setvalue", 10, 1, 9},
{"map_remove", 10, 2, 9},
{"map_find", 10, 3, 9},
{"map_getvaluesize", 9, 19, 2},
{"map_getvalue", 14, 2, 6},
{"map_done", 9, 20, 2},
{"file_find_limit", 10, 4, 9},
{"engine_functionality_level", 12, 1, 5},
{"engine_dconf_level", 12, 2, 5},
{"engine_scan_options", 12, 3, 5},
{"engine_db_options", 12, 4, 5},
{"extract_set_container", 9, 21, 2},
{"input_switch", 9, 22, 2},
{"get_environment", 16, 17, 1},
{"disable_bytecode_if", 10, 5, 9},
{"disable_jit_if", 10, 6, 9},
{"version_compare", 13, 1, 8},
{"check_platform", 15, 5, 7},
{"pdf_get_obj_num", 12, 5, 5},
{"pdf_get_flags", 12, 6, 5},
{"pdf_set_flags", 9, 23, 2},
{"pdf_lookupobj", 9, 24, 2},
{"pdf_getobjsize", 9, 25, 2},
{"pdf_getobj", 14, 3, 6},
{"pdf_getobjid", 9, 26, 2},
{"pdf_getobjflags", 9, 27, 2},
{"pdf_setobjflags", 11, 10, 0},
{"pdf_get_offset", 9, 28, 2},
{"pdf_get_phase", 12, 7, 5},
{"pdf_get_dumpedobjid", 12, 8, 5},
{"matchicon", 13, 2, 8},
{"running_on_jit", 12, 9, 5},
{"get_file_reliability", 12, 10, 5},
{"json_is_active", 12, 11, 5},
{"json_get_object", 10, 7, 9},
{"json_get_type", 9, 29, 2},
{"json_get_array_length", 9, 30, 2},
{"json_get_array_idx", 11, 11, 0},
{"json_get_string_length", 9, 31, 2},
{"json_get_string", 10, 8, 9},
{"json_get_boolean", 9, 32, 2},
{"json_get_int", 9, 33, 2},
{"engine_scan_options_ex", 8, 18, 1}
/* Bytecode APIcalls END */
};
const unsigned cli_numapicalls=sizeof(cli_apicalls)/sizeof(cli_apicalls[0]);
Expand Down Expand Up @@ -354,7 +356,8 @@ const cli_apicall_pointer cli_apicalls1[] = {
(cli_apicall_pointer)cli_bcapi_debug_print_str_start,
(cli_apicall_pointer)cli_bcapi_debug_print_str_nonl,
(cli_apicall_pointer)cli_bcapi_entropy_buffer,
(cli_apicall_pointer)cli_bcapi_get_environment
(cli_apicall_pointer)cli_bcapi_get_environment,
(cli_apicall_pointer)cli_bcapi_engine_scan_options_ex
};
const cli_apicall_int1 cli_apicalls2[] = {
(cli_apicall_int1)cli_bcapi_debug_print_uint,
Expand Down
3 changes: 2 additions & 1 deletion libclamav/bytecode_api_impl.h
Expand Up @@ -2,7 +2,7 @@
* ClamAV bytecode internal API
* This is an automatically generated file!
*
* Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2014-2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2009-2013 Sourcefire, Inc.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -131,5 +131,6 @@ int32_t cli_bcapi_json_get_string_length(struct cli_bc_ctx *ctx , int32_t);
int32_t cli_bcapi_json_get_string(struct cli_bc_ctx *ctx , int8_t*, int32_t, int32_t);
int32_t cli_bcapi_json_get_boolean(struct cli_bc_ctx *ctx , int32_t);
int32_t cli_bcapi_json_get_int(struct cli_bc_ctx *ctx , int32_t);
uint32_t cli_bcapi_engine_scan_options_ex(struct cli_bc_ctx *ctx , const uint8_t*, uint32_t);

#endif
2 changes: 1 addition & 1 deletion libclamav/bytecode_hooks.h
Expand Up @@ -2,7 +2,7 @@
* ClamAV bytecode internal API
* This is an automatically generated file!
*
* Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2014-2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2009-2013 Sourcefire, Inc.
*
* Redistribution and use in source and binary forms, with or without
Expand Down
2 changes: 1 addition & 1 deletion libclamav/cache.c
Expand Up @@ -833,7 +833,7 @@ void cache_add(unsigned char *md5, size_t size, cli_ctx *ctx) {
level = (*ctx->fmap && (*ctx->fmap)->dont_cache_flag) ? ctx->recursion : 0;
if (ctx->found_possibly_unwanted && (level || !ctx->recursion))
return;
if (SCAN_ALL && (ctx->num_viruses > 0)) {
if (SCAN_ALLMATCHES && (ctx->num_viruses > 0)) {
cli_dbgmsg("cache_add: alert found within same topfile, skipping cache\n");
return;
}
Expand Down
135 changes: 74 additions & 61 deletions libclamav/clamav.h
Expand Up @@ -65,6 +65,8 @@
#include <sys/types.h>
#include <sys/stat.h>

#include "cltypes.h"

#ifdef __cplusplus
extern "C"
{
Expand Down Expand Up @@ -121,64 +123,75 @@ typedef enum cl_error_t {
} cl_error_t;

/* db options */
#define CL_DB_PHISHING 0x2
#define CL_DB_PHISHING_URLS 0x8
#define CL_DB_PUA 0x10
#define CL_DB_CVDNOTMP 0x20 /* obsolete */
#define CL_DB_OFFICIAL 0x40 /* internal */
#define CL_DB_PUA_MODE 0x80
#define CL_DB_PUA_INCLUDE 0x100
#define CL_DB_PUA_EXCLUDE 0x200
#define CL_DB_COMPILED 0x400 /* internal */
#define CL_DB_DIRECTORY 0x800 /* internal */
#define CL_DB_OFFICIAL_ONLY 0x1000
#define CL_DB_BYTECODE 0x2000
#define CL_DB_SIGNED 0x4000 /* internal */
#define CL_DB_BYTECODE_UNSIGNED 0x8000
#define CL_DB_UNSIGNED 0x10000 /* internal */
#define CL_DB_BYTECODE_STATS 0x20000
#define CL_DB_ENHANCED 0x40000
#define CL_DB_PCRE_STATS 0x80000
#define CL_DB_YARA_EXCLUDE 0x100000
#define CL_DB_YARA_ONLY 0x200000
#define CL_DB_PHISHING 0x2
#define CL_DB_PHISHING_URLS 0x8
#define CL_DB_PUA 0x10
#define CL_DB_CVDNOTMP 0x20 /* obsolete */
#define CL_DB_OFFICIAL 0x40 /* internal */
#define CL_DB_PUA_MODE 0x80
#define CL_DB_PUA_INCLUDE 0x100
#define CL_DB_PUA_EXCLUDE 0x200
#define CL_DB_COMPILED 0x400 /* internal */
#define CL_DB_DIRECTORY 0x800 /* internal */
#define CL_DB_OFFICIAL_ONLY 0x1000
#define CL_DB_BYTECODE 0x2000
#define CL_DB_SIGNED 0x4000 /* internal */
#define CL_DB_BYTECODE_UNSIGNED 0x8000
#define CL_DB_UNSIGNED 0x10000 /* internal */
#define CL_DB_BYTECODE_STATS 0x20000
#define CL_DB_ENHANCED 0x40000
#define CL_DB_PCRE_STATS 0x80000
#define CL_DB_YARA_EXCLUDE 0x100000
#define CL_DB_YARA_ONLY 0x200000

/* recommended db settings */
#define CL_DB_STDOPT (CL_DB_PHISHING | CL_DB_PHISHING_URLS | CL_DB_BYTECODE)

/* scan options */
#define CL_SCAN_RAW 0x0
#define CL_SCAN_ARCHIVE 0x1
#define CL_SCAN_MAIL 0x2
#define CL_SCAN_OLE2 0x4
#define CL_SCAN_BLOCKENCRYPTED 0x8
#define CL_SCAN_HTML 0x10
#define CL_SCAN_PE 0x20
#define CL_SCAN_BLOCKBROKEN 0x40
#define CL_SCAN_MAILURL 0x80 /* ignored */
#define CL_SCAN_BLOCKMAX 0x100
#define CL_SCAN_ALGORITHMIC 0x200
#define CL_SCAN_PHISHING_BLOCKSSL 0x800 /* ssl mismatches, not ssl by itself*/
#define CL_SCAN_PHISHING_BLOCKCLOAK 0x1000
#define CL_SCAN_ELF 0x2000
#define CL_SCAN_PDF 0x4000
#define CL_SCAN_STRUCTURED 0x8000
#define CL_SCAN_STRUCTURED_SSN_NORMAL 0x10000
#define CL_SCAN_STRUCTURED_SSN_STRIPPED 0x20000
#define CL_SCAN_PARTIAL_MESSAGE 0x40000
#define CL_SCAN_HEURISTIC_PRECEDENCE 0x80000
#define CL_SCAN_BLOCKMACROS 0x100000
#define CL_SCAN_ALLMATCHES 0x200000
#define CL_SCAN_SWF 0x400000
#define CL_SCAN_PARTITION_INTXN 0x800000
#define CL_SCAN_XMLDOCS 0x1000000
#define CL_SCAN_HWP3 0x2000000
#define CL_SCAN_FILE_PROPERTIES 0x10000000
//#define UNUSED 0x20000000
#define CL_SCAN_PERFORMANCE_INFO 0x40000000 /* collect performance timings */
#define CL_SCAN_INTERNAL_COLLECT_SHA 0x80000000 /* Enables hash output in sha-collect builds - for internal use only */

/* recommended scan settings */
#define CL_SCAN_STDOPT (CL_SCAN_ARCHIVE | CL_SCAN_MAIL | CL_SCAN_OLE2 | CL_SCAN_PDF | CL_SCAN_HTML | CL_SCAN_PE | CL_SCAN_ALGORITHMIC | CL_SCAN_ELF | CL_SCAN_SWF | CL_SCAN_XMLDOCS | CL_SCAN_HWP3)
#define CL_DB_STDOPT (CL_DB_PHISHING | CL_DB_PHISHING_URLS | CL_DB_BYTECODE)

/*** scan options ***/
struct cl_scan_options {
uint32_t general;
uint32_t parse;
uint32_t heuristic;
uint32_t mail;
uint32_t dev;
};

/* general */
#define CL_SCAN_GENERAL_ALLMATCHES 0x1 /* scan in all-match mode */
#define CL_SCAN_GENERAL_COLLECT_METADATA 0x2 /* collect metadata (--gen-json) */
#define CL_SCAN_GENERAL_HEURISTICS 0x4 /* option to enable heuristic alerts */
#define CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE 0x8 /* allow heuristic match to take precedence. */

/* parsing capabilities options */
#define CL_SCAN_PARSE_ARCHIVE 0x1
#define CL_SCAN_PARSE_ELF 0x2
#define CL_SCAN_PARSE_PDF 0x4
#define CL_SCAN_PARSE_SWF 0x8
#define CL_SCAN_PARSE_HWP3 0x10
#define CL_SCAN_PARSE_XMLDOCS 0x20
#define CL_SCAN_PARSE_MAIL 0x40
#define CL_SCAN_PARSE_OLE2 0x80
#define CL_SCAN_PARSE_HTML 0x100
#define CL_SCAN_PARSE_PE 0x200

/* heuristic alerting options */
#define CL_SCAN_HEURISTIC_BROKEN 0x2
#define CL_SCAN_HEURISTIC_EXCEEDS_MAX 0x4
#define CL_SCAN_HEURISTIC_PHISHING_SSL_MISMATCH 0x8
#define CL_SCAN_HEURISTIC_PHISHING_CLOAK 0x10
#define CL_SCAN_HEURISTIC_MACROS 0x20
#define CL_SCAN_HEURISTIC_ENCRYPTED 0x40
#define CL_SCAN_HEURISTIC_PARTITION_INTXN 0x80 /* alert if partition table size doesn't make sense */
#define CL_SCAN_HEURISTIC_STRUCTURED 0x100 /* data loss prevention options, i.e. alert when detecting personal information */
#define CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL 0x200 /* alert when detecting social security numbers */
#define CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED 0x400 /* alert when detecting stripped social security numbers */

/* mail scanning options */
#define CL_SCAN_MAIL_PARTIAL_MESSAGE 0x1

/* dev options */
#define CL_SCAN_DEV_COLLECT_SHA 0x1 /* Enables hash output in sha-collect builds - for internal use only */
#define CL_SCAN_DEV_COLLECT_PERFORMANCE_INFO 0x2 /* collect performance timings */

/* cl_countsigs options */
#define CL_COUNTSIGS_OFFICIAL 0x1
Expand Down Expand Up @@ -488,11 +501,11 @@ struct cl_cvd { /* field no. */
};

/* file scanning */
extern int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions);
extern int cl_scandesc_callback(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions, void *context);
extern int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options* scanoptions);
extern int cl_scandesc_callback(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options* scanoptions, void *context);

extern int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions);
extern int cl_scanfile_callback(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions, void *context);
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_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 */
extern int cl_load(const char *path, struct cl_engine *engine, unsigned int *signo, unsigned int dboptions);
Expand Down Expand Up @@ -558,7 +571,7 @@ extern cl_fmap_t *cl_fmap_open_memory(const void *start, size_t len);
extern void cl_fmap_close(cl_fmap_t*);

/* Scan custom data */
extern int cl_scanmap_callback(cl_fmap_t *map, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions, void *context);
extern int cl_scanmap_callback(cl_fmap_t *map, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options *scanoptions, void *context);

/* Crypto/hashing functions */
#define SHA1_HASH_SIZE 20
Expand Down
2 changes: 1 addition & 1 deletion libclamav/clambc.h
@@ -1,7 +1,7 @@
/*
* ClamAV bytecode definitions.
*
* Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2014-2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2009-2010 Sourcefire, Inc.
*
* Authors: Török Edvin
Expand Down
12 changes: 6 additions & 6 deletions libclamav/cpio.c
Expand Up @@ -153,7 +153,7 @@ int cli_scancpio_old(cli_ctx *ctx)
continue;

if(cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS) {
if (!SCAN_ALL)
if (!SCAN_ALLMATCHES)
return CL_VIRUS;
virus_found = 1;
}
Expand All @@ -168,7 +168,7 @@ int cli_scancpio_old(cli_ctx *ctx)
} else if(ret == CL_SUCCESS) {
ret = cli_map_scan(*ctx->fmap, pos, filesize, ctx, CL_TYPE_ANY);
if(ret == CL_VIRUS) {
if (!SCAN_ALL)
if (!SCAN_ALLMATCHES)
return ret;
virus_found = 1;
}
Expand Down Expand Up @@ -247,7 +247,7 @@ int cli_scancpio_odc(cli_ctx *ctx)
continue;

if(cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS) {
if (!SCAN_ALL)
if (!SCAN_ALLMATCHES)
return CL_VIRUS;
virus_found = 1;
}
Expand All @@ -259,7 +259,7 @@ int cli_scancpio_odc(cli_ctx *ctx)
} else if(ret == CL_SUCCESS) {
ret = cli_map_scan(*ctx->fmap, pos, filesize, ctx, CL_TYPE_ANY);
if(ret == CL_VIRUS) {
if (!SCAN_ALL)
if (!SCAN_ALLMATCHES)
return ret;
virus_found = 1;
}
Expand Down Expand Up @@ -341,7 +341,7 @@ int cli_scancpio_newc(cli_ctx *ctx, int crc)
continue;

if(cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS) {
if (!SCAN_ALL)
if (!SCAN_ALLMATCHES)
return CL_VIRUS;
virus_found = 1;
}
Expand All @@ -352,7 +352,7 @@ int cli_scancpio_newc(cli_ctx *ctx, int crc)
} else if(ret == CL_SUCCESS) {
ret = cli_map_scan(*ctx->fmap, pos, filesize, ctx, CL_TYPE_ANY);
if(ret == CL_VIRUS) {
if (!SCAN_ALL)
if (!SCAN_ALLMATCHES)
return ret;
virus_found = 1;
}
Expand Down
2 changes: 1 addition & 1 deletion libclamav/dmg.c
Expand Up @@ -239,7 +239,7 @@ int cli_scandmg(cli_ctx *ctx)
if (depth < 0) {
break;
}
if ((depth > 50) && SCAN_ALGO) {
if ((depth > 50) && SCAN_HEURISTICS) {
// Possible heuristic, should limit runaway
cli_dbgmsg("cli_scandmg: Excessive nesting in DMG TOC.\n");
break;
Expand Down
24 changes: 12 additions & 12 deletions libclamav/elf.c
Expand Up @@ -213,7 +213,7 @@ static int cli_elf_ph32(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
cli_dbgmsg("ELF: Number of program headers: %d\n", phnum);
if(phnum > 128) {
cli_dbgmsg("ELF: Suspicious number of program headers\n");
if(ctx && DETECT_BROKEN) {
if(ctx && SCAN_HEURISTIC_BROKEN) {
cli_append_virus(ctx, "Heuristics.Broken.Executable");
return CL_VIRUS;
}
Expand All @@ -226,7 +226,7 @@ static int cli_elf_ph32(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
/* Sanity check */
if(phentsize != sizeof(struct elf_program_hdr32)) {
cli_dbgmsg("ELF: phentsize != sizeof(struct elf_program_hdr32)\n");
if(ctx && DETECT_BROKEN) {
if(ctx && SCAN_HEURISTIC_BROKEN) {
cli_append_virus(ctx, "Heuristics.Broken.Executable");
return CL_VIRUS;
}
Expand Down Expand Up @@ -261,7 +261,7 @@ static int cli_elf_ph32(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
cli_dbgmsg("ELF: Possibly broken ELF file\n");
}
free(program_hdr);
if(ctx && DETECT_BROKEN) {
if(ctx && SCAN_HEURISTIC_BROKEN) {
cli_append_virus(ctx, "Heuristics.Broken.Executable");
return CL_VIRUS;
}
Expand All @@ -283,7 +283,7 @@ static int cli_elf_ph32(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
free(program_hdr);
if(err) {
cli_dbgmsg("ELF: Can't calculate file offset of entry point\n");
if(ctx && DETECT_BROKEN) {
if(ctx && SCAN_HEURISTIC_BROKEN) {
cli_append_virus(ctx, "Heuristics.Broken.Executable");
return CL_VIRUS;
}
Expand Down Expand Up @@ -317,7 +317,7 @@ static int cli_elf_ph64(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
cli_dbgmsg("ELF: Number of program headers: %d\n", phnum);
if(phnum > 128) {
cli_dbgmsg("ELF: Suspicious number of program headers\n");
if(ctx && DETECT_BROKEN) {
if(ctx && SCAN_HEURISTIC_BROKEN) {
cli_append_virus(ctx, "Heuristics.Broken.Executable");
return CL_VIRUS;
}
Expand All @@ -330,7 +330,7 @@ static int cli_elf_ph64(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
/* Sanity check */
if (phentsize != sizeof(struct elf_program_hdr64)) {
cli_dbgmsg("ELF: phentsize != sizeof(struct elf_program_hdr64)\n");
if(ctx && DETECT_BROKEN) {
if(ctx && SCAN_HEURISTIC_BROKEN) {
cli_append_virus(ctx, "Heuristics.Broken.Executable");
return CL_VIRUS;
}
Expand Down Expand Up @@ -365,7 +365,7 @@ static int cli_elf_ph64(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
cli_dbgmsg("ELF: Possibly broken ELF file\n");
}
free(program_hdr);
if(ctx && DETECT_BROKEN) {
if(ctx && SCAN_HEURISTIC_BROKEN) {
cli_append_virus(ctx, "Heuristics.Broken.Executable");
return CL_VIRUS;
}
Expand All @@ -387,7 +387,7 @@ static int cli_elf_ph64(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
free(program_hdr);
if(err) {
cli_dbgmsg("ELF: Can't calculate file offset of entry point\n");
if(ctx && DETECT_BROKEN) {
if(ctx && SCAN_HEURISTIC_BROKEN) {
cli_append_virus(ctx, "Heuristics.Broken.Executable");
return CL_VIRUS;
}
Expand Down Expand Up @@ -432,7 +432,7 @@ static int cli_elf_sh32(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
/* Sanity check */
if(shentsize != sizeof(struct elf_section_hdr32)) {
cli_dbgmsg("ELF: shentsize != sizeof(struct elf_section_hdr32)\n");
if(ctx && DETECT_BROKEN) {
if(ctx && SCAN_HEURISTIC_BROKEN) {
cli_append_virus(ctx, "Heuristics.Broken.Executable");
return CL_VIRUS;
}
Expand Down Expand Up @@ -484,7 +484,7 @@ static int cli_elf_sh32(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
free(elfinfo->section);
elfinfo->section = NULL;
}
if(ctx && DETECT_BROKEN) {
if(ctx && SCAN_HEURISTIC_BROKEN) {
cli_append_virus(ctx, "Heuristics.Broken.Executable");
return CL_VIRUS;
}
Expand Down Expand Up @@ -542,7 +542,7 @@ static int cli_elf_sh64(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
/* Sanity check */
if(shentsize != sizeof(struct elf_section_hdr64)) {
cli_dbgmsg("ELF: shentsize != sizeof(struct elf_section_hdr64)\n");
if(ctx && DETECT_BROKEN) {
if(ctx && SCAN_HEURISTIC_BROKEN) {
cli_append_virus(ctx, "Heuristics.Broken.Executable");
return CL_VIRUS;
}
Expand Down Expand Up @@ -594,7 +594,7 @@ static int cli_elf_sh64(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
free(elfinfo->section);
elfinfo->section = NULL;
}
if(ctx && DETECT_BROKEN) {
if(ctx && SCAN_HEURISTIC_BROKEN) {
cli_append_virus(ctx, "Heuristics.Broken.Executable");
return CL_VIRUS;
}
Expand Down
20 changes: 10 additions & 10 deletions libclamav/gpt.c
Expand Up @@ -137,7 +137,7 @@ int cli_scangpt(cli_ctx *ctx, size_t sectorsize)
/* check the protective mbr */
ret = gpt_check_mbr(ctx, sectorsize);
if (ret != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
Expand Down Expand Up @@ -198,17 +198,17 @@ int cli_scangpt(cli_ctx *ctx, size_t sectorsize)
}

/* check that the partition table has no intersections - HEURISTICS */
if ((ctx->options & CL_SCAN_PARTITION_INTXN) && (ctx->dconf->other & OTHER_CONF_PRTNINTXN)) {
if (SCAN_HEURISTIC_PARTITION_INTXN && (ctx->dconf->other & OTHER_CONF_PRTNINTXN)) {
ret = gpt_prtn_intxn(ctx, phdr, sectorsize);
if (ret != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
}
ret = gpt_prtn_intxn(ctx, shdr, sectorsize);
if (ret != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
Expand All @@ -221,7 +221,7 @@ int cli_scangpt(cli_ctx *ctx, size_t sectorsize)
cli_dbgmsg("cli_scangpt: Scanning primary GPT partitions only\n");
ret = gpt_scan_partitions(ctx, phdr, sectorsize);
if (ret != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
Expand All @@ -231,7 +231,7 @@ int cli_scangpt(cli_ctx *ctx, size_t sectorsize)
cli_dbgmsg("cli_scangpt: Scanning secondary GPT partitions only\n");
ret = gpt_scan_partitions(ctx, shdr, sectorsize);
if (ret != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
Expand All @@ -241,15 +241,15 @@ int cli_scangpt(cli_ctx *ctx, size_t sectorsize)
cli_dbgmsg("cli_scangpt: Scanning primary GPT partitions\n");
ret = gpt_scan_partitions(ctx, phdr, sectorsize);
if (ret != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
}
cli_dbgmsg("cli_scangpt: Scanning secondary GPT partitions\n");
ret = gpt_scan_partitions(ctx, shdr, sectorsize);
if (ret != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
Expand Down Expand Up @@ -351,7 +351,7 @@ static int gpt_scan_partitions(cli_ctx *ctx, struct gpt_header hdr, size_t secto
part_size = (gpe.lastLBA - gpe.firstLBA + 1) * sectorsize;
ret = cli_map_scan(*ctx->fmap, part_off, part_size, ctx, CL_TYPE_PART_ANY);
if (ret != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
Expand Down Expand Up @@ -654,7 +654,7 @@ static int gpt_prtn_intxn(cli_ctx *ctx, struct gpt_header hdr, size_t sectorsize
ret = cli_append_virus(ctx, PRTN_INTXN_DETECTION);
if (ret == CL_VIRUS)
virus_found = 1;
if (SCAN_ALL || ret == CL_CLEAN)
if (SCAN_ALLMATCHES || ret == CL_CLEAN)
tmp = 0;
else
goto leave;
Expand Down
8 changes: 4 additions & 4 deletions libclamav/hfsplus.c
Expand Up @@ -662,8 +662,8 @@ static int hfsplus_walk_catalog(cli_ctx *ctx, hfsPlusVolumeHeader *volHeader, hf
/* Check return code */
if (ret == CL_VIRUS) {
has_alerts = 1;
if (SCAN_ALL) {
/* Continue scanning in SCAN_ALL mode */
if (SCAN_ALLMATCHES) {
/* Continue scanning in SCAN_ALLMATCHES mode */
cli_dbgmsg("hfsplus_walk_catalog: data fork alert, continuing");
ret = CL_CLEAN;
}
Expand All @@ -681,8 +681,8 @@ static int hfsplus_walk_catalog(cli_ctx *ctx, hfsPlusVolumeHeader *volHeader, hf
/* Check return code */
if (ret == CL_VIRUS) {
has_alerts = 1;
if (SCAN_ALL) {
/* Continue scanning in SCAN_ALL mode */
if (SCAN_ALLMATCHES) {
/* Continue scanning in SCAN_ALLMATCHES mode */
cli_dbgmsg("hfsplus_walk_catalog: resource fork alert, continuing");
ret = CL_CLEAN;
}
Expand Down
44 changes: 22 additions & 22 deletions libclamav/hwp.c
Expand Up @@ -306,7 +306,7 @@ int cli_hwp5header(cli_ctx *ctx, hwp5_header_t *hwp5)
return CL_ENULLARG;

#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES) {
if (SCAN_COLLECT_METADATA) {
json_object *header, *flags;

header = cli_jsonobj(ctx->wrkproperty, "Hwp5Header");
Expand Down Expand Up @@ -426,7 +426,7 @@ int cli_scanhwp5_stream(cli_ctx *ctx, hwp5_header_t *hwp5, char *name, int fd)

#if HAVE_JSON
/* JSON Output Summary Information */
if (ctx->options & CL_SCAN_FILE_PROPERTIES && ctx->properties != NULL) {
if (SCAN_COLLECT_METADATA && ctx->properties != NULL) {
if (name && !strncmp(name, "_5_hwpsummaryinformation", 24)) {
cli_dbgmsg("HWP5.x: Detected a '_5_hwpsummaryinformation' stream\n");
/* JSONOLE2 - what to do if something breaks? */
Expand Down Expand Up @@ -539,7 +539,7 @@ static inline int parsehwp3_docinfo(cli_ctx *ctx, off_t offset, struct hwp3_doci
hwp3_debug("HWP3.x: di_infoblksize: %u\n", docinfo->di_infoblksize);

#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES) {
if (SCAN_COLLECT_METADATA) {
json_object *header, *flags;
char *str;

Expand Down Expand Up @@ -605,7 +605,7 @@ static inline int parsehwp3_docsummary(cli_ctx *ctx, off_t offset)
int i, iret, ret;
json_object *summary;

if (!(ctx->options & CL_SCAN_FILE_PROPERTIES))
if (!SCAN_COLLECT_METADATA)
return CL_SUCCESS;

if (!(hwp3_ptr = fmap_need_off_once(*ctx->fmap, offset, HWP3_DOCSUMMARY_SIZE))) {
Expand Down Expand Up @@ -1537,7 +1537,7 @@ static inline int parsehwp3_infoblk_1(cli_ctx *ctx, fmap_t *dmap, off_t *offset,
hwp3_debug("HWP3.x: Information Block @ offset %llu\n", infoloc);

#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES) {
if (SCAN_COLLECT_METADATA) {
infoblk_1 = cli_jsonobj(ctx->wrkproperty, "InfoBlk_1");
if (!infoblk_1) {
cli_errmsg("HWP5.x: No memory for information block object\n");
Expand Down Expand Up @@ -1568,7 +1568,7 @@ static inline int parsehwp3_infoblk_1(cli_ctx *ctx, fmap_t *dmap, off_t *offset,
infoid = le32_to_host(infoid);

#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES) {
if (SCAN_COLLECT_METADATA) {
entry = cli_jsonobj(contents, NULL);
if (!entry) {
cli_errmsg("HWP5.x: No memory for information block entry object\n");
Expand All @@ -1584,7 +1584,7 @@ static inline int parsehwp3_infoblk_1(cli_ctx *ctx, fmap_t *dmap, off_t *offset,
if (infoid == 5) {
hwp3_debug("HWP3.x: Information Block[%llu]: TYPE: Booking Information\n", infoloc);
#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES)
if (SCAN_COLLECT_METADATA)
cli_jsonstr(entry, "Type", "Booking Information");
#endif
return CL_SUCCESS;
Expand All @@ -1599,7 +1599,7 @@ static inline int parsehwp3_infoblk_1(cli_ctx *ctx, fmap_t *dmap, off_t *offset,
infolen = le32_to_host(infolen);

#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES) {
if (SCAN_COLLECT_METADATA) {
cli_jsonint64(entry, "Offset", infoloc);
cli_jsonint(entry, "Length", infolen);
}
Expand All @@ -1619,7 +1619,7 @@ static inline int parsehwp3_infoblk_1(cli_ctx *ctx, fmap_t *dmap, off_t *offset,
if (infolen == 0) {
hwp3_debug("HWP3.x: Information Block[%llu]: TYPE: Terminating Entry\n", infoloc);
#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES)
if (SCAN_COLLECT_METADATA)
cli_jsonstr(entry, "Type", "Terminating Entry");
#endif
if (last) *last = 1;
Expand All @@ -1631,7 +1631,7 @@ static inline int parsehwp3_infoblk_1(cli_ctx *ctx, fmap_t *dmap, off_t *offset,
case 1: /* Image Data */
hwp3_debug("HWP3.x: Information Block[%llu]: TYPE: Image Data\n", infoloc);
#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES)
if (SCAN_COLLECT_METADATA)
cli_jsonstr(entry, "Type", "Image Data");
#endif
#if HWP3_DEBUG /* additional fields can be added */
Expand All @@ -1658,7 +1658,7 @@ static inline int parsehwp3_infoblk_1(cli_ctx *ctx, fmap_t *dmap, off_t *offset,
case 2: /* OLE2 Data */
hwp3_debug("HWP3.x: Information Block[%llu]: TYPE: OLE2 Data\n", infoloc);
#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES)
if (SCAN_COLLECT_METADATA)
cli_jsonstr(entry, "Type", "OLE2 Data");
#endif
if (infolen > 0)
Expand All @@ -1674,7 +1674,7 @@ static inline int parsehwp3_infoblk_1(cli_ctx *ctx, fmap_t *dmap, off_t *offset,
count = (infolen / 617);
hwp3_debug("HWP3.x: Information Block[%llu]: COUNT: %d entries\n", infoloc, count);
#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES) {
if (SCAN_COLLECT_METADATA) {
cli_jsonstr(entry, "Type", "Hypertext/Hyperlink Information");
cli_jsonint(entry, "Count", count);
}
Expand All @@ -1697,7 +1697,7 @@ static inline int parsehwp3_infoblk_1(cli_ctx *ctx, fmap_t *dmap, off_t *offset,
case 4: /* Presentation Information */
hwp3_debug("HWP3.x: Information Block[%llu]: TYPE: Presentation Information\n", infoloc);
#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES)
if (SCAN_COLLECT_METADATA)
cli_jsonstr(entry, "Type", "Presentation Information");
#endif
/* contains nothing of interest to scan */
Expand All @@ -1706,14 +1706,14 @@ static inline int parsehwp3_infoblk_1(cli_ctx *ctx, fmap_t *dmap, off_t *offset,
/* should never run this as it is short-circuited above */
hwp3_debug("HWP3.x: Information Block[%llu]: TYPE: Booking Information\n", infoloc);
#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES)
if (SCAN_COLLECT_METADATA)
cli_jsonstr(entry, "Type", "Booking Information");
#endif
break;
case 6: /* Background Image Data */
hwp3_debug("HWP3.x: Information Block[%llu]: TYPE: Background Image Data\n", infoloc);
#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES) {
if (SCAN_COLLECT_METADATA) {
cli_jsonstr(entry, "Type", "Background Image Data");
cli_jsonint(entry, "ImageSize", infolen-324);
}
Expand All @@ -1734,15 +1734,15 @@ static inline int parsehwp3_infoblk_1(cli_ctx *ctx, fmap_t *dmap, off_t *offset,
case 0x100: /* Table Extension */
hwp3_debug("HWP3.x: Information Block[%llu]: TYPE: Table Extension\n", infoloc);
#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES)
if (SCAN_COLLECT_METADATA)
cli_jsonstr(entry, "Type", "Table Extension");
#endif
/* contains nothing of interest to scan */
break;
case 0x101: /* Press Frame Information Field Name */
hwp3_debug("HWP3.x: Information Block[%llu]: TYPE: Press Frame Information Field Name\n", infoloc);
#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES)
if (SCAN_COLLECT_METADATA)
cli_jsonstr(entry, "Type", "Press Frame Information Field Name");
#endif
/* contains nothing of interest to scan */
Expand Down Expand Up @@ -1796,7 +1796,7 @@ static int hwp3_cb(void *cbdata, int fd, cli_ctx *ctx)

/* Fonts - 7 entries of 2 + (n x 40) bytes where n is the first 2 bytes of the entry */
#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES)
if (SCAN_COLLECT_METADATA)
fonts = cli_jsonarray(ctx->wrkproperty, "FontCounts");
#endif
for (i = 0; i < 7; i++) {
Expand All @@ -1810,7 +1810,7 @@ static int hwp3_cb(void *cbdata, int fd, cli_ctx *ctx)
nfonts = le16_to_host(nfonts);

#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES)
if (SCAN_COLLECT_METADATA)
cli_jsonint(fonts, NULL, nfonts);
#endif
hwp3_debug("HWP3.x: Font Entry %d with %u entries @ offset %llu\n", i+1, nfonts, (long long unsigned)offset);
Expand All @@ -1831,7 +1831,7 @@ static int hwp3_cb(void *cbdata, int fd, cli_ctx *ctx)
nstyles = le16_to_host(nstyles);

#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES)
if (SCAN_COLLECT_METADATA)
cli_jsonint(ctx->wrkproperty, "StyleCount", nstyles);
#endif
hwp3_debug("HWP3.x: %u Styles @ offset %llu\n", nstyles, (long long unsigned)offset);
Expand All @@ -1853,7 +1853,7 @@ static int hwp3_cb(void *cbdata, int fd, cli_ctx *ctx)
return ret;
}
#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES)
if (SCAN_COLLECT_METADATA)
cli_jsonint(ctx->wrkproperty, "ParagraphCount", p);
#endif

Expand All @@ -1862,7 +1862,7 @@ static int hwp3_cb(void *cbdata, int fd, cli_ctx *ctx)
while (!last && ((ret = parsehwp3_infoblk_1(ctx, map, &offset, &last)) == CL_SUCCESS));

/* scan the uncompressed stream - both compressed and uncompressed cases [ALLMATCH] */
if ((ret == CL_SUCCESS) || ((SCAN_ALL) && (ret == CL_VIRUS))) {
if ((ret == CL_SUCCESS) || ((SCAN_ALLMATCHES) && (ret == CL_VIRUS))) {
int subret = ret;
size_t dlen = offset - start;

Expand Down
2 changes: 1 addition & 1 deletion libclamav/ishield.c
Expand Up @@ -380,7 +380,7 @@ int cli_scanishield(cli_ctx *ctx, off_t off, size_t sz) {

cli_dbgmsg("ishield: @%lx found file %s (%s) - version %s - size %lu\n", (unsigned long int) coff, fname, path, version, (unsigned long int) fsize);
if(cli_matchmeta(ctx, fname, fsize, fsize, 0, fc++, 0, NULL) == CL_VIRUS) {
if (!SCAN_ALL) {
if (!SCAN_ALLMATCHES) {
ret = CL_VIRUS;
break;
}
Expand Down
4 changes: 2 additions & 2 deletions libclamav/iso9660.c
Expand Up @@ -187,7 +187,7 @@ static int iso_parse_dir(iso9660_t *iso, unsigned int block, unsigned int len) {
ret = cli_matchmeta(ctx, iso->buf, filesz, filesz, 0, 0, 0, NULL);
if (ret == CL_VIRUS) {
viruses_found = 1;
if (!SCAN_ALL)
if (!SCAN_ALLMATCHES)
break;
ret = CL_CLEAN;
}
Expand All @@ -206,7 +206,7 @@ static int iso_parse_dir(iso9660_t *iso, unsigned int block, unsigned int len) {
}
if (ret == CL_VIRUS) {
viruses_found = 1;
if (!SCAN_ALL)
if (!SCAN_ALLMATCHES)
break;
ret = CL_CLEAN;
}
Expand Down
2 changes: 1 addition & 1 deletion libclamav/json_api.c
Expand Up @@ -31,7 +31,7 @@
#ifdef HAVE_JSON
int cli_json_timeout_cycle_check(cli_ctx *ctx, int *toval)
{
if (ctx->options & CL_SCAN_FILE_PROPERTIES) {
if (SCAN_COLLECT_METADATA) {
if (*toval <= 0) {
if (cli_checktimelimit(ctx) != CL_SUCCESS) {
cli_errmsg("cli_json_timeout_cycle_check: timeout!\n");
Expand Down
8 changes: 4 additions & 4 deletions libclamav/libmspack.c
Expand Up @@ -385,7 +385,7 @@ int cli_scanmscab(cli_ctx *ctx, off_t sfx_offset)
if (ret) {
if (ret == CL_VIRUS) {
virus_num++;
if (!SCAN_ALL)
if (!SCAN_ALLMATCHES)
break;
}
goto out_close;
Expand Down Expand Up @@ -434,7 +434,7 @@ int cli_scanmscab(cli_ctx *ctx, off_t sfx_offset)
}
free(tmp_fname);
files++;
if (ret == CL_VIRUS && SCAN_ALL)
if (ret == CL_VIRUS && SCAN_ALLMATCHES)
continue;
if (ret)
break;
Expand Down Expand Up @@ -486,7 +486,7 @@ int cli_scanmschm(cli_ctx *ctx)
if (ret) {
if (ret == CL_VIRUS) {
virus_num++;
if (!SCAN_ALL)
if (!SCAN_ALLMATCHES)
break;
}
goto out_close;
Expand Down Expand Up @@ -536,7 +536,7 @@ int cli_scanmschm(cli_ctx *ctx)
}
free(tmp_fname);
files++;
if (ret == CL_VIRUS && SCAN_ALL)
if (ret == CL_VIRUS && SCAN_ALLMATCHES)
continue;
if (ret)
break;
Expand Down
2 changes: 1 addition & 1 deletion libclamav/macho.c
Expand Up @@ -175,7 +175,7 @@ struct macho_fat_arch
#define RETURN_BROKEN \
if(matcher) \
return -1; \
if(DETECT_BROKEN) { \
if(SCAN_HEURISTIC_BROKEN) { \
if (CL_VIRUS == cli_append_virus(ctx, "Heuristics.Broken.Executable")) \
return CL_VIRUS; \
} \
Expand Down
8 changes: 4 additions & 4 deletions libclamav/matcher-ac.c
Expand Up @@ -1854,15 +1854,15 @@ int cli_ac_scanbuff(
ptN = ptN->next_same;
continue;
} else {
if(ctx && SCAN_ALL) {
if(ctx && SCAN_ALLMATCHES) {
cli_append_virus(ctx, (const char *)pt->virname);
viruses_found = 1;
}
if (virname)
*virname = pt->virname;
if(customdata)
*customdata = pt->customdata;
if (!ctx || !SCAN_ALL)
if (!ctx || !SCAN_ALLMATCHES)
return CL_VIRUS;
ptN = ptN->next_same;
continue;
Expand Down Expand Up @@ -1909,7 +1909,7 @@ int cli_ac_scanbuff(
ptN = ptN->next_same;
continue;
} else {
if(ctx && SCAN_ALL) {
if(ctx && SCAN_ALLMATCHES) {
cli_append_virus(ctx, (const char *)pt->virname);
viruses_found = 1;
}
Expand All @@ -1920,7 +1920,7 @@ int cli_ac_scanbuff(
if(customdata)
*customdata = pt->customdata;

if (!ctx || !SCAN_ALL)
if (!ctx || !SCAN_ALLMATCHES)
return CL_VIRUS;

ptN = ptN->next_same;
Expand Down
4 changes: 2 additions & 2 deletions libclamav/matcher-bm.c
Expand Up @@ -381,7 +381,7 @@ int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
}
if(virname) {
*virname = p->virname;
if(ctx != NULL && SCAN_ALL) {
if(ctx != NULL && SCAN_ALLMATCHES) {
cli_append_virus(ctx, *virname);
//*viroffset = offset + i + j - BM_MIN_LENGTH + BM_BLOCK_SIZE;
}
Expand All @@ -391,7 +391,7 @@ int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **v

viruses_found = 1;

if(ctx != NULL && !SCAN_ALL)
if(ctx != NULL && !SCAN_ALLMATCHES)
return CL_VIRUS;
}
p = p->next;
Expand Down
2 changes: 1 addition & 1 deletion libclamav/matcher-pcre.c
Expand Up @@ -744,7 +744,7 @@ int cli_pcre_scanbuf(const unsigned char *buffer, uint32_t length, const char **
ret = cli_append_virus(ctx, (const char *)pm->virname);
if (virname)
*virname = pm->virname;
if (!ctx || !SCAN_ALL)
if (!ctx || !SCAN_ALLMATCHES)
if (ret != CL_CLEAN)
break;
}
Expand Down