e3aaff8e |
/* |
2023340a |
* Copyright (C) 2007-2008 Sourcefire, Inc. |
4addba22 |
* |
2023340a |
* Authors: Tomasz Kojm |
e3aaff8e |
*
* This program is free software; you can redistribute it and/or modify |
bb34cb31 |
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. |
e3aaff8e |
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software |
48b7b4a7 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA. |
e3aaff8e |
*/
|
6d6e8271 |
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
|
e3aaff8e |
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h> |
b58fdfc2 |
#ifdef HAVE_UNISTD_H |
e3aaff8e |
#include <unistd.h> |
b58fdfc2 |
#endif |
d3a6556d |
#ifndef C_WINDOWS |
e3aaff8e |
#include <dirent.h> |
b58fdfc2 |
#endif |
e3aaff8e |
#include <sys/types.h>
#include <sys/stat.h> |
b58fdfc2 |
#ifdef HAVE_SYS_PARAM_H |
15edd45f |
#include <sys/param.h> |
b58fdfc2 |
#endif |
e3aaff8e |
#include <fcntl.h> |
056d95dc |
#include <zlib.h> |
e3aaff8e |
#include "clamav.h" |
e4ae7726 |
#include "cvd.h" |
b58fdfc2 |
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif |
8000d078 |
#include "matcher-ac.h"
#include "matcher-bm.h" |
bedc58de |
#include "matcher.h" |
e3aaff8e |
#include "others.h"
#include "str.h" |
bc93eda0 |
#include "dconf.h" |
7021b545 |
#include "filetypes.h"
#include "filetypes_int.h" |
fc83da82 |
#include "readdb.h" |
677fc4ba |
#include "cltypes.h" |
4367454d |
#include "default.h" |
e3aaff8e |
|
fc83da82 |
#include "phishcheck.h" |
7dec7955 |
#include "phish_whitelist.h"
#include "phish_domaincheck_db.h" |
3da4dd4c |
#include "regex_list.h" |
c3671221 |
#include "hashtab.h" |
7dec7955 |
|
2bb229f6 |
#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2)
#include <limits.h> |
88794204 |
#include <stddef.h> |
2bb229f6 |
#endif
|
b94e66c4 |
#include "mpool.h"
|
f51e962f |
#ifdef CL_THREAD_SAFE
# include <pthread.h>
static pthread_mutex_t cli_ref_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
|
ed9753e9 |
struct cli_ignsig {
char *dbname, *signame;
unsigned int line;
struct cli_ignsig *next;
};
struct cli_ignored {
struct hashset hs;
struct cli_ignsig *list;
};
|
d6e1ef16 |
char *cli_virname(char *virname, unsigned int official) |
b5513f8d |
{
char *newname, *pt;
if(!virname)
return NULL;
if((pt = strstr(virname, " (Clam)"))) |
d6e1ef16 |
*pt='\0'; |
b5513f8d |
|
d6e1ef16 |
if(!virname[0]) { |
b5513f8d |
cli_errmsg("cli_virname: Empty virus name\n");
return NULL;
}
|
d6e1ef16 |
if(official)
return cli_strdup(virname); |
b5513f8d |
|
d6e1ef16 |
newname = (char *) cli_malloc(strlen(virname) + 11 + 1);
if(!newname) {
cli_errmsg("cli_virname: Can't allocate memory for newname\n");
return NULL; |
b5513f8d |
} |
d6e1ef16 |
sprintf(newname, "%s.UNOFFICIAL", virname);
return newname; |
b5513f8d |
}
|
ec285505 |
int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hexsig, uint16_t rtype, uint16_t type, const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options) |
888f5794 |
{ |
8000d078 |
struct cli_bm_patt *bm_new; |
084ee140 |
char *pt, *hexcpy, *start, *n; |
b5513f8d |
int ret, asterisk = 0; |
33f89aa5 |
unsigned int i, j, len, parts = 0; |
084ee140 |
int mindist = 0, maxdist = 0, error = 0;
|
888f5794 |
|
084ee140 |
if(strchr(hexsig, '{')) { |
888f5794 |
|
8000d078 |
root->ac_partsigs++; |
084ee140 |
|
6f38c939 |
if(!(hexcpy = cli_strdup(hexsig))) |
084ee140 |
return CL_EMEM;
len = strlen(hexsig);
for(i = 0; i < len; i++) |
a8f79297 |
if(hexsig[i] == '{' || hexsig[i] == '*') |
084ee140 |
parts++;
if(parts)
parts++;
start = pt = hexcpy;
for(i = 1; i <= parts; i++) {
if(i != parts) { |
a8f79297 |
for(j = 0; j < strlen(start); j++) {
if(start[j] == '{') {
asterisk = 0;
pt = start + j;
break;
}
if(start[j] == '*') {
asterisk = 1;
pt = start + j;
break;
}
} |
084ee140 |
*pt++ = 0;
}
|
341faf60 |
if((ret = cli_ac_addsig(root, virname, start, root->ac_partsigs, parts, i, rtype, type, mindist, maxdist, offset, lsigid, options))) { |
a8f79297 |
cli_errmsg("cli_parse_add(): Problem adding signature (1).\n"); |
084ee140 |
error = 1;
break;
}
if(i == parts)
break;
|
a8f79297 |
mindist = maxdist = 0;
if(asterisk) {
start = pt;
continue;
}
|
084ee140 |
if(!(start = strchr(pt, '}'))) {
error = 1;
break;
}
*start++ = 0;
if(!pt) {
error = 1;
break;
}
if(!strchr(pt, '-')) { |
a3fe2c5b |
if(!cli_isnumber(pt) || (mindist = maxdist = atoi(pt)) < 0) { |
084ee140 |
error = 1;
break;
}
} else { |
b68d11d2 |
if((n = cli_strtok(pt, 0, "-"))) { |
a3fe2c5b |
if(!cli_isnumber(n) || (mindist = atoi(n)) < 0) { |
084ee140 |
error = 1;
free(n);
break;
}
free(n);
}
|
b68d11d2 |
if((n = cli_strtok(pt, 1, "-"))) { |
a3fe2c5b |
if(!cli_isnumber(n) || (maxdist = atoi(n)) < 0) { |
084ee140 |
error = 1;
free(n);
break;
}
free(n);
} |
a3fe2c5b |
if((n = cli_strtok(pt, 2, "-"))) { /* strict check */
error = 1;
free(n); |
9b0004bf |
break; |
a3fe2c5b |
} |
084ee140 |
}
}
free(hexcpy);
if(error)
return CL_EMALFDB;
} else if(strchr(hexsig, '*')) { |
8000d078 |
root->ac_partsigs++; |
888f5794 |
len = strlen(hexsig);
for(i = 0; i < len; i++)
if(hexsig[i] == '*')
parts++;
|
8000d078 |
if(parts) |
888f5794 |
parts++;
for(i = 1; i <= parts; i++) {
if((pt = cli_strtok(hexsig, i - 1, "*")) == NULL) { |
3ed92fe1 |
cli_errmsg("Can't extract part %d of partial signature.\n", i); |
888f5794 |
return CL_EMALFDB;
}
|
341faf60 |
if((ret = cli_ac_addsig(root, virname, pt, root->ac_partsigs, parts, i, rtype, type, 0, 0, offset, lsigid, options))) { |
a8f79297 |
cli_errmsg("cli_parse_add(): Problem adding signature (2).\n"); |
888f5794 |
free(pt);
return ret;
}
free(pt);
}
|
677fc4ba |
} else if(root->ac_only || strpbrk(hexsig, "?(") || type || lsigid) { |
341faf60 |
if((ret = cli_ac_addsig(root, virname, hexsig, 0, 0, 0, rtype, type, 0, 0, offset, lsigid, options))) { |
a8f79297 |
cli_errmsg("cli_parse_add(): Problem adding signature (3).\n"); |
8000d078 |
return ret;
}
} else { |
47d40feb |
bm_new = (struct cli_bm_patt *) mpool_calloc(root->mempool, 1, sizeof(struct cli_bm_patt)); |
8000d078 |
if(!bm_new)
return CL_EMEM; |
47d40feb |
bm_new->pattern = (unsigned char *) cli_mpool_hex2str(root->mempool, hexsig); |
b583d6ed |
if(!bm_new->pattern) { |
47d40feb |
mpool_free(root->mempool, bm_new); |
8000d078 |
return CL_EMALFDB; |
091df0e3 |
} |
8000d078 |
bm_new->length = strlen(hexsig) / 2;
|
47d40feb |
bm_new->virname = cli_mpool_virname(root->mempool, (char *) virname, options & CL_DB_OFFICIAL); |
b5513f8d |
if(!bm_new->virname) { |
47d40feb |
mpool_free(root->mempool, bm_new->pattern);
mpool_free(root->mempool, bm_new); |
8000d078 |
return CL_EMEM;
}
|
6f38c939 |
if(offset) { |
47d40feb |
bm_new->offset = cli_mpool_strdup(root->mempool, offset); |
6f38c939 |
if(!bm_new->offset) { |
47d40feb |
mpool_free(root->mempool, bm_new->pattern);
mpool_free(root->mempool, bm_new->virname);
mpool_free(root->mempool, bm_new); |
6f38c939 |
return CL_EMEM;
} |
c889f9cf |
}
|
b68d11d2 |
bm_new->target = target;
|
8000d078 |
if(bm_new->length > root->maxpatlen)
root->maxpatlen = bm_new->length;
if((ret = cli_bm_addpatt(root, bm_new))) { |
a8f79297 |
cli_errmsg("cli_parse_add(): Problem adding signature (4).\n"); |
47d40feb |
mpool_free(root->mempool, bm_new->pattern);
mpool_free(root->mempool, bm_new->virname);
mpool_free(root->mempool, bm_new); |
888f5794 |
return ret;
}
}
|
8d3aca30 |
return CL_SUCCESS; |
888f5794 |
} |
e3aaff8e |
|
83fa5305 |
static int cli_initroots(struct cl_engine *engine, unsigned int options) |
5612732c |
{
int i, ret;
struct cli_matcher *root;
|
4addba22 |
for(i = 0; i < CLI_MTARGETS; i++) { |
5612732c |
if(!engine->root[i]) {
cli_dbgmsg("Initializing engine->root[%d]\n", i); |
47d40feb |
root = engine->root[i] = (struct cli_matcher *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_matcher)); |
b94e66c4 |
#ifdef USE_MPOOL
root->mempool = engine->mempool;
#endif |
5612732c |
if(!root) { |
0a3d4094 |
cli_errmsg("cli_initroots: Can't allocate memory for cli_matcher\n"); |
5612732c |
return CL_EMEM;
}
|
ab0d2f05 |
if(cli_mtargets[i].ac_only || engine->ac_only) |
83fa5305 |
root->ac_only = 1;
|
5612732c |
cli_dbgmsg("Initialising AC pattern matcher of root[%d]\n", i); |
ab0d2f05 |
if((ret = cli_ac_init(root, engine->ac_mindepth, engine->ac_maxdepth))) { |
5612732c |
/* no need to free previously allocated memory here */ |
0a3d4094 |
cli_errmsg("cli_initroots: Can't initialise AC pattern matcher\n"); |
fbcef1b0 |
return ret; |
5612732c |
}
|
83fa5305 |
if(!root->ac_only) { |
0a3d4094 |
cli_dbgmsg("cli_initroots: Initializing BM tables of root[%d]\n", i); |
83fa5305 |
if((ret = cli_bm_init(root))) { |
0a3d4094 |
cli_errmsg("cli_initroots: Can't initialise BM pattern matcher\n"); |
83fa5305 |
return ret;
} |
5612732c |
} |
8000d078 |
}
}
|
8d3aca30 |
return CL_SUCCESS; |
5612732c |
}
|
e8ae4fae |
char *cli_dbgets(char *buff, unsigned int size, FILE *fs, struct cli_dbio *dbio) |
056d95dc |
{
if(fs) {
return fgets(buff, size, fs);
} else {
char *pt;
unsigned int bs;
|
e8ae4fae |
if(!dbio->size) |
056d95dc |
return NULL;
|
e8ae4fae |
bs = dbio->size < size ? dbio->size + 1 : size;
if(dbio->gzs)
pt = gzgets(dbio->gzs, buff, bs);
else
pt = fgets(buff, bs, dbio->fs);
dbio->size -= strlen(buff); |
056d95dc |
if(!pt)
cli_errmsg("cli_dbgets: Preliminary end of data\n");
return pt;
}
}
|
ed9753e9 |
static int cli_chkign(const struct cli_ignored *ignored, const char *dbname, unsigned int line, const char *signame)
{
struct cli_ignsig *pt;
if(!ignored || !dbname || !signame)
return 0;
if(hashset_contains(&ignored->hs, line)) {
pt = ignored->list;
while(pt) {
if(pt->line == line && !strcmp(pt->dbname, dbname) && !strcmp(pt->signame, signame)) {
cli_dbgmsg("Skipping signature %s @ %s:%u\n", signame, dbname, line);
return 1;
}
pt = pt->next;
}
}
return 0;
}
|
b023c36d |
static int cli_chkpua(const char *signame, const char *pua_cats, unsigned int options)
{
char cat[32], *pt;
const char *sig;
int ret;
if(strncmp(signame, "PUA.", 4)) {
cli_dbgmsg("Skipping signature %s - no PUA prefix\n", signame);
return 1;
}
sig = signame + 3;
if(!(pt = strchr(sig + 1, '.'))) {
cli_dbgmsg("Skipping signature %s - bad syntax\n", signame);
return 1;
}
|
a45c7039 |
if((unsigned int) (pt - sig + 2) > sizeof(cat)) { |
b023c36d |
cli_dbgmsg("Skipping signature %s - too long category name\n", signame);
return 1;
}
strncpy(cat, sig, pt - signame + 1);
cat[pt - sig + 1] = 0;
pt = strstr(pua_cats, cat);
if(options & CL_DB_PUA_INCLUDE)
ret = pt ? 0 : 1;
else
ret = pt ? 1 : 0;
if(ret)
cli_dbgmsg("Skipping PUA signature %s - excluded category\n", signame);
return ret;
}
|
15850fc6 |
static int cli_loaddb(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, const char *dbname) |
5612732c |
{
char buffer[FILEBUFF], *pt, *start; |
ed9753e9 |
unsigned int line = 0, sigs = 0;
int ret = 0; |
5612732c |
struct cli_matcher *root;
|
15850fc6 |
if((ret = cli_initroots(engine, options))) |
5612732c |
return ret;
|
15850fc6 |
root = engine->root[0]; |
5612732c |
|
e8ae4fae |
while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) { |
4048c4f6 |
line++;
cli_chomp(buffer);
pt = strchr(buffer, '=');
if(!pt) {
cli_errmsg("Malformed pattern line %d\n", line);
ret = CL_EMALFDB;
break;
}
start = buffer;
*pt++ = 0; |
ee039e40 |
|
15850fc6 |
if(engine->ignored && cli_chkign(engine->ignored, dbname, line, start)) |
ed9753e9 |
continue;
|
4048c4f6 |
if(*pt == '=') continue; |
ee039e40 |
|
677fc4ba |
if((ret = cli_parse_add(root, start, pt, 0, 0, NULL, 0, NULL, options))) { |
b68d11d2 |
ret = CL_EMALFDB;
break;
} |
ed9753e9 |
sigs++; |
b68d11d2 |
}
if(!line) {
cli_errmsg("Empty database file\n");
return CL_EMALFDB;
}
if(ret) {
cli_errmsg("Problem parsing database at line %d\n", line);
return ret;
}
if(signo) |
ed9753e9 |
*signo += sigs; |
b68d11d2 |
|
8d3aca30 |
return CL_SUCCESS; |
b68d11d2 |
}
|
15850fc6 |
static int cli_loadwdb(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio) |
3da4dd4c |
{
int ret = 0;
|
ec481027 |
|
15850fc6 |
if(!(engine->dconf->phishing & PHISHING_CONF_ENGINE)) |
692bda68 |
return CL_SUCCESS;
|
15850fc6 |
if(!engine->whitelist_matcher) {
if((ret = init_whitelist(engine))) { |
ec481027 |
return ret; |
3da4dd4c |
} |
ec481027 |
} |
3da4dd4c |
|
03527bee |
if((ret = load_regex_matcher(engine->whitelist_matcher, fs, NULL, options, 1, dbio))) { |
ec481027 |
return ret;
} |
3da4dd4c |
|
ec481027 |
return CL_SUCCESS; |
3da4dd4c |
}
|
03527bee |
static int cli_loadpdb(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio) |
3da4dd4c |
{
int ret = 0;
|
ec481027 |
|
15850fc6 |
if(!(engine->dconf->phishing & PHISHING_CONF_ENGINE)) |
692bda68 |
return CL_SUCCESS;
|
15850fc6 |
if(!engine->domainlist_matcher) {
if((ret = init_domainlist(engine))) { |
ec481027 |
return ret; |
3da4dd4c |
} |
ec481027 |
} |
3da4dd4c |
|
03527bee |
if((ret = load_regex_matcher(engine->domainlist_matcher, fs, signo, options, 0, dbio))) { |
ec481027 |
return ret;
}
return CL_SUCCESS; |
3da4dd4c |
} |
ec481027 |
|
fea1b9bb |
static int cli_checkoffset(const char *offset, unsigned int type)
{
unsigned int foo;
const char *pt = offset;
if(isdigit(*offset)) {
while(*pt++)
if(!strchr("0123456789,", *pt))
return 1;
return 0;
}
if(!strncmp(offset, "EOF-", 4))
return 0;
if((type == 1 || type == 6) && (!strncmp(offset, "EP+", 3) || !strncmp(offset, "EP-", 3) || (sscanf(offset, "SL+%u", &foo) == 1) || (sscanf(offset, "S%u+%u", &foo, &foo) == 2)))
return 0;
return 1;
}
|
e4e8366f |
#define NDB_TOKENS 6 |
15850fc6 |
static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned short sdb, unsigned int options, struct cli_dbio *dbio, const char *dbname) |
b68d11d2 |
{ |
72fb25ea |
const char *tokens[NDB_TOKENS + 1]; |
e4e8366f |
char buffer[FILEBUFF];
const char *sig, *virname, *offset, *pt; |
5612732c |
struct cli_matcher *root; |
72fb25ea |
int line = 0, sigs = 0, ret = 0, tokens_count; |
b68d11d2 |
unsigned short target; |
9f8098c0 |
unsigned int phish = options & CL_DB_PHISHING; |
b68d11d2 |
|
15850fc6 |
if((ret = cli_initroots(engine, options))) |
5612732c |
return ret; |
b68d11d2 |
|
e8ae4fae |
while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) { |
b68d11d2 |
line++; |
7afdc309 |
if(!strncmp(buffer, "Exploit.JPEG.Comment", 20)) /* temporary */
continue;
|
9f8098c0 |
if(!phish) |
d6449522 |
if(!strncmp(buffer, "HTML.Phishing", 13) || !strncmp(buffer, "Email.Phishing", 14))
continue;
|
b68d11d2 |
cli_chomp(buffer);
|
72fb25ea |
tokens_count = cli_strtokenize(buffer, ':', NDB_TOKENS + 1, tokens);
/* FIXME: re-enable after fixing invalid sig @ main.ndb:53467 */
if(tokens_count < 4 /*|| tokens_count > 6*/) { |
b68d11d2 |
ret = CL_EMALFDB;
break;
}
|
72fb25ea |
virname = tokens[0];
|
15850fc6 |
if(engine->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)))
if(cli_chkpua(virname, engine->pua_cats, options)) |
b023c36d |
continue;
|
15850fc6 |
if(engine->ignored && cli_chkign(engine->ignored, dbname, line, virname)) |
ed9753e9 |
continue;
|
72fb25ea |
if(tokens_count > 4) { /* min version */
pt = tokens[4]; |
95083a4f |
if(!isdigit(*pt)) {
ret = CL_EMALFDB;
break;
}
|
53721687 |
if((unsigned int) atoi(pt) > cl_retflevel()) { |
38d1d109 |
cli_dbgmsg("Signature for %s not loaded (required f-level: %d)\n", virname, atoi(pt)); |
95083a4f |
continue;
}
|
72fb25ea |
if(tokens_count == 6) { /* max version */
pt = tokens[5]; |
555c5390 |
if(!isdigit(*pt)) {
ret = CL_EMALFDB;
break;
}
|
53721687 |
if((unsigned int) atoi(pt) < cl_retflevel()) { |
555c5390 |
continue;
}
} |
95083a4f |
}
|
e4e8366f |
if(!(pt = tokens[1]) || !isdigit(*pt)) { |
b68d11d2 |
ret = CL_EMALFDB;
break;
}
target = (unsigned short) atoi(pt);
|
4addba22 |
if(target >= CLI_MTARGETS) { |
5612732c |
cli_dbgmsg("Not supported target type in signature for %s\n", virname);
continue;
}
|
15850fc6 |
root = engine->root[target]; |
5612732c |
|
72fb25ea |
offset = tokens[2];
if(!strcmp(offset, "*")) |
7ec67e94 |
offset = NULL; |
b68d11d2 |
|
fea1b9bb |
if(offset && cli_checkoffset(offset, target)) {
cli_errmsg("Incorrect offset '%s' for signature type-%u\n", offset, target);
ret = CL_EMALFDB;
break;
}
|
72fb25ea |
sig = tokens[3]; |
b68d11d2 |
|
677fc4ba |
if((ret = cli_parse_add(root, virname, sig, 0, 0, offset, target, NULL, options))) { |
4048c4f6 |
ret = CL_EMALFDB;
break;
} |
ed9753e9 |
sigs++; |
ee039e40 |
}
|
4048c4f6 |
if(!line) {
cli_errmsg("Empty database file\n");
return CL_EMALFDB;
} |
8139fd99 |
|
4048c4f6 |
if(ret) { |
b68d11d2 |
cli_errmsg("Problem parsing database at line %d\n", line); |
8139fd99 |
return ret;
}
|
3805ebcb |
if(signo) |
95083a4f |
*signo += sigs; |
4048c4f6 |
|
15850fc6 |
if(sdb && sigs && !engine->sdb) {
engine->sdb = 1; |
555c5390 |
cli_dbgmsg("*** Self protection mechanism activated.\n");
}
|
8d3aca30 |
return CL_SUCCESS; |
4048c4f6 |
}
|
677fc4ba |
struct lsig_attrib {
const char *name;
unsigned int type;
void **pt;
};
/* TODO: rework this */
static int lsigattribs(char *attribs, struct cli_lsig_tdb *tdb)
{
struct lsig_attrib attrtab[] = {
#define ATTRIB_TOKENS 2
{ "Target", CLI_TDB_UINT, (void **) &tdb->target },
{ "Engine", CLI_TDB_RANGE, (void **) &tdb->engine },
/*
{ "NoS", CLI_TDB_RANGE, (void **) &tdb->nos },
{ "EP", CLI_TDB_RANGE, (void **) &tdb->ep },
{ "SectOff", CLI_TDB_RANGE2, (void **) &tdb->sectoff },
{ "SectRVA", CLI_TDB_RANGE2, (void **) &tdb->sectrva },
{ "SectVSZ", CLI_TDB_RANGE2, (void **) &tdb->sectvsz },
{ "SectRAW", CLI_TDB_RANGE2, (void **) &tdb->sectraw },
{ "SectRSZ", CLI_TDB_RANGE2, (void **) &tdb->sectrsz },
{ "SectURVA", CLI_TDB_RANGE2, (void **) &tdb->secturva },
{ "SectUVSZ", CLI_TDB_RANGE2, (void **) &tdb->sectuvsz },
{ "SectURAW", CLI_TDB_RANGE2, (void **) &tdb->secturaw },
{ "SectURSZ", CLI_TDB_RANGE2, (void **) &tdb->sectursz },
*/
{ NULL, 0, NULL, }
};
struct lsig_attrib *apt;
char *tokens[ATTRIB_TOKENS], *pt, *pt2; |
72fb25ea |
unsigned int v1, v2, v3, i, j, tokens_count; |
677fc4ba |
uint32_t cnt, off[ATTRIB_TOKENS];
|
72fb25ea |
tokens_count = cli_strtokenize(attribs, ',', ATTRIB_TOKENS, (const char **) tokens); |
677fc4ba |
|
72fb25ea |
for(i = 0; i < tokens_count; i++) { |
677fc4ba |
if(!(pt = strchr(tokens[i], ':'))) {
cli_errmsg("lsigattribs: Incorrect format of attribute '%s'\n", tokens[i]);
return -1;
}
*pt++ = 0;
apt = NULL;
for(j = 0; attrtab[j].name; j++) {
if(!strcmp(attrtab[j].name, tokens[i])) {
apt = &attrtab[j];
break;
}
}
if(!apt) {
cli_dbgmsg("lsigattribs: Unknown attribute name '%s'\n", tokens[i]);
continue;
}
switch(apt->type) {
case CLI_TDB_UINT:
off[i] = cnt = tdb->cnt[CLI_TDB_UINT]++; |
47d40feb |
tdb->val = (uint32_t *) mpool_realloc2(tdb->mempool, tdb->val, tdb->cnt[CLI_TDB_UINT] * sizeof(uint32_t)); |
677fc4ba |
if(!tdb->val) {
tdb->cnt[CLI_TDB_UINT] = 0;
return -1;
}
tdb->val[cnt] = atoi(pt);
break;
case CLI_TDB_RANGE:
if(!(pt2 = strchr(pt, '-'))) {
cli_errmsg("lsigattribs: Incorrect parameters in '%s'\n", tokens[i]);
return -1;
}
*pt2++ = 0;
off[i] = cnt = tdb->cnt[CLI_TDB_RANGE];
tdb->cnt[CLI_TDB_RANGE] += 2; |
47d40feb |
tdb->range = (uint32_t *) mpool_realloc2(tdb->mempool, tdb->range, tdb->cnt[CLI_TDB_RANGE] * sizeof(uint32_t)); |
677fc4ba |
if(!tdb->range) {
tdb->cnt[CLI_TDB_RANGE] = 0;
return -1;
}
tdb->range[cnt] = atoi(pt);
tdb->range[cnt + 1] = atoi(pt2);
break;
case CLI_TDB_RANGE2:
if(!strchr(pt, '-') || !strchr(pt, '.')) {
cli_errmsg("lsigattribs: Incorrect parameters in '%s'\n", tokens[i]);
return -1;
}
off[i] = cnt = tdb->cnt[CLI_TDB_RANGE];
tdb->cnt[CLI_TDB_RANGE] += 3; |
47d40feb |
tdb->range = (uint32_t *) mpool_realloc2(tdb->mempool, tdb->range, tdb->cnt[CLI_TDB_RANGE] * sizeof(uint32_t)); |
677fc4ba |
if(!tdb->range) {
tdb->cnt[CLI_TDB_RANGE] = 0;
return -1;
}
if(sscanf(pt, "%u.%u-%u", &v1, &v2, &v3) != 3) {
cli_errmsg("lsigattribs: Can't parse parameters in '%s'\n", tokens[i]);
return -1;
}
tdb->range[cnt] = (uint32_t) v1;
tdb->range[cnt + 1] = (uint32_t) v2;
tdb->range[cnt + 2] = (uint32_t) v3;
break;
case CLI_TDB_STR:
off[i] = cnt = tdb->cnt[CLI_TDB_STR];
tdb->cnt[CLI_TDB_STR] += strlen(pt) + 1; |
47d40feb |
tdb->str = (char *) mpool_realloc2(tdb->mempool, tdb->str, tdb->cnt[CLI_TDB_STR] * sizeof(char)); |
677fc4ba |
if(!tdb->str) {
cli_errmsg("lsigattribs: Can't allocate memory for tdb->str\n");
return -1;
}
memcpy(&tdb->str[cnt], pt, strlen(pt));
tdb->str[tdb->cnt[CLI_TDB_STR] - 1] = 0;
break;
}
}
if(!i) {
cli_errmsg("lsigattribs: Empty TDB\n");
return -1;
}
|
72fb25ea |
for(i = 0; i < tokens_count; i++) { |
677fc4ba |
for(j = 0; attrtab[j].name; j++) {
if(!strcmp(attrtab[j].name, tokens[i])) {
apt = &attrtab[j];
break;
}
} |
c9157be3 |
if(!apt)
continue; |
677fc4ba |
switch(apt->type) {
case CLI_TDB_UINT:
*apt->pt = (uint32_t *) &tdb->val[off[i]];
break;
case CLI_TDB_RANGE:
case CLI_TDB_RANGE2:
*apt->pt = (uint32_t *) &tdb->range[off[i]];
break;
case CLI_TDB_STR:
*apt->pt = (char *) &tdb->str[off[i]];
break;
}
}
return 0;
}
|
0d9dbdef |
#define FREE_TDB(x) do { \
if(x.cnt[CLI_TDB_UINT]) \ |
47d40feb |
mpool_free(x.mempool, x.val); \ |
0d9dbdef |
if(x.cnt[CLI_TDB_RANGE]) \ |
47d40feb |
mpool_free(x.mempool, x.range); \ |
0d9dbdef |
if(x.cnt[CLI_TDB_STR]) \ |
47d40feb |
mpool_free(x.mempool, x.str); \ |
0d9dbdef |
} while(0); |
677fc4ba |
#define LDB_TOKENS 67 |
15850fc6 |
static int cli_loadldb(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, const char *dbname) |
677fc4ba |
{
char *tokens[LDB_TOKENS]; |
4367454d |
char buffer[CLI_DEFAULT_LSIG_BUFSIZE + 1], *pt; |
677fc4ba |
const char *sig, *virname, *offset, *logic;
struct cli_matcher *root;
unsigned int line = 0, sigs = 0;
unsigned short target = 0;
struct cli_ac_lsig **newtable, *lsig;
uint32_t lsigid[2]; |
72fb25ea |
int ret = CL_SUCCESS, i, subsigs, tokens_count; |
677fc4ba |
struct cli_lsig_tdb tdb;
|
15850fc6 |
if((ret = cli_initroots(engine, options))) |
677fc4ba |
return ret;
|
4367454d |
while(cli_dbgets(buffer, sizeof(buffer), fs, dbio)) { |
677fc4ba |
line++;
sigs++;
cli_chomp(buffer);
|
72fb25ea |
tokens_count = cli_strtokenize(buffer, ';', LDB_TOKENS, (const char **) tokens);
if(tokens_count < 4) { |
677fc4ba |
ret = CL_EMALFDB;
break;
}
|
72fb25ea |
virname = tokens[0];
logic = tokens[2];
|
15850fc6 |
if(engine->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)))
if(cli_chkpua(virname, engine->pua_cats, options)) |
b023c36d |
continue;
|
15850fc6 |
if(engine->ignored && cli_chkign(engine->ignored, dbname, line, virname)) |
677fc4ba |
continue;
|
ee8bd2fb |
subsigs = cli_ac_chklsig(logic, logic + strlen(logic), NULL, NULL, NULL, 1); |
677fc4ba |
if(subsigs == -1) {
ret = CL_EMALFDB;
break;
}
subsigs++;
if(subsigs > 64) {
cli_errmsg("cli_loadldb: Broken logical expression or too many subsignatures\n");
ret = CL_EMALFDB;
break;
}
/* TDB */
memset(&tdb, 0, sizeof(tdb)); |
a963dd92 |
#ifdef USE_MPOOL |
15850fc6 |
tdb.mempool = engine->mempool; |
1e2969a4 |
#endif |
677fc4ba |
if(lsigattribs(tokens[1], &tdb) == -1) {
FREE_TDB(tdb);
ret = CL_EMALFDB;
break;
}
if(tdb.engine) {
if(tdb.engine[0] > cl_retflevel()) {
cli_dbgmsg("cli_loadldb: Signature for %s not loaded (required f-level: %u)\n", virname, tdb.engine[0]);
FREE_TDB(tdb);
sigs--;
continue;
} else if(tdb.engine[1] < cl_retflevel()) {
FREE_TDB(tdb);
sigs--;
continue;
}
}
if(!tdb.target) {
cli_errmsg("cli_loadldb: No target specified in TDB\n");
FREE_TDB(tdb);
ret = CL_EMALFDB;
break;
} else if(tdb.target[0] >= CLI_MTARGETS) {
cli_dbgmsg("cli_loadldb: Not supported target type in logical signature for %s\n", virname);
FREE_TDB(tdb);
sigs--;
continue;
}
|
15850fc6 |
root = engine->root[tdb.target[0]]; |
677fc4ba |
|
47d40feb |
lsig = (struct cli_ac_lsig *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_ac_lsig)); |
677fc4ba |
if(!lsig) {
cli_errmsg("cli_loadldb: Can't allocate memory for lsig\n");
FREE_TDB(tdb);
ret = CL_EMEM;
break;
} |
d6e1ef16 |
|
47d40feb |
lsig->logic = cli_mpool_strdup(engine->mempool, logic); |
677fc4ba |
if(!lsig->logic) {
cli_errmsg("cli_loadldb: Can't allocate memory for lsig->logic\n");
FREE_TDB(tdb);
ret = CL_EMEM; |
47d40feb |
mpool_free(engine->mempool, lsig); |
677fc4ba |
break;
}
lsigid[0] = lsig->id = root->ac_lsigs;
memcpy(&lsig->tdb, &tdb, sizeof(tdb));
root->ac_lsigs++; |
47d40feb |
newtable = (struct cli_ac_lsig **) mpool_realloc(engine->mempool, root->ac_lsigtable, root->ac_lsigs * sizeof(struct cli_ac_lsig *)); |
677fc4ba |
if(!newtable) {
root->ac_lsigs--;
cli_errmsg("cli_loadldb: Can't realloc root->ac_lsigtable\n");
FREE_TDB(tdb); |
47d40feb |
mpool_free(engine->mempool, lsig); |
677fc4ba |
ret = CL_EMEM;
break;
}
newtable[root->ac_lsigs - 1] = lsig;
root->ac_lsigtable = newtable;
for(i = 0; i < subsigs; i++) { |
72fb25ea |
if(i >= tokens_count) { |
677fc4ba |
cli_errmsg("cli_loadldb: Missing subsignature id %u\n", i);
ret = CL_EMALFDB;
break;
}
lsigid[1] = i;
sig = tokens[3 + i];
if((pt = strchr(tokens[3 + i], ':'))) {
*pt = 0;
sig = ++pt;
offset = tokens[3 + i]; |
c7aeeb46 |
if(!strcmp(offset, "*"))
offset = NULL; |
677fc4ba |
} else {
offset = NULL;
sig = tokens[3 + i];
}
|
fea1b9bb |
if(offset && cli_checkoffset(offset, tdb.target[0])) {
cli_errmsg("Incorrect offset '%s' in subsignature id %u for signature type-%u\n", offset, i, tdb.target[0]);
ret = CL_EMALFDB;
break;
}
|
677fc4ba |
if((ret = cli_parse_add(root, virname, sig, 0, 0, offset, target, lsigid, options))) {
ret = CL_EMALFDB;
break;
}
}
if(ret)
break;
}
if(!line) {
cli_errmsg("Empty database file\n");
return CL_EMALFDB;
}
if(ret) {
cli_errmsg("Problem parsing database at line %u\n", line);
return ret;
}
if(signo)
*signo += sigs;
return CL_SUCCESS;
}
|
72fb25ea |
#define FTM_TOKENS 8 |
15850fc6 |
static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options, unsigned int internal, struct cli_dbio *dbio) |
7021b545 |
{ |
72fb25ea |
const char *tokens[FTM_TOKENS + 1], *pt; |
7021b545 |
char buffer[FILEBUFF]; |
72fb25ea |
unsigned int line = 0, sigs = 0, tokens_count; |
7021b545 |
struct cli_ftype *new; |
6038397e |
cli_file_t rtype, type; |
7021b545 |
int ret;
|
15850fc6 |
if((ret = cli_initroots(engine, options))) |
7021b545 |
return ret;
while(1) {
if(internal) {
if(!ftypes_int[line])
break;
strncpy(buffer, ftypes_int[line], sizeof(buffer)); |
72ce4b70 |
buffer[sizeof(buffer)-1]='\0'; |
7021b545 |
} else { |
e8ae4fae |
if(!cli_dbgets(buffer, FILEBUFF, fs, dbio)) |
7021b545 |
break;
cli_chomp(buffer);
}
line++; |
72fb25ea |
tokens_count = cli_strtokenize(buffer, ':', FTM_TOKENS + 1, tokens); |
7021b545 |
|
72fb25ea |
if(tokens_count < 6 || tokens_count > 8) { |
7021b545 |
ret = CL_EMALFDB;
break;
}
|
72fb25ea |
if(tokens_count > 6) { /* min version */
pt = tokens[6]; |
6038397e |
if(!cli_isnumber(pt)) {
ret = CL_EMALFDB;
break;
}
if((unsigned int) atoi(pt) > cl_retflevel()) {
cli_dbgmsg("cli_loadftm: File type signature for %s not loaded (required f-level: %u)\n", tokens[3], atoi(pt));
continue;
} |
72fb25ea |
if(tokens_count == 8) { /* max version */
pt = tokens[7]; |
6038397e |
if(!cli_isnumber(pt)) {
ret = CL_EMALFDB;
break;
}
if((unsigned int) atoi(pt) < cl_retflevel())
continue;
}
}
rtype = cli_ftcode(tokens[4]);
type = cli_ftcode(tokens[5]);
if(rtype == CL_TYPE_ERROR || type == CL_TYPE_ERROR) { |
7021b545 |
ret = CL_EMALFDB;
break;
}
|
6038397e |
if(atoi(tokens[0]) == 1) { /* A-C */ |
15850fc6 |
if((ret = cli_parse_add(engine->root[0], tokens[3], tokens[2], rtype, type, strcmp(tokens[1], "*") ? tokens[1] : NULL, 0, NULL, options))) |
7021b545 |
break;
|
6038397e |
} else if(atoi(tokens[0]) == 0) { /* memcmp() */ |
47d40feb |
new = (struct cli_ftype *) mpool_malloc(engine->mempool, sizeof(struct cli_ftype)); |
7021b545 |
if(!new) {
ret = CL_EMEM;
break;
}
new->type = type; |
6038397e |
new->offset = atoi(tokens[1]); |
47d40feb |
new->magic = (unsigned char *) cli_mpool_hex2str(engine->mempool, tokens[2]); |
7021b545 |
if(!new->magic) { |
6038397e |
cli_errmsg("cli_loadftm: Can't decode the hex string\n"); |
7021b545 |
ret = CL_EMALFDB; |
47d40feb |
mpool_free(engine->mempool, new); |
7021b545 |
break;
} |
6038397e |
new->length = strlen(tokens[2]) / 2; |
47d40feb |
new->tname = cli_mpool_strdup(engine->mempool, tokens[3]); |
7021b545 |
if(!new->tname) { |
47d40feb |
mpool_free(engine->mempool, new->magic);
mpool_free(engine->mempool, new); |
7021b545 |
ret = CL_EMEM;
break;
} |
15850fc6 |
new->next = engine->ftypes;
engine->ftypes = new; |
6038397e |
} else {
cli_dbgmsg("cli_loadftm: Unsupported mode %u\n", atoi(tokens[0]));
continue; |
7021b545 |
} |
6038397e |
sigs++; |
7021b545 |
}
|
6038397e |
if(ret) {
cli_errmsg("Problem parsing %s filetype database at line %u\n", internal ? "built-in" : "external", line);
return ret; |
7021b545 |
}
|
6038397e |
if(!sigs) {
cli_errmsg("Empty %s filetype database\n", internal ? "built-in" : "external");
return CL_EMALFDB; |
7021b545 |
}
|
6038397e |
cli_dbgmsg("Loaded %u filetype definitions\n", sigs); |
7021b545 |
return CL_SUCCESS;
}
|
d6e1ef16 |
#define IGN_TOKENS 3 |
15850fc6 |
static int cli_loadign(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio) |
ed9753e9 |
{ |
72fb25ea |
const char *tokens[IGN_TOKENS + 1]; |
b9b47784 |
char buffer[FILEBUFF]; |
72fb25ea |
unsigned int line = 0, tokens_count; |
6c0d1684 |
struct cli_ignsig *new; |
ac1b219c |
int ret = CL_SUCCESS; |
ed9753e9 |
|
15850fc6 |
if(!engine->ignored) {
engine->ignored = (struct cli_ignored *) cli_calloc(sizeof(struct cli_ignored), 1);
if(!engine->ignored || hashset_init(&engine->ignored->hs, 64, 50)) |
ed9753e9 |
return CL_EMEM;
}
|
e8ae4fae |
while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) { |
ed9753e9 |
line++;
cli_chomp(buffer); |
72fb25ea |
tokens_count = cli_strtokenize(buffer, ':', IGN_TOKENS + 1, tokens);
if(tokens_count != IGN_TOKENS) {
ret = CL_EMALFDB;
break;
} |
d6e1ef16 |
|
47d40feb |
new = (struct cli_ignsig *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_ignsig)); |
ed9753e9 |
if(!new) {
ret = CL_EMEM;
break;
}
|
47d40feb |
new->dbname = cli_mpool_strdup(engine->mempool, tokens[0]); |
d6e1ef16 |
|
0728972e |
if(!new->dbname) { |
47d40feb |
mpool_free(engine->mempool, new); |
ed9753e9 |
ret = CL_EMALFDB;
break;
}
|
d6e1ef16 |
new->line = atoi(tokens[1]); |
ed9753e9 |
|
15850fc6 |
if((ret = hashset_addkey(&engine->ignored->hs, new->line))) |
ed9753e9 |
break;
|
47d40feb |
new->signame = cli_mpool_strdup(engine->mempool, tokens[2]); |
0728972e |
if(!new->signame) { |
47d40feb |
mpool_free(engine->mempool, new->dbname);
mpool_free(engine->mempool, new); |
ed9753e9 |
ret = CL_EMALFDB;
break;
}
|
15850fc6 |
new->next = engine->ignored->list;
engine->ignored->list = new; |
ed9753e9 |
}
if(ret) {
cli_errmsg("cli_loadign: Problem parsing database at line %u\n", line);
return ret;
}
return CL_SUCCESS;
}
static void cli_freeign(struct cl_engine *engine)
{
struct cli_ignsig *pt;
struct cli_ignored *ignored;
if((ignored = engine->ignored)) {
while(ignored->list) {
pt = ignored->list;
ignored->list = ignored->list->next; |
47d40feb |
mpool_free(engine->mempool, pt->dbname);
mpool_free(engine->mempool, pt->signame);
mpool_free(engine->mempool,pt); |
ed9753e9 |
}
hashset_destroy(&ignored->hs);
free(engine->ignored);
engine->ignored = NULL;
}
}
|
0a3d4094 |
static int scomp(const void *a, const void *b)
{
return *(const uint32_t *)a - *(const uint32_t *)b;
}
|
3dad68eb |
#define MD5_HDB 0
#define MD5_MDB 1
#define MD5_FP 2 |
2b459819 |
|
15850fc6 |
static int cli_md5db_init(struct cl_engine *engine, unsigned int mode) |
2b459819 |
{
struct cli_matcher *bm = NULL;
int ret;
if(mode == MD5_HDB) { |
47d40feb |
bm = engine->md5_hdb = (struct cli_matcher *) mpool_calloc(engine->mempool, sizeof(struct cli_matcher), 1); |
2b459819 |
} else if(mode == MD5_MDB) { |
47d40feb |
bm = engine->md5_mdb = (struct cli_matcher *) mpool_calloc(engine->mempool, sizeof(struct cli_matcher), 1); |
2b459819 |
} else { |
47d40feb |
bm = engine->md5_fp = (struct cli_matcher *) mpool_calloc(engine->mempool, sizeof(struct cli_matcher), 1); |
2b459819 |
}
if(!bm)
return CL_EMEM; |
0728972e |
#ifdef USE_MPOOL |
15850fc6 |
bm->mempool = engine->mempool; |
0728972e |
#endif |
2b459819 |
if((ret = cli_bm_init(bm))) {
cli_errmsg("cli_md5db_init: Failed to initialize B-M\n");
return ret;
}
return CL_SUCCESS;
}
#define MD5_DB \
if(mode == MD5_HDB) \ |
15850fc6 |
db = engine->md5_hdb; \ |
2b459819 |
else if(mode == MD5_MDB) \ |
15850fc6 |
db = engine->md5_mdb; \ |
2b459819 |
else \ |
15850fc6 |
db = engine->md5_fp; |
2b459819 |
|
a72b7d2e |
#define MD5_TOKENS 3 |
15850fc6 |
static int cli_loadmd5(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int mode, unsigned int options, struct cli_dbio *dbio, const char *dbname) |
4048c4f6 |
{ |
72fb25ea |
const char *tokens[MD5_TOKENS + 1]; |
a72b7d2e |
char buffer[FILEBUFF];
const char *pt; |
0a3d4094 |
int ret = CL_SUCCESS; |
72fb25ea |
unsigned int size_field = 1, md5_field = 0, line = 0, sigs = 0, tokens_count; |
2b459819 |
uint32_t size;
struct cli_bm_patt *new;
struct cli_matcher *db = NULL; |
e3aaff8e |
|
4048c4f6 |
|
3dad68eb |
if(mode == MD5_MDB) {
size_field = 0;
md5_field = 1; |
8ce42de3 |
}
|
e8ae4fae |
while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) { |
e3aaff8e |
line++;
cli_chomp(buffer); |
72fb25ea |
tokens_count = cli_strtokenize(buffer, ':', MD5_TOKENS + 1, tokens);
if(tokens_count != MD5_TOKENS) { |
b023c36d |
ret = CL_EMALFDB;
break;
}
|
72fb25ea |
pt = tokens[2]; /* virname */ |
15850fc6 |
if(engine->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)))
if(cli_chkpua(pt, engine->pua_cats, options)) |
b023c36d |
continue;
|
15850fc6 |
if(engine->ignored && cli_chkign(engine->ignored, dbname, line, pt)) |
b023c36d |
continue;
|
47d40feb |
new = (struct cli_bm_patt *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_bm_patt)); |
4048c4f6 |
if(!new) {
ret = CL_EMEM;
break; |
e3aaff8e |
}
|
72fb25ea |
pt = tokens[md5_field]; /* md5 */ |
47d40feb |
if(strlen(pt) != 32 || !(new->pattern = (unsigned char *) cli_mpool_hex2str(engine->mempool, pt))) { |
0728972e |
cli_errmsg("cli_loadmd5: Malformed MD5 string at line %u\n", line); |
47d40feb |
mpool_free(engine->mempool, new); |
0728972e |
ret = CL_EMALFDB;
break;
} |
2b459819 |
new->length = 16; |
e3aaff8e |
|
72fb25ea |
size = atoi(tokens[size_field]); |
022a21cf |
|
47d40feb |
new->virname = cli_mpool_virname(engine->mempool, (char *) tokens[2], options & CL_DB_OFFICIAL); |
0728972e |
if(!new->virname) { |
47d40feb |
mpool_free(engine->mempool, new->pattern);
mpool_free(engine->mempool, new); |
4048c4f6 |
ret = CL_EMALFDB;
break; |
e3aaff8e |
} |
4048c4f6 |
|
2b459819 |
MD5_DB;
if(!db && (ret = cli_md5db_init(engine, mode))) { |
47d40feb |
mpool_free(engine->mempool, new->pattern);
mpool_free(engine->mempool, new->virname);
mpool_free(engine->mempool, new); |
2b459819 |
break;
} else {
MD5_DB;
} |
0a3d4094 |
|
2b459819 |
if((ret = cli_bm_addpatt(db, new))) {
cli_errmsg("cli_loadmd5: Error adding BM pattern\n"); |
47d40feb |
mpool_free(engine->mempool, new->pattern);
mpool_free(engine->mempool, new->virname);
mpool_free(engine->mempool, new); |
2b459819 |
break;
} |
0a3d4094 |
|
2b459819 |
if(mode == MD5_MDB) { /* section MD5 */ |
c3671221 |
if(!db->md5_sizes_hs.capacity) { |
fe389c84 |
hashset_init(&db->md5_sizes_hs, 65536, 80); |
8000d078 |
} |
c3671221 |
hashset_addkey(&db->md5_sizes_hs, size); |
c09d6c19 |
} |
ed9753e9 |
sigs++; |
e3aaff8e |
}
|
4048c4f6 |
if(!line) { |
3dad68eb |
cli_errmsg("cli_loadmd5: Empty database file\n"); |
4048c4f6 |
return CL_EMALFDB;
} |
e3aaff8e |
|
4048c4f6 |
if(ret) { |
3dad68eb |
cli_errmsg("cli_loadmd5: Problem parsing database at line %u\n", line); |
4048c4f6 |
return ret;
} |
ee039e40 |
|
3805ebcb |
if(signo) |
ed9753e9 |
*signo += sigs; |
3365db23 |
|
8d3aca30 |
return CL_SUCCESS; |
e3aaff8e |
}
|
d6e1ef16 |
#define MD_TOKENS 9 |
15850fc6 |
static int cli_loadmd(FILE *fs, struct cl_engine *engine, unsigned int *signo, int type, unsigned int options, struct cli_dbio *dbio, const char *dbname) |
e5916a51 |
{ |
72fb25ea |
const char *tokens[MD_TOKENS + 1]; |
b9b47784 |
char buffer[FILEBUFF]; |
72fb25ea |
unsigned int line = 0, sigs = 0, tokens_count; |
ac1b219c |
int ret = CL_SUCCESS, crc; |
a62ae54f |
struct cli_meta_node *new; |
e5916a51 |
|
e8ae4fae |
while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) { |
e5916a51 |
line++; |
ed9753e9 |
if(buffer[0] == '#') |
e5916a51 |
continue;
cli_chomp(buffer); |
72fb25ea |
tokens_count = cli_strtokenize(buffer, ':', MD_TOKENS + 1, tokens);
if(tokens_count != MD_TOKENS) {
ret = CL_EMALFDB;
break;
} |
e5916a51 |
|
47d40feb |
new = (struct cli_meta_node *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_meta_node)); |
e5916a51 |
if(!new) {
ret = CL_EMEM;
break;
}
|
47d40feb |
new->virname = cli_mpool_virname(engine->mempool, (char *)tokens[0], options & CL_DB_OFFICIAL); |
0728972e |
if(!new->virname) { |
47d40feb |
mpool_free(engine->mempool, new); |
b5513f8d |
ret = CL_EMEM; |
e5916a51 |
break;
}
|
15850fc6 |
if(engine->ignored && cli_chkign(engine->ignored, dbname, line, new->virname)) { |
47d40feb |
mpool_free(engine->mempool, new->virname);
mpool_free(engine->mempool, new); |
ed9753e9 |
continue;
}
|
d6e1ef16 |
new->encrypted = atoi(tokens[1]); |
47d40feb |
new->filename = cli_mpool_strdup(engine->mempool, tokens[2]); |
0728972e |
if(!new->filename) { |
47d40feb |
mpool_free(engine->mempool, new->virname);
mpool_free(engine->mempool, new); |
e5916a51 |
ret = CL_EMALFDB;
break;
} else {
if(!strcmp(new->filename, "*")) { |
47d40feb |
mpool_free(engine->mempool, new->filename); |
e5916a51 |
new->filename = NULL;
}
}
|
d6e1ef16 |
if(!strcmp(tokens[3], "*"))
new->size = -1;
else
new->size = atoi(tokens[3]); |
e5916a51 |
|
d6e1ef16 |
if(!strcmp(tokens[4], "*"))
new->csize = -1;
else
new->csize = atoi(tokens[4]); |
e5916a51 |
|
d6e1ef16 |
if(!strcmp(tokens[5], "*")) {
new->crc32 = 0; |
e5916a51 |
} else { |
d6e1ef16 |
crc = cli_hex2num(tokens[5]);
if(crc == -1) {
ret = CL_EMALFDB;
break; |
e5916a51 |
} |
d6e1ef16 |
new->crc32 = (unsigned int) crc; |
e5916a51 |
}
|
d6e1ef16 |
if(!strcmp(tokens[6], "*"))
new->method = -1;
else
new->method = atoi(tokens[6]); |
e5916a51 |
|
d6e1ef16 |
if(!strcmp(tokens[7], "*"))
new->fileno = 0;
else
new->fileno = atoi(tokens[7]); |
19e2ac07 |
|
d6e1ef16 |
if(!strcmp(tokens[8], "*"))
new->maxdepth = 0;
else
new->maxdepth = atoi(tokens[8]); |
19e2ac07 |
|
a62ae54f |
if(type == 1) { |
15850fc6 |
new->next = engine->zip_mlist;
engine->zip_mlist = new; |
a62ae54f |
} else { |
15850fc6 |
new->next = engine->rar_mlist;
engine->rar_mlist = new; |
a62ae54f |
} |
ed9753e9 |
sigs++; |
e5916a51 |
}
if(!line) {
cli_errmsg("Empty database file\n");
return CL_EMALFDB;
}
if(ret) {
cli_errmsg("Problem parsing database at line %d\n", line);
return ret;
}
if(signo) |
ed9753e9 |
*signo += sigs; |
e5916a51 |
|
8d3aca30 |
return CL_SUCCESS; |
e5916a51 |
}
|
15850fc6 |
static int cli_loaddbdir(const char *dirname, struct cl_engine *engine, unsigned int *signo, unsigned int options); |
52c67b86 |
|
15850fc6 |
int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio) |
e3aaff8e |
{ |
056d95dc |
FILE *fs = NULL; |
f51e962f |
int ret = CL_SUCCESS; |
4efca56b |
uint8_t skipped = 0; |
ed9753e9 |
const char *dbname; |
f51e962f |
|
4048c4f6 |
|
e8ae4fae |
if(!dbio && (fs = fopen(filename, "rb")) == NULL) { |
f51e962f |
cli_errmsg("cli_load(): Can't open file %s\n", filename); |
4048c4f6 |
return CL_EOPEN;
}
|
ed9753e9 |
/*
#ifdef C_WINDOWS
if((dbname = strrchr(filename, '\\')))
#else
*/
if((dbname = strrchr(filename, '/')))
/*#endif */
dbname++;
else
dbname = filename; |
4048c4f6 |
|
ed9753e9 |
if(cli_strbcasestr(dbname, ".db")) { |
e8ae4fae |
ret = cli_loaddb(fs, engine, signo, options, dbio, dbname); |
ed9753e9 |
} else if(cli_strbcasestr(dbname, ".cvd")) { |
ac1b219c |
ret = cli_cvdload(fs, engine, signo, !strcmp(dbname, "daily.cvd"), options, 0); |
9d193ff2 |
|
ed9753e9 |
} else if(cli_strbcasestr(dbname, ".cld")) { |
ac1b219c |
ret = cli_cvdload(fs, engine, signo, !strcmp(dbname, "daily.cld"), options | CL_DB_CVDNOTMP, 1); |
4048c4f6 |
|
ed9753e9 |
} else if(cli_strbcasestr(dbname, ".hdb")) { |
e8ae4fae |
ret = cli_loadmd5(fs, engine, signo, MD5_HDB, options, dbio, dbname); |
db65451b |
|
ed9753e9 |
} else if(cli_strbcasestr(dbname, ".hdu")) { |
70edb085 |
if(options & CL_DB_PUA) |
b023c36d |
ret = cli_loadmd5(fs, engine, signo, MD5_HDB, options | CL_DB_PUA_MODE, dbio, dbname); |
70edb085 |
else
skipped = 1;
|
ed9753e9 |
} else if(cli_strbcasestr(dbname, ".fp")) { |
e8ae4fae |
ret = cli_loadmd5(fs, engine, signo, MD5_FP, options, dbio, dbname); |
4048c4f6 |
|
ed9753e9 |
} else if(cli_strbcasestr(dbname, ".mdb")) { |
e8ae4fae |
ret = cli_loadmd5(fs, engine, signo, MD5_MDB, options, dbio, dbname); |
c09d6c19 |
|
ed9753e9 |
} else if(cli_strbcasestr(dbname, ".mdu")) { |
70edb085 |
if(options & CL_DB_PUA) |
b023c36d |
ret = cli_loadmd5(fs, engine, signo, MD5_MDB, options | CL_DB_PUA_MODE, dbio, dbname); |
70edb085 |
else
skipped = 1;
|
ed9753e9 |
} else if(cli_strbcasestr(dbname, ".ndb")) { |
e8ae4fae |
ret = cli_loadndb(fs, engine, signo, 0, options, dbio, dbname); |
555c5390 |
|
ed9753e9 |
} else if(cli_strbcasestr(dbname, ".ndu")) { |
09eab32a |
if(!(options & CL_DB_PUA)) |
70edb085 |
skipped = 1;
else |
b023c36d |
ret = cli_loadndb(fs, engine, signo, 0, options | CL_DB_PUA_MODE, dbio, dbname); |
70edb085 |
|
677fc4ba |
} else if(cli_strbcasestr(filename, ".ldb")) {
ret = cli_loadldb(fs, engine, signo, options, dbio, dbname);
} else if(cli_strbcasestr(filename, ".ldu")) {
if(options & CL_DB_PUA) |
b023c36d |
ret = cli_loadldb(fs, engine, signo, options | CL_DB_PUA_MODE, dbio, dbname); |
677fc4ba |
else
skipped = 1;
|
ed9753e9 |
} else if(cli_strbcasestr(dbname, ".sdb")) { |
e8ae4fae |
ret = cli_loadndb(fs, engine, signo, 1, options, dbio, dbname); |
b68d11d2 |
|
ed9753e9 |
} else if(cli_strbcasestr(dbname, ".zmd")) { |
e8ae4fae |
ret = cli_loadmd(fs, engine, signo, 1, options, dbio, dbname); |
a62ae54f |
|
ed9753e9 |
} else if(cli_strbcasestr(dbname, ".rmd")) { |
e8ae4fae |
ret = cli_loadmd(fs, engine, signo, 2, options, dbio, dbname); |
e5916a51 |
|
ed9753e9 |
} else if(cli_strbcasestr(dbname, ".cfg")) { |
e8ae4fae |
ret = cli_dconf_load(fs, engine, options, dbio); |
bc93eda0 |
|
ed9753e9 |
} else if(cli_strbcasestr(dbname, ".wdb")) { |
056d95dc |
if(options & CL_DB_PHISHING_URLS) { |
e8ae4fae |
ret = cli_loadwdb(fs, engine, options, dbio); |
056d95dc |
} else |
7dec7955 |
skipped = 1; |
0810d861 |
} else if(cli_strbcasestr(dbname, ".pdb") || cli_strbcasestr(dbname, ".gdb")) { |
056d95dc |
if(options & CL_DB_PHISHING_URLS) { |
03527bee |
ret = cli_loadpdb(fs, engine, signo, options, dbio); |
056d95dc |
} else |
7dec7955 |
skipped = 1; |
6038397e |
} else if(cli_strbcasestr(dbname, ".ftm")) { |
e8ae4fae |
ret = cli_loadftm(fs, engine, options, 0, dbio); |
7021b545 |
|
ed9753e9 |
} else if(cli_strbcasestr(dbname, ".ign")) { |
e8ae4fae |
ret = cli_loadign(fs, engine, options, dbio); |
ed9753e9 |
|
4048c4f6 |
} else { |
f51e962f |
cli_dbgmsg("cli_load: unknown extension - assuming old database format\n"); |
e8ae4fae |
ret = cli_loaddb(fs, engine, signo, options, dbio, dbname); |
4048c4f6 |
}
|
4efca56b |
if(ret) { |
975ef8ce |
cli_errmsg("Can't load %s: %s\n", filename, cl_strerror(ret)); |
4efca56b |
} else {
if(skipped)
cli_dbgmsg("%s skipped\n", filename);
else
cli_dbgmsg("%s loaded\n", filename);
} |
4048c4f6 |
|
056d95dc |
if(fs)
fclose(fs);
|
4048c4f6 |
return ret; |
e3aaff8e |
}
|
15850fc6 |
static int cli_loaddbdir(const char *dirname, struct cl_engine *engine, unsigned int *signo, unsigned int options) |
e3aaff8e |
{
DIR *dd;
struct dirent *dent; |
72a1b240 |
#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2) |
88794204 |
union {
struct dirent d;
char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
} result; |
2bb229f6 |
#endif |
e3aaff8e |
char *dbfile; |
871177cd |
int ret = CL_EOPEN; |
e3aaff8e |
|
0eacacec |
cli_dbgmsg("Loading databases from %s\n", dirname); |
ed9753e9 |
dbfile = (char *) cli_malloc(strlen(dirname) + 20); |
0eacacec |
if(!dbfile)
return CL_EMEM; |
ed9753e9 |
/* try to load local.ign and daily.cvd/daily.ign first */
sprintf(dbfile, "%s/local.ign", dirname); |
e8ae4fae |
if(!access(dbfile, R_OK) && (ret = cli_load(dbfile, engine, signo, options, NULL))) { |
ed9753e9 |
free(dbfile);
return ret;
}
sprintf(dbfile, "%s/daily.cld", dirname);
if(access(dbfile, R_OK))
sprintf(dbfile, "%s/daily.cvd", dirname); |
e8ae4fae |
if(!access(dbfile, R_OK) && (ret = cli_load(dbfile, engine, signo, options, NULL))) { |
ed9753e9 |
free(dbfile);
return ret;
}
sprintf(dbfile, "%s/daily.ign", dirname); |
e8ae4fae |
if(!access(dbfile, R_OK) && (ret = cli_load(dbfile, engine, signo, options, NULL))) { |
ed9753e9 |
free(dbfile);
return ret;
}
|
816d66a8 |
/* try to load local.gdb next */
sprintf(dbfile, "%s/local.gdb", dirname);
if(!access(dbfile, R_OK) && (ret = cli_load(dbfile, engine, signo, options, NULL))) {
free(dbfile);
return ret;
}
|
ed9753e9 |
/* check for and load daily.cfg */ |
0eacacec |
sprintf(dbfile, "%s/daily.cfg", dirname); |
e8ae4fae |
if(!access(dbfile, R_OK) && (ret = cli_load(dbfile, engine, signo, options, NULL))) { |
ed9753e9 |
free(dbfile);
return ret; |
0eacacec |
}
free(dbfile);
|
e3aaff8e |
if((dd = opendir(dirname)) == NULL) { |
15e1a7cd |
cli_errmsg("cli_loaddbdir(): Can't open directory %s\n", dirname); |
e3aaff8e |
return CL_EOPEN;
}
|
72a1b240 |
#ifdef HAVE_READDIR_R_3 |
88794204 |
while(!readdir_r(dd, &result.d, &dent) && dent) { |
72a1b240 |
#elif defined(HAVE_READDIR_R_2) |
88794204 |
while((dent = (struct dirent *) readdir_r(dd, &result.d))) { |
72a1b240 |
#else |
e3aaff8e |
while((dent = readdir(dd))) { |
72a1b240 |
#endif |
6670d61d |
#if (!defined(C_INTERIX)) && (!defined(C_WINDOWS)) |
feeaa333 |
if(dent->d_ino)
#endif
{ |
ed9753e9 |
if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") && strcmp(dent->d_name, "daily.cvd") && strcmp(dent->d_name, "daily.cld") && strcmp(dent->d_name, "daily.ign") && strcmp(dent->d_name, "daily.cfg") && strcmp(dent->d_name, "local.ign") && CLI_DBEXT(dent->d_name)) { |
8139fd99 |
|
0eacacec |
dbfile = (char *) cli_malloc(strlen(dent->d_name) + strlen(dirname) + 2); |
e3aaff8e |
if(!dbfile) { |
15e1a7cd |
cli_dbgmsg("cli_loaddbdir(): dbfile == NULL\n"); |
e3aaff8e |
closedir(dd);
return CL_EMEM;
}
sprintf(dbfile, "%s/%s", dirname, dent->d_name); |
e8ae4fae |
ret = cli_load(dbfile, engine, signo, options, NULL); |
3dad68eb |
if(ret) { |
15e1a7cd |
cli_dbgmsg("cli_loaddbdir(): error loading database %s\n", dbfile); |
e3aaff8e |
free(dbfile);
closedir(dd);
return ret;
}
free(dbfile);
}
}
}
closedir(dd); |
871177cd |
if(ret == CL_EOPEN) |
d6898042 |
cli_errmsg("cli_loaddb(): No supported database files found in %s\n", dirname);
return ret; |
e3aaff8e |
}
|
2accc66f |
int cl_load(const char *path, struct cl_engine *engine, unsigned int *signo, unsigned int dboptions) |
04933acd |
{
struct stat sb; |
f7470773 |
int ret; |
04933acd |
|
15850fc6 |
if(!engine) { |
724b2bf7 |
cli_errmsg("cl_load: engine == NULL\n");
return CL_ENULLARG;
} |
04933acd |
|
d7c3f6e2 |
if(engine->dboptions & CL_DB_COMPILED) {
cli_errmsg("cl_load(): can't load new databases when engine is already compiled\n");
return CL_EARG;
}
|
04933acd |
if(stat(path, &sb) == -1) { |
ac1b219c |
cli_errmsg("cl_load(): Can't get status of %s\n", path); |
871177cd |
return CL_ESTAT; |
04933acd |
}
|
2accc66f |
if((dboptions & CL_DB_PHISHING_URLS) && !engine->phishcheck && (engine->dconf->phishing & PHISHING_CONF_ENGINE)) |
15850fc6 |
if((ret = phishing_init(engine))) |
724b2bf7 |
return ret; |
f7470773 |
|
d7c3f6e2 |
engine->dboptions |= dboptions; |
616bc3b9 |
|
f51e962f |
switch(sb.st_mode & S_IFMT) { |
04933acd |
case S_IFREG: |
2accc66f |
ret = cli_load(path, engine, signo, dboptions, NULL); |
bc93eda0 |
break; |
04933acd |
case S_IFDIR: |
2accc66f |
ret = cli_loaddbdir(path, engine, signo, dboptions); |
bc93eda0 |
break; |
04933acd |
default: |
bc93eda0 |
cli_errmsg("cl_load(%s): Not supported database file type\n", path); |
04933acd |
return CL_EOPEN;
} |
bc93eda0 |
return ret; |
04933acd |
}
|
4048c4f6 |
const char *cl_retdbdir(void)
{
return DATADIR;
}
|
e3aaff8e |
int cl_statinidir(const char *dirname, struct cl_stat *dbstat)
{
DIR *dd; |
2bb229f6 |
const struct dirent *dent; |
72a1b240 |
#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2) |
88794204 |
union {
struct dirent d;
char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
} result; |
2bb229f6 |
#endif |
e3aaff8e |
char *fname;
if(dbstat) { |
b5134815 |
dbstat->entries = 0; |
e3aaff8e |
dbstat->stattab = NULL; |
75ccac9f |
dbstat->statdname = NULL; |
6f38c939 |
dbstat->dir = cli_strdup(dirname); |
e3aaff8e |
} else {
cli_errmsg("cl_statdbdir(): Null argument passed.\n");
return CL_ENULLARG;
}
if((dd = opendir(dirname)) == NULL) {
cli_errmsg("cl_statdbdir(): Can't open directory %s\n", dirname); |
cd69cf20 |
cl_statfree(dbstat); |
e3aaff8e |
return CL_EOPEN;
}
cli_dbgmsg("Stat()ing files in %s\n", dirname);
|
72a1b240 |
#ifdef HAVE_READDIR_R_3 |
88794204 |
while(!readdir_r(dd, &result.d, &dent) && dent) { |
72a1b240 |
#elif defined(HAVE_READDIR_R_2) |
88794204 |
while((dent = (struct dirent *) readdir_r(dd, &result.d))) { |
72a1b240 |
#else |
e3aaff8e |
while((dent = readdir(dd))) { |
72a1b240 |
#endif |
6670d61d |
#if (!defined(C_INTERIX)) && (!defined(C_WINDOWS)) |
feeaa333 |
if(dent->d_ino)
#endif
{ |
3dad68eb |
if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") && CLI_DBEXT(dent->d_name)) { |
b5134815 |
dbstat->entries++; |
84fd5a61 |
dbstat->stattab = (struct stat *) cli_realloc2(dbstat->stattab, dbstat->entries * sizeof(struct stat)); |
cd69cf20 |
if(!dbstat->stattab) {
cl_statfree(dbstat);
closedir(dd);
return CL_EMEM;
}
|
e871e527 |
#if defined(C_INTERIX) || defined(C_OS2) |
84fd5a61 |
dbstat->statdname = (char **) cli_realloc2(dbstat->statdname, dbstat->entries * sizeof(char *)); |
cd69cf20 |
if(!dbstat->statdname) {
cl_statfree(dbstat);
closedir(dd);
return CL_EMEM;
} |
75ccac9f |
#endif
|
0eacacec |
fname = cli_malloc(strlen(dirname) + strlen(dent->d_name) + 32); |
cd69cf20 |
if(!fname) {
cl_statfree(dbstat);
closedir(dd);
return CL_EMEM;
} |
9d193ff2 |
sprintf(fname, "%s/%s", dirname, dent->d_name); |
e871e527 |
#if defined(C_INTERIX) || defined(C_OS2) |
0eacacec |
dbstat->statdname[dbstat->entries - 1] = (char *) cli_malloc(strlen(dent->d_name) + 1); |
cd69cf20 |
if(!dbstat->statdname[dbstat->entries - 1]) {
cl_statfree(dbstat);
closedir(dd);
return CL_EMEM;
}
|
b5134815 |
strcpy(dbstat->statdname[dbstat->entries - 1], dent->d_name); |
75ccac9f |
#endif |
b5134815 |
stat(fname, &dbstat->stattab[dbstat->entries - 1]); |
e3aaff8e |
free(fname);
}
}
}
closedir(dd); |
8d3aca30 |
return CL_SUCCESS; |
e3aaff8e |
}
int cl_statchkdir(const struct cl_stat *dbstat)
{
DIR *dd;
struct dirent *dent; |
72a1b240 |
#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2) |
88794204 |
union {
struct dirent d;
char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
} result; |
2bb229f6 |
#endif |
e3aaff8e |
struct stat sb; |
53721687 |
unsigned int i, found; |
e3aaff8e |
char *fname;
if(!dbstat || !dbstat->dir) {
cli_errmsg("cl_statdbdir(): Null argument passed.\n");
return CL_ENULLARG;
}
if((dd = opendir(dbstat->dir)) == NULL) {
cli_errmsg("cl_statdbdir(): Can't open directory %s\n", dbstat->dir);
return CL_EOPEN;
}
cli_dbgmsg("Stat()ing files in %s\n", dbstat->dir);
|
72a1b240 |
#ifdef HAVE_READDIR_R_3 |
88794204 |
while(!readdir_r(dd, &result.d, &dent) && dent) { |
72a1b240 |
#elif defined(HAVE_READDIR_R_2) |
88794204 |
while((dent = (struct dirent *) readdir_r(dd, &result.d))) { |
72a1b240 |
#else |
e3aaff8e |
while((dent = readdir(dd))) { |
72a1b240 |
#endif |
6670d61d |
#if (!defined(C_INTERIX)) && (!defined(C_WINDOWS)) |
feeaa333 |
if(dent->d_ino)
#endif
{ |
3dad68eb |
if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") && CLI_DBEXT(dent->d_name)) { |
0eacacec |
fname = cli_malloc(strlen(dbstat->dir) + strlen(dent->d_name) + 32); |
cd69cf20 |
if(!fname) {
closedir(dd);
return CL_EMEM;
}
|
9d193ff2 |
sprintf(fname, "%s/%s", dbstat->dir, dent->d_name); |
e3aaff8e |
stat(fname, &sb);
free(fname);
found = 0; |
b5134815 |
for(i = 0; i < dbstat->entries; i++) |
e871e527 |
#if defined(C_INTERIX) || defined(C_OS2) |
75ccac9f |
if(!strcmp(dbstat->statdname[i], dent->d_name)) {
#else |
e3aaff8e |
if(dbstat->stattab[i].st_ino == sb.st_ino) { |
75ccac9f |
#endif |
e3aaff8e |
found = 1; |
e3f0de57 |
if(dbstat->stattab[i].st_mtime != sb.st_mtime) {
closedir(dd); |
e3aaff8e |
return 1; |
e3f0de57 |
} |
e3aaff8e |
}
|
e3f0de57 |
if(!found) {
closedir(dd); |
e3aaff8e |
return 1; |
e3f0de57 |
} |
e3aaff8e |
}
}
}
closedir(dd); |
8d3aca30 |
return CL_SUCCESS; |
e3aaff8e |
}
int cl_statfree(struct cl_stat *dbstat)
{
if(dbstat) { |
75ccac9f |
|
e871e527 |
#if defined(C_INTERIX) || defined(C_OS2) |
75ccac9f |
int i;
|
cd69cf20 |
if(dbstat->statdname) {
for(i = 0; i < dbstat->entries; i++) {
if(dbstat->statdname[i])
free(dbstat->statdname[i]);
dbstat->statdname[i] = NULL;
}
free(dbstat->statdname);
dbstat->statdname = NULL; |
75ccac9f |
}
#endif
|
cd69cf20 |
if(dbstat->stattab) {
free(dbstat->stattab);
dbstat->stattab = NULL;
} |
b5134815 |
dbstat->entries = 0; |
cd69cf20 |
|
9e431a95 |
if(dbstat->dir) { |
e3aaff8e |
free(dbstat->dir); |
9e431a95 |
dbstat->dir = NULL;
} |
e3aaff8e |
} else { |
8000d078 |
cli_errmsg("cl_statfree(): Null argument passed\n"); |
e3aaff8e |
return CL_ENULLARG;
}
|
8d3aca30 |
return CL_SUCCESS; |
e3aaff8e |
} |
f51e962f |
|
724b2bf7 |
int cl_engine_free(struct cl_engine *engine) |
f51e962f |
{ |
677fc4ba |
unsigned int i, j; |
f51e962f |
struct cli_meta_node *metapt, *metah;
struct cli_matcher *root; |
c9c463fe |
|
f51e962f |
if(!engine) {
cli_errmsg("cl_free: engine == NULL\n"); |
724b2bf7 |
return CL_ENULLARG; |
f51e962f |
}
#ifdef CL_THREAD_SAFE
pthread_mutex_lock(&cli_ref_mutex);
#endif
|
04ba76d2 |
if(engine->refcount)
engine->refcount--;
|
f51e962f |
if(engine->refcount) {
#ifdef CL_THREAD_SAFE
pthread_mutex_unlock(&cli_ref_mutex);
#endif |
724b2bf7 |
return CL_SUCCESS; |
f51e962f |
}
#ifdef CL_THREAD_SAFE
pthread_mutex_unlock(&cli_ref_mutex);
#endif |
bc93eda0 |
if(engine->root) { |
4addba22 |
for(i = 0; i < CLI_MTARGETS; i++) { |
bc93eda0 |
if((root = engine->root[i])) { |
bedc58de |
if(!root->ac_only) |
bc93eda0 |
cli_bm_free(root); |
bedc58de |
cli_ac_free(root); |
677fc4ba |
if(root->ac_lsigtable) {
for(j = 0; j < root->ac_lsigs; j++) { |
47d40feb |
mpool_free(engine->mempool, root->ac_lsigtable[j]->logic); |
677fc4ba |
FREE_TDB(root->ac_lsigtable[j]->tdb); |
47d40feb |
mpool_free(engine->mempool, root->ac_lsigtable[j]); |
677fc4ba |
} |
47d40feb |
mpool_free(engine->mempool, root->ac_lsigtable); |
677fc4ba |
} |
47d40feb |
mpool_free(engine->mempool, root); |
bc93eda0 |
} |
f51e962f |
} |
47d40feb |
mpool_free(engine->mempool, engine->root); |
f51e962f |
}
|
2b459819 |
if((root = engine->md5_hdb)) {
cli_bm_free(root); |
47d40feb |
mpool_free(engine->mempool, root); |
f51e962f |
}
|
2b459819 |
if((root = engine->md5_mdb)) { |
0a3d4094 |
cli_bm_free(root); |
47d40feb |
mpool_free(engine->mempool, root->soff); |
c3671221 |
if(root->md5_sizes_hs.capacity) {
hashset_destroy(&root->md5_sizes_hs);
} |
47d40feb |
mpool_free(engine->mempool, root); |
2f942502 |
}
|
2b459819 |
if((root = engine->md5_fp)) {
cli_bm_free(root); |
47d40feb |
mpool_free(engine->mempool, root); |
2b459819 |
}
|
f51e962f |
metapt = engine->zip_mlist;
while(metapt) {
metah = metapt;
metapt = metapt->next; |
47d40feb |
mpool_free(engine->mempool, metah->virname); |
f51e962f |
if(metah->filename) |
47d40feb |
mpool_free(engine->mempool, metah->filename);
mpool_free(engine->mempool, metah); |
f51e962f |
}
metapt = engine->rar_mlist;
while(metapt) {
metah = metapt;
metapt = metapt->next; |
47d40feb |
mpool_free(engine->mempool, metah->virname); |
f51e962f |
if(metah->filename) |
47d40feb |
mpool_free(engine->mempool, metah->filename);
mpool_free(engine->mempool, metah); |
f51e962f |
}
|
15850fc6 |
if(engine->dconf->phishing & PHISHING_CONF_ENGINE) |
692bda68 |
phishing_done(engine); |
bc93eda0 |
if(engine->dconf) |
47d40feb |
mpool_free(engine->mempool, engine->dconf); |
bc93eda0 |
|
b023c36d |
if(engine->pua_cats) |
47d40feb |
mpool_free(engine->mempool, engine->pua_cats); |
b023c36d |
|
33068e09 |
if(engine->tmpdir) |
47d40feb |
mpool_free(engine->mempool, engine->tmpdir); |
33068e09 |
|
0d9dbdef |
cli_ftfree(engine); |
ed9753e9 |
cli_freeign(engine); |
0d9dbdef |
#ifdef USE_MPOOL |
47d40feb |
if(engine->mempool) mpool_destroy(engine->mempool); |
e21657df |
#endif |
f51e962f |
free(engine); |
724b2bf7 |
return CL_SUCCESS; |
f51e962f |
}
|
c3671221 |
static void cli_md5db_build(struct cli_matcher* root)
{
if(root && root->md5_sizes_hs.capacity) {
/* TODO: use hashset directly, instead of the array when matching*/ |
a1c9ad2c |
cli_dbgmsg("Converting hashset to array: %u entries\n", root->md5_sizes_hs.count); |
d22176ef |
#ifdef USE_MPOOL
{
uint32_t *mpoolht;
unsigned int mpoolhtsz = root->md5_sizes_hs.count * sizeof(*mpoolht); |
47d40feb |
root->soff = mpool_malloc(root->mempool, mpoolhtsz); |
d22176ef |
root->soff_len = hashset_toarray(&root->md5_sizes_hs, &mpoolht);
memcpy(root->soff, mpoolht, mpoolhtsz);
free(mpoolht);
}
#else |
c3671221 |
root->soff_len = hashset_toarray(&root->md5_sizes_hs, &root->soff); |
d22176ef |
#endif |
c3671221 |
hashset_destroy(&root->md5_sizes_hs);
qsort(root->soff, root->soff_len, sizeof(uint32_t), scomp);
}
}
|
724b2bf7 |
int cl_engine_compile(struct cl_engine *engine) |
f51e962f |
{ |
7021b545 |
unsigned int i;
int ret; |
f51e962f |
struct cli_matcher *root;
|
7021b545 |
if(!engine)
return CL_ENULLARG;
if(!engine->ftypes) |
15850fc6 |
if((ret = cli_loadftm(NULL, engine, 0, 1, NULL))) |
7021b545 |
return ret; |
f51e962f |
|
4addba22 |
for(i = 0; i < CLI_MTARGETS; i++) {
if((root = engine->root[i])) {
if((ret = cli_ac_buildtrie(root)))
return ret;
cli_dbgmsg("matcher[%u]: %s: AC sigs: %u BM sigs: %u %s\n", i, cli_mtargets[i].name, root->ac_patterns, root->bm_patterns, root->ac_only ? "(ac_only mode)" : "");
}
} |
f51e962f |
|
2e11bcdf |
if((ret = cli_build_regex_list(engine->whitelist_matcher))) {
return ret;
}
if((ret = cli_build_regex_list(engine->domainlist_matcher))) {
return ret;
} |
c3671221 |
cli_md5db_build(engine->md5_mdb); |
ed9753e9 |
cli_freeign(engine); |
02ce73de |
cli_dconf_print(engine->dconf); |
47d40feb |
mpool_flush(engine->mempool); |
02ce73de |
|
b3df93db |
engine->dboptions |= CL_DB_COMPILED; |
8d3aca30 |
return CL_SUCCESS; |
f51e962f |
}
|
b8fe70b3 |
int cl_engine_addref(struct cl_engine *engine) |
f51e962f |
{
if(!engine) { |
b8fe70b3 |
cli_errmsg("cl_engine_addref: engine == NULL\n");
return CL_ENULLARG; |
f51e962f |
}
#ifdef CL_THREAD_SAFE
pthread_mutex_lock(&cli_ref_mutex);
#endif
engine->refcount++;
#ifdef CL_THREAD_SAFE
pthread_mutex_unlock(&cli_ref_mutex);
#endif
|
b8fe70b3 |
return CL_SUCCESS; |
f51e962f |
} |