555
if(engine->ignored && cli_chkign(engine->ignored, start, buffer_cpy))
558
if(engine->cb_sigload && engine->cb_sigload("db", start, engine->cb_sigload_ctx)) {
559
cli_dbgmsg("cli_loaddb: skipping %s due to callback\n", start);
563
613
if(*pt == '=') continue;
565
if((ret = cli_parse_add(root, start, pt, 0, 0, "*", 0, NULL, options))) {
615
if((ret = cli_parse_add(root, start, pt, 0, NULL, 0))) {
616
cli_errmsg("Problem parsing signature at line %d\n", line);
566
617
ret = CL_EMALFDB;
576
623
cli_errmsg("Empty database file\n");
577
625
return CL_EMALFDB;
581
629
cli_errmsg("Problem parsing database at line %d\n", line);
592
static int cli_loadidb(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio)
594
const char *tokens[ICO_TOKENS + 1];
595
char buffer[FILEBUFF], *buffer_cpy = NULL;
597
int ret = CL_SUCCESS;
598
unsigned int line = 0, sigs = 0, tokens_count, i, size, enginesize;
599
struct icomtr *metric;
600
struct icon_matcher *matcher;
603
if(!(matcher = (struct icon_matcher *)mpool_calloc(engine->mempool, sizeof(*matcher),1)))
607
if(!(buffer_cpy = cli_malloc(FILEBUFF))) {
608
mpool_free(engine->mempool, matcher);
612
while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
619
strcpy(buffer_cpy, buffer);
621
tokens_count = cli_strtokenize(buffer, ':', ICO_TOKENS + 1, tokens);
622
if(tokens_count != ICO_TOKENS) {
623
cli_errmsg("cli_loadidb: Malformed hash at line %u (wrong token count)\n", line);
628
if(strlen(tokens[3]) != 124) {
629
cli_errmsg("cli_loadidb: Malformed hash at line %u (wrong length)\n", line);
634
if(engine->ignored && cli_chkign(engine->ignored, tokens[0], buffer_cpy))
637
if(engine->cb_sigload && engine->cb_sigload("idb", tokens[0], engine->cb_sigload_ctx)) {
638
cli_dbgmsg("cli_loadidb: skipping %s due to callback\n", tokens[0]);
642
hash = (uint8_t *)tokens[3];
643
if(cli_hexnibbles((char *)hash, 124)) {
644
cli_errmsg("cli_loadidb: Malformed hash at line %u (bad chars)\n", line);
648
size = (hash[0] << 4) + hash[1];
649
if(size != 32 && size != 24 && size != 16) {
650
cli_errmsg("cli_loadidb: Malformed hash at line %u (bad size)\n", line);
654
enginesize = (size >> 3) - 2;
657
metric = (struct icomtr *)mpool_realloc(engine->mempool, matcher->icons[enginesize], sizeof(struct icomtr) * (matcher->icon_counts[enginesize] + 1));
663
matcher->icons[enginesize] = metric;
664
metric += matcher->icon_counts[enginesize];
665
matcher->icon_counts[enginesize]++;
668
if((metric->color_avg[i] = (hash[0] << 8) | (hash[1] << 4) | hash[2]) > 4072)
670
if((metric->color_x[i] = (hash[3] << 4) | hash[4]) > size - size / 8)
672
if((metric->color_y[i] = (hash[5] << 4) | hash[6]) > size - size / 8)
677
cli_errmsg("cli_loadidb: Malformed hash at line %u (bad color data)\n", line);
683
if((metric->gray_avg[i] = (hash[0] << 8) | (hash[1] << 4) | hash[2]) > 4072)
685
if((metric->gray_x[i] = (hash[3] << 4) | hash[4]) > size - size / 8)
687
if((metric->gray_y[i] = (hash[5] << 4) | hash[6]) > size - size / 8)
692
cli_errmsg("cli_loadidb: Malformed hash at line %u (bad gray data)\n", line);
698
metric->bright_avg[i] = (hash[0] << 4) | hash[1];
699
if((metric->bright_x[i] = (hash[2] << 4) | hash[3]) > size - size / 8)
701
if((metric->bright_y[i] = (hash[4] << 4) | hash[5]) > size - size / 8)
706
cli_errmsg("cli_loadidb: Malformed hash at line %u (bad bright data)\n", line);
712
metric->dark_avg[i] = (hash[0] << 4) | hash[1];
713
if((metric->dark_x[i] = (hash[2] << 4) | hash[3]) > size - size / 8)
715
if((metric->dark_y[i] = (hash[4] << 4) | hash[5]) > size - size / 8)
720
cli_errmsg("cli_loadidb: Malformed hash at line %u (bad dark data)\n", line);
726
metric->edge_avg[i] = (hash[0] << 4) | hash[1];
727
if((metric->edge_x[i] = (hash[2] << 4) | hash[3]) > size - size / 8)
729
if((metric->edge_y[i] = (hash[4] << 4) | hash[5]) > size - size / 8)
734
cli_errmsg("cli_loadidb: Malformed hash at line %u (bad edge data)\n", line);
740
metric->noedge_avg[i] = (hash[0] << 4) | hash[1];
741
if((metric->noedge_x[i] = (hash[2] << 4) | hash[3]) > size - size / 8)
743
if((metric->noedge_y[i] = (hash[4] << 4) | hash[5]) > size - size / 8)
748
cli_errmsg("cli_loadidb: Malformed hash at line %u (bad noedge data)\n", line);
753
metric->rsum = (hash[0] << 4) | hash[1];
754
metric->gsum = (hash[2] << 4) | hash[3];
755
metric->bsum = (hash[4] << 4) | hash[5];
756
metric->ccount = (hash[6] << 4) | hash[7];
757
if(metric->rsum + metric->gsum + metric->bsum > 103 || metric->ccount > 100) {
758
cli_errmsg("cli_loadidb: Malformed hash at line %u (bad spread data)\n", line);
763
if(!(metric->name = cli_mpool_strdup(engine->mempool, tokens[0]))) {
768
for(i=0; i<matcher->group_counts[0]; i++) {
769
if(!strcmp(tokens[1], matcher->group_names[0][i]))
772
if(i==matcher->group_counts[0]) {
773
if(!(matcher->group_names[0] = mpool_realloc(engine->mempool, matcher->group_names[0], sizeof(char *) * (i + 1))) ||
774
!(matcher->group_names[0][i] = cli_mpool_strdup(engine->mempool, tokens[1]))) {
778
matcher->group_counts[0]++;
780
metric->group[0] = i;
782
for(i=0; i<matcher->group_counts[1]; i++) {
783
if(!strcmp(tokens[2], matcher->group_names[1][i]))
786
if(i==matcher->group_counts[1]) {
787
if(!(matcher->group_names[1] = mpool_realloc(engine->mempool, matcher->group_names[1], sizeof(char *) * (i + 1))) ||
788
!(matcher->group_names[1][i] = cli_mpool_strdup(engine->mempool, tokens[2]))) {
792
matcher->group_counts[1]++;
794
metric->group[1] = i;
796
if(matcher->group_counts[0] > 256 || matcher->group_counts[1] > 256) {
797
cli_errmsg("cli_loadidb: too many icon groups!\n");
808
cli_errmsg("cli_loadidb: Empty database file\n");
813
cli_errmsg("cli_loadidb: Problem parsing database at line %u\n", line);
820
engine->iconcheck = matcher;
824
static int cli_loadwdb(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio)
829
if(!(engine->dconf->phishing & PHISHING_CONF_ENGINE))
832
if(!engine->whitelist_matcher) {
833
if((ret = init_whitelist(engine))) {
838
if((ret = load_regex_matcher(engine, engine->whitelist_matcher, fs, NULL, options, 1, dbio, engine->dconf->other&OTHER_CONF_PREFILTERING))) {
845
static int cli_loadpdb(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio)
850
if(!(engine->dconf->phishing & PHISHING_CONF_ENGINE))
853
if(!engine->domainlist_matcher) {
854
if((ret = init_domainlist(engine))) {
859
if((ret = load_regex_matcher(engine, engine->domainlist_matcher, fs, signo, options, 0, dbio, engine->dconf->other&OTHER_CONF_PREFILTERING))) {
867
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)
869
const char *tokens[NDB_TOKENS + 1];
870
char buffer[FILEBUFF], *buffer_cpy = NULL;
871
const char *sig, *virname, *offset, *pt;
640
#ifdef CL_EXPERIMENTAL
641
static int cli_loadwdb(FILE *fd, struct cl_engine **engine, unsigned int options)
646
if((ret = cli_initengine(engine, options))) {
651
if(!(*engine)->whitelist_matcher) {
652
if((ret = init_whitelist(*engine))) {
653
phishing_done(*engine);
659
if((ret = load_regex_matcher((*engine)->whitelist_matcher, fd, options, 1))) {
660
phishing_done(*engine);
668
static int cli_loadpdb(FILE *fd, struct cl_engine **engine, unsigned int options)
673
if((ret = cli_initengine(engine, options))) {
678
if(!(*engine)->domainlist_matcher) {
679
if((ret = init_domainlist(*engine))) {
680
phishing_done(*engine);
686
if((ret = load_regex_matcher((*engine)->domainlist_matcher, fd, options, 0))) {
687
phishing_done(*engine);
696
static int cli_loadndb(FILE *fd, struct cl_engine **engine, unsigned int *signo, unsigned short sdb, unsigned int options)
698
char buffer[FILEBUFF], *sig, *virname, *offset, *pt;
872
699
struct cli_matcher *root;
873
int line = 0, sigs = 0, ret = 0, tokens_count;
700
int line = 0, sigs = 0, ret = 0;
874
701
unsigned short target;
875
702
unsigned int phish = options & CL_DB_PHISHING;
878
if((ret = cli_initroots(engine, options)))
882
if(!(buffer_cpy = cli_malloc(FILEBUFF)))
885
while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
705
if((ret = cli_initengine(engine, options))) {
710
if((ret = cli_initroots(*engine, options))) {
715
while(fgets(buffer, FILEBUFF, fd)) {
718
if(!strncmp(buffer, "Exploit.JPEG.Comment", 20)) /* temporary */
889
722
if(!strncmp(buffer, "HTML.Phishing", 13) || !strncmp(buffer, "Email.Phishing", 14))
892
726
cli_chomp(buffer);
894
strcpy(buffer_cpy, buffer);
896
tokens_count = cli_strtokenize(buffer, ':', NDB_TOKENS + 1, tokens);
897
if(tokens_count < 4 || tokens_count > 6) {
728
if(!(virname = cli_strtok(buffer, 0, ":"))) {
898
729
ret = CL_EMALFDB;
904
if(engine->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)))
905
if(cli_chkpua(virname, engine->pua_cats, options))
908
if(engine->ignored && cli_chkign(engine->ignored, virname, buffer_cpy))
911
if(!sdb && engine->cb_sigload && engine->cb_sigload("ndb", virname, engine->cb_sigload_ctx)) {
912
cli_dbgmsg("cli_loadndb: skipping %s due to callback\n", virname);
916
if(tokens_count > 4) { /* min version */
919
if(!cli_isnumber(pt)) {
733
if((pt = cli_strtok(buffer, 4, ":"))) { /* min version */
920
737
ret = CL_EMALFDB;
924
741
if((unsigned int) atoi(pt) > cl_retflevel()) {
925
742
cli_dbgmsg("Signature for %s not loaded (required f-level: %d)\n", virname, atoi(pt));
929
if(tokens_count == 6) { /* max version */
931
if(!cli_isnumber(pt)) {
751
if((pt = cli_strtok(buffer, 5, ":"))) { /* max version */
932
755
ret = CL_EMALFDB;
936
759
if((unsigned int) atoi(pt) < cl_retflevel()) {
942
if(!(pt = tokens[1]) || (strcmp(pt, "*") && !cli_isnumber(pt))) {
770
if(!(pt = cli_strtok(buffer, 1, ":")) || !isdigit(*pt)) {
943
774
ret = CL_EMALFDB;
946
777
target = (unsigned short) atoi(pt);
948
if(target >= CLI_MTARGETS) {
780
if(target >= CL_TARGET_TABLE_SIZE) {
949
781
cli_dbgmsg("Not supported target type in signature for %s\n", virname);
953
root = engine->root[target];
958
if((ret = cli_parse_add(root, virname, sig, 0, 0, offset, target, NULL, options))) {
787
root = (*engine)->root[target];
789
if(!(offset = cli_strtok(buffer, 2, ":"))) {
793
} else if(!strcmp(offset, "*")) {
798
if(!(sig = cli_strtok(buffer, 3, ":"))) {
805
if((ret = cli_parse_add(root, virname, sig, 0, offset, target))) {
806
cli_errmsg("Problem parsing signature at line %d\n", line);
968
820
cli_errmsg("Empty database file\n");
969
822
return CL_EMALFDB;
973
826
cli_errmsg("Problem parsing database at line %d\n", line);
980
if(sdb && sigs && !engine->sdb) {
834
if(sdb && sigs && !(*engine)->sdb) {
982
836
cli_dbgmsg("*** Self protection mechanism activated.\n");
985
839
return CL_SUCCESS;
994
/* TODO: rework this */
995
static int lsigattribs(char *attribs, struct cli_lsig_tdb *tdb)
997
struct lsig_attrib attrtab[] = {
998
#define ATTRIB_TOKENS 9
999
{ "Target", CLI_TDB_UINT, (void **) &tdb->target },
1000
{ "Engine", CLI_TDB_RANGE, (void **) &tdb->engine },
1002
{ "FileSize", CLI_TDB_RANGE, (void **) &tdb->filesize },
1003
{ "EntryPoint", CLI_TDB_RANGE, (void **) &tdb->ep },
1004
{ "NumberOfSections", CLI_TDB_RANGE, (void **) &tdb->nos },
1006
{ "IconGroup1", CLI_TDB_STR, (void **) &tdb->icongrp1 },
1007
{ "IconGroup2", CLI_TDB_STR, (void **) &tdb->icongrp2 },
1009
{ "Container", CLI_TDB_FTYPE, (void **) &tdb->container },
1010
{ "HandlerType", CLI_TDB_FTYPE, (void **) &tdb->handlertype },
1012
{ "SectOff", CLI_TDB_RANGE2, (void **) &tdb->sectoff },
1013
{ "SectRVA", CLI_TDB_RANGE2, (void **) &tdb->sectrva },
1014
{ "SectVSZ", CLI_TDB_RANGE2, (void **) &tdb->sectvsz },
1015
{ "SectRAW", CLI_TDB_RANGE2, (void **) &tdb->sectraw },
1016
{ "SectRSZ", CLI_TDB_RANGE2, (void **) &tdb->sectrsz },
1017
{ "SectURVA", CLI_TDB_RANGE2, (void **) &tdb->secturva },
1018
{ "SectUVSZ", CLI_TDB_RANGE2, (void **) &tdb->sectuvsz },
1019
{ "SectURAW", CLI_TDB_RANGE2, (void **) &tdb->secturaw },
1020
{ "SectURSZ", CLI_TDB_RANGE2, (void **) &tdb->sectursz },
1024
struct lsig_attrib *apt;
1025
char *tokens[ATTRIB_TOKENS], *pt, *pt2;
1026
unsigned int v1, v2, v3, i, j, tokens_count, have_newext = 0;
1027
uint32_t cnt, off[ATTRIB_TOKENS];
1030
tokens_count = cli_strtokenize(attribs, ',', ATTRIB_TOKENS, (const char **) tokens);
1032
for(i = 0; i < tokens_count; i++) {
1033
if(!(pt = strchr(tokens[i], ':'))) {
1034
cli_errmsg("lsigattribs: Incorrect format of attribute '%s'\n", tokens[i]);
1040
for(j = 0; attrtab[j].name; j++) {
1041
if(!strcmp(attrtab[j].name, tokens[i])) {
1048
cli_dbgmsg("lsigattribs: Unknown attribute name '%s'\n", tokens[i]);
1052
if(!strcmp(apt->name, "Engine")) {
1054
cli_errmsg("lsigattribs: For backward compatibility the Engine attribute must be on the first position\n");
1057
} else if(strcmp(apt->name, "Target"))
1062
if(!cli_isnumber(pt)) {
1063
cli_errmsg("lsigattribs: Invalid argument for %s\n", tokens[i]);
1066
off[i] = cnt = tdb->cnt[CLI_TDB_UINT]++;
1067
tdb->val = (uint32_t *) mpool_realloc2(tdb->mempool, tdb->val, tdb->cnt[CLI_TDB_UINT] * sizeof(uint32_t));
1069
tdb->cnt[CLI_TDB_UINT] = 0;
1072
tdb->val[cnt] = atoi(pt);
1076
if((v1 = cli_ftcode(pt)) == CL_TYPE_ERROR) {
1077
cli_dbgmsg("lsigattribs: Unknown file type in %s\n", tokens[i]);
1078
return 1; /* skip */
1080
off[i] = cnt = tdb->cnt[CLI_TDB_UINT]++;
1081
tdb->val = (uint32_t *) mpool_realloc2(tdb->mempool, tdb->val, tdb->cnt[CLI_TDB_UINT] * sizeof(uint32_t));
1083
tdb->cnt[CLI_TDB_UINT] = 0;
1090
if(!(pt2 = strchr(pt, '-'))) {
1091
cli_errmsg("lsigattribs: Incorrect parameters in '%s'\n", tokens[i]);
1095
off[i] = cnt = tdb->cnt[CLI_TDB_RANGE];
1096
tdb->cnt[CLI_TDB_RANGE] += 2;
1097
tdb->range = (uint32_t *) mpool_realloc2(tdb->mempool, tdb->range, tdb->cnt[CLI_TDB_RANGE] * sizeof(uint32_t));
1099
tdb->cnt[CLI_TDB_RANGE] = 0;
1102
if(!cli_isnumber(pt) || !cli_isnumber(pt2)) {
1103
cli_errmsg("lsigattribs: Invalid argument for %s\n", tokens[i]);
1106
tdb->range[cnt] = atoi(pt);
1107
tdb->range[cnt + 1] = atoi(pt2);
1110
case CLI_TDB_RANGE2:
1111
if(!strchr(pt, '-') || !strchr(pt, '.')) {
1112
cli_errmsg("lsigattribs: Incorrect parameters in '%s'\n", tokens[i]);
1115
off[i] = cnt = tdb->cnt[CLI_TDB_RANGE];
1116
tdb->cnt[CLI_TDB_RANGE] += 3;
1117
tdb->range = (uint32_t *) mpool_realloc2(tdb->mempool, tdb->range, tdb->cnt[CLI_TDB_RANGE] * sizeof(uint32_t));
1119
tdb->cnt[CLI_TDB_RANGE] = 0;
1122
if(sscanf(pt, "%u.%u-%u", &v1, &v2, &v3) != 3) {
1123
cli_errmsg("lsigattribs: Can't parse parameters in '%s'\n", tokens[i]);
1126
tdb->range[cnt] = (uint32_t) v1;
1127
tdb->range[cnt + 1] = (uint32_t) v2;
1128
tdb->range[cnt + 2] = (uint32_t) v3;
1132
off[i] = cnt = tdb->cnt[CLI_TDB_STR];
1133
tdb->cnt[CLI_TDB_STR] += strlen(pt) + 1;
1134
tdb->str = (char *) mpool_realloc2(tdb->mempool, tdb->str, tdb->cnt[CLI_TDB_STR] * sizeof(char));
1136
cli_errmsg("lsigattribs: Can't allocate memory for tdb->str\n");
1139
memcpy(&tdb->str[cnt], pt, strlen(pt));
1140
tdb->str[tdb->cnt[CLI_TDB_STR] - 1] = 0;
1146
cli_errmsg("lsigattribs: Empty TDB\n");
1150
for(i = 0; i < tokens_count; i++) {
1151
for(j = 0; attrtab[j].name; j++) {
1152
if(!strcmp(attrtab[j].name, tokens[i])) {
1162
*apt->pt = (uint32_t *) &tdb->val[off[i]];
1166
case CLI_TDB_RANGE2:
1167
*apt->pt = (uint32_t *) &tdb->range[off[i]];
1171
*apt->pt = (char *) &tdb->str[off[i]];
1176
if(have_newext && (!tdb->engine || tdb->engine[0] < 51)) {
1177
cli_errmsg("lsigattribs: For backward compatibility all signatures using new attributes must have the Engine attribute present and set to min_level of at least 51 (0.96)\n");
1183
#define FREE_TDB(x) do { \
1184
if(x.cnt[CLI_TDB_UINT]) \
1185
mpool_free(x.mempool, x.val); \
1186
if(x.cnt[CLI_TDB_RANGE]) \
1187
mpool_free(x.mempool, x.range); \
1188
if(x.cnt[CLI_TDB_STR]) \
1189
mpool_free(x.mempool, x.str); \
1191
mpool_free(x.mempool, x.macro_ptids);\
1194
#define LDB_TOKENS 67
1195
static int load_oneldb(char *buffer, int chkpua, int chkign, struct cl_engine *engine, unsigned int options, const char *dbname, unsigned int line, unsigned int *sigs, unsigned bc_idx, const char *buffer_cpy)
1197
const char *sig, *virname, *offset, *logic;
1198
struct cli_ac_lsig **newtable, *lsig;
1199
char *tokens[LDB_TOKENS+1], *pt;
1200
int i, subsigs, tokens_count;
1201
unsigned short target = 0;
1202
struct cli_matcher *root;
1203
struct cli_lsig_tdb tdb;
1207
tokens_count = cli_strtokenize(buffer, ';', LDB_TOKENS + 1, (const char **) tokens);
1208
if(tokens_count < 4) {
1211
virname = tokens[0];
1214
if (chkpua && cli_chkpua(virname, engine->pua_cats, options))
1217
if (chkign && cli_chkign(engine->ignored, virname, buffer_cpy))
1220
if(engine->cb_sigload && engine->cb_sigload("ldb", virname, engine->cb_sigload_ctx)) {
1221
cli_dbgmsg("cli_loadldb: skipping %s due to callback\n", virname);
1226
subsigs = cli_ac_chklsig(logic, logic + strlen(logic), NULL, NULL, NULL, 1);
1232
cli_errmsg("cli_loadldb: Broken logical expression or too many subsignatures\n");
1236
/* This is a logical signature from the bytecode, we need all
1237
* subsignatures, even if not referenced from the logical expression */
1238
if (subsigs > tokens_count-3) {
1239
cli_errmsg("load_oneldb: Too many subsignatures: %u (max %u)\n",
1240
subsigs, tokens_count-3);
1243
subsigs = tokens_count-3;
1244
} else if(subsigs != tokens_count - 3) {
1245
cli_errmsg("cli_loadldb: The number of subsignatures (== %u) doesn't match the IDs in the logical expression (== %u)\n", tokens_count - 3, subsigs);
1250
memset(&tdb, 0, sizeof(tdb));
1252
tdb.mempool = engine->mempool;
1254
if((ret = lsigattribs(tokens[1], &tdb))) {
1257
cli_dbgmsg("cli_loadldb: Not supported attribute(s) in logical signature for %s, skipping\n", virname);
1265
if(tdb.engine[0] > cl_retflevel()) {
1266
cli_dbgmsg("cli_loadldb: Signature for %s not loaded (required f-level: %u)\n", virname, tdb.engine[0]);
1270
} else if(tdb.engine[1] < cl_retflevel()) {
1278
cli_errmsg("cli_loadldb: No target specified in TDB\n");
1281
} else if(tdb.target[0] >= CLI_MTARGETS) {
1282
cli_dbgmsg("cli_loadldb: Not supported target type in logical signature for %s, skipping\n", virname);
1288
if((tdb.icongrp1 || tdb.icongrp2) && tdb.target[0] != 1) {
1289
cli_errmsg("cli_loadldb: IconGroup is only supported in PE (target 1) signatures\n");
1294
if((tdb.ep || tdb.nos) && tdb.target[0] != 1 && tdb.target[0] != 6 && tdb.target[0] != 9) {
1295
cli_errmsg("cli_loadldb: EntryPoint/NumberOfSections is only supported in PE/ELF/Mach-O signatures\n");
1300
root = engine->root[tdb.target[0]];
1302
lsig = (struct cli_ac_lsig *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_ac_lsig));
1304
cli_errmsg("cli_loadldb: Can't allocate memory for lsig\n");
1309
lsig->logic = cli_mpool_strdup(engine->mempool, logic);
1311
cli_errmsg("cli_loadldb: Can't allocate memory for lsig->logic\n");
1313
mpool_free(engine->mempool, lsig);
1317
lsigid[0] = lsig->id = root->ac_lsigs;
1320
newtable = (struct cli_ac_lsig **) mpool_realloc(engine->mempool, root->ac_lsigtable, root->ac_lsigs * sizeof(struct cli_ac_lsig *));
1323
cli_errmsg("cli_loadldb: Can't realloc root->ac_lsigtable\n");
1325
mpool_free(engine->mempool, lsig);
1328
/* 0 marks no bc, we can't use a pointer to bc, since that is
1329
* realloced/moved during load */
1330
lsig->bc_idx = bc_idx;
1331
newtable[root->ac_lsigs - 1] = lsig;
1332
root->ac_lsigtable = newtable;
1333
tdb.subsigs = subsigs;
1335
for(i = 0; i < subsigs; i++) {
1337
sig = tokens[3 + i];
1339
if((pt = strchr(tokens[3 + i], ':'))) {
1342
offset = tokens[3 + i];
1345
sig = tokens[3 + i];
1348
if((ret = cli_parse_add(root, virname, sig, 0, 0, offset, target, lsigid, options)))
1350
if(sig[0] == '$' && i) {
1351
/* allow mapping from lsig back to pattern for macros */
1352
if (!tdb.macro_ptids)
1353
tdb.macro_ptids = mpool_calloc(root->mempool, subsigs, sizeof(*tdb.macro_ptids));
1354
if (!tdb.macro_ptids)
1356
tdb.macro_ptids[i-1] = root->ac_patterns-1;
1359
memcpy(&lsig->tdb, &tdb, sizeof(tdb));
1363
static int cli_loadldb(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, const char *dbname)
1365
char buffer[CLI_DEFAULT_LSIG_BUFSIZE + 1], *buffer_cpy = NULL;
1366
unsigned int line = 0, sigs = 0;
1370
if((ret = cli_initroots(engine, options)))
842
static int cli_loadhdb(FILE *fd, struct cl_engine **engine, unsigned int *signo, unsigned short mode, unsigned int options)
844
char buffer[FILEBUFF], *pt;
845
int line = 0, ret = 0;
846
unsigned int md5f = 0, sizef = 1;
847
struct cli_md5_node *new, *mpt, *last;
850
if((ret = cli_initengine(engine, options))) {
1374
if(!(buffer_cpy = cli_malloc(sizeof(buffer))))
1376
while(cli_dbgets(buffer, sizeof(buffer), fs, dbio)) {
860
while(fgets(buffer, FILEBUFF, fd)) {
1379
862
cli_chomp(buffer);
1382
strcpy(buffer_cpy, buffer);
1383
ret = load_oneldb(buffer,
1384
engine->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)),
1386
engine, options, dbname, line, &sigs, 0, buffer_cpy);
1394
cli_errmsg("Empty database file\n");
1399
cli_errmsg("Problem parsing database at line %u\n", line);
1409
static int cli_loadcbc(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, const char *dbname)
1413
struct cli_all_bc *bcs = &engine->bcs;
1416
unsigned security_trust = 0;
1420
/* TODO: virusname have a common prefix, and whitelist by that */
1421
if((rc = cli_initroots(engine, options)))
1424
if(!(engine->dconf->bytecode & BYTECODE_ENGINE_MASK)) {
1428
if(engine->cb_sigload && engine->cb_sigload("cbc", dbname, engine->cb_sigload_ctx)) {
1429
cli_dbgmsg("cli_loadcbc: skipping %s due to callback\n", dbname);
1433
#ifndef CL_BCUNSIGNED
1434
if (!(options & CL_DB_SIGNED)) {
1435
cli_warnmsg("Only loading signed bytecode, skipping load of unsigned bytecode!\n");
1436
cli_warnmsg("Build with ./configure --enable-unsigned-bytecode to enable loading of unsigned bytecode\n");
1440
bcs->all_bcs = cli_realloc2(bcs->all_bcs, sizeof(*bcs->all_bcs)*(bcs->count+1));
1441
if (!bcs->all_bcs) {
1442
cli_errmsg("cli_loadcbc: Can't allocate memory for bytecode entry\n");
1446
bc = &bcs->all_bcs[bcs->count-1];
1448
switch (engine->bytecode_security) {
1449
case CL_BYTECODE_TRUST_ALL:
1451
cli_dbgmsg("bytecode: trusting all bytecode!\n");
1453
case CL_BYTECODE_TRUST_SIGNED:
1454
security_trust = !!(options & CL_DB_SIGNED);
1460
rc = cli_bytecode_load(bc, fs, dbio, security_trust);
1461
/* read remainder of DB, needed because cvd.c checks that we read the entire
1463
while (cli_dbgets(buf, sizeof(buf), fs, dbio)) {}
1465
if (rc != CL_SUCCESS) {
1466
cli_bytecode_destroy(bc);
1467
cli_errmsg("Unable to load %s bytecode: %s\n", dbname, cl_strerror(rc));
1470
if (bc->state == bc_skip) {
1471
cli_bytecode_destroy(bc);
1475
bc->id = bcs->count;/* must set after _load, since load zeroes */
1476
if (engine->bytecode_mode == CL_BYTECODE_MODE_TEST)
1477
cli_infomsg(NULL, "bytecode %u -> %s\n", bc->id, dbname);
1479
if (bc->kind == BC_LOGICAL || bc->lsig) {
1480
unsigned oldsigs = sigs;
1482
cli_errmsg("Bytecode %s has logical kind, but missing logical signature!\n", dbname);
1485
cli_dbgmsg("Bytecode %s(%u) has logical signature: %s\n", dbname, bc->id, bc->lsig);
1486
rc = load_oneldb(bc->lsig, 0, 0, engine, options, dbname, 0, &sigs, bcs->count, NULL);
1487
if (rc != CL_SUCCESS) {
1488
cli_errmsg("Problem parsing logical signature %s for bytecode %s: %s\n",
1489
bc->lsig, dbname, cl_strerror(rc));
1492
if (sigs != oldsigs) {
1493
/* compiler ensures Engine field in lsig matches the one in bytecode,
1494
* so this should never happen. */
1495
cli_errmsg("Bytecode logical signature skipped, but bytecode itself not?");
1499
if (bc->kind != BC_LOGICAL) {
1501
/* runlsig will only flip a status bit, not report a match,
1502
* when the hooks are executed we only execute the hook if its
1503
* status bit is on */
1504
bc->hook_lsig_id = ++engine->hook_lsig_ids;
1506
if (bc->kind >= _BC_START_HOOKS && bc->kind < _BC_LAST_HOOK) {
1507
unsigned hook = bc->kind - _BC_START_HOOKS;
1508
unsigned cnt = ++engine->hooks_cnt[hook];
1509
engine->hooks[hook] = cli_realloc2(engine->hooks[hook],
1510
sizeof(*engine->hooks[0])*cnt);
1511
if (!engine->hooks[hook]) {
1512
cli_errmsg("Out of memory allocating memory for hook %u", hook);
1515
engine->hooks[hook][cnt-1] = bcs->count-1;
1516
} else switch (bc->kind) {
1518
for (i=0;i<bcs->count-1;i++)
1519
if (bcs->all_bcs[i].kind == BC_STARTUP) {
1520
struct cli_bc *bc0 = &bcs->all_bcs[i];
1521
cli_errmsg("Can only load 1 BC_STARTUP bytecode, attempted to load 2nd!\n");
1522
cli_warnmsg("Previous BC_STARTUP: %d %d by %s\n",
1523
bc0->id, (uint32_t)bc0->metadata.timestamp,
1524
bc0->metadata.sigmaker ? bc0->metadata.sigmaker : "N/A");
1525
cli_warnmsg("Conflicting BC_STARTUP: %d %d by %s\n",
1526
bc->id, (uint32_t)bc->metadata.timestamp,
1527
bc->metadata.sigmaker ? bc->metadata.sigmaker : "N/A");
864
new = (struct cli_md5_node *) cli_calloc(1, sizeof(struct cli_md5_node));
870
if(mode == 1) /* fp */
873
if(!(pt = cli_strtok(buffer, md5f, ":"))) {
879
if(!(new->md5 = (unsigned char *) cli_hex2str(pt))) {
880
cli_errmsg("Malformed MD5 string at line %d\n", line);
888
if(!(pt = cli_strtok(buffer, sizef, ":"))) {
894
new->size = atoi(pt);
897
if(!(new->virname = cli_strtok(buffer, 2, ":"))) {
904
new->viralias = cli_strtok(buffer, 3, ":"); /* aliases are optional */
906
if(mode == 2) { /* section MD5 */
907
if(!(*engine)->md5_sect) {
908
(*engine)->md5_sect = new;
910
if(new->size <= (*engine)->md5_sect->size) {
911
new->next = (*engine)->md5_sect;
912
(*engine)->md5_sect = new;
914
mpt = (*engine)->md5_sect;
917
if(!mpt->next || new->size <= mpt->next->size)
1532
cli_errmsg("Bytecode: unhandled bytecode kind %u\n", bc->kind);
1541
#define FTM_TOKENS 8
1542
static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options, unsigned int internal, struct cli_dbio *dbio)
1544
const char *tokens[FTM_TOKENS + 1], *pt;
1545
char buffer[FILEBUFF];
1546
unsigned int line = 0, sigs = 0, tokens_count;
1547
struct cli_ftype *new;
1548
cli_file_t rtype, type;
1552
if((ret = cli_initroots(engine, options)))
1557
options |= CL_DB_OFFICIAL;
1558
if(!ftypes_int[line])
1560
strncpy(buffer, ftypes_int[line], sizeof(buffer));
1561
buffer[sizeof(buffer)-1]='\0';
1563
if(!cli_dbgets(buffer, FILEBUFF, fs, dbio))
1568
tokens_count = cli_strtokenize(buffer, ':', FTM_TOKENS + 1, tokens);
1570
if(tokens_count < 6 || tokens_count > 8) {
1575
if(tokens_count > 6) { /* min version */
1577
if(!cli_isnumber(pt)) {
1581
if((unsigned int) atoi(pt) > cl_retflevel()) {
1582
cli_dbgmsg("cli_loadftm: File type signature for %s not loaded (required f-level: %u)\n", tokens[3], atoi(pt));
1585
if(tokens_count == 8) { /* max version */
1587
if(!cli_isnumber(pt)) {
1591
if((unsigned int) atoi(pt) < cl_retflevel())
1596
rtype = cli_ftcode(tokens[4]);
1597
type = cli_ftcode(tokens[5]);
1598
if(rtype == CL_TYPE_ERROR || type == CL_TYPE_ERROR) {
1603
if(!cli_isnumber(tokens[0])) {
1604
cli_errmsg("cli_loadftm: Invalid value for the first field\n");
1609
if(atoi(tokens[0]) == 1) { /* A-C */
1610
if((ret = cli_parse_add(engine->root[0], tokens[3], tokens[2], rtype, type, tokens[1], 0, NULL, options)))
1613
} else if(atoi(tokens[0]) == 0) { /* memcmp() */
1614
if(!cli_isnumber(tokens[1])) {
1615
cli_errmsg("cli_loadftm: Invalid offset\n");
1619
new = (struct cli_ftype *) mpool_malloc(engine->mempool, sizeof(struct cli_ftype));
1625
new->offset = atoi(tokens[1]);
1626
new->magic = (unsigned char *) cli_mpool_hex2str(engine->mempool, tokens[2]);
1628
cli_errmsg("cli_loadftm: Can't decode the hex string\n");
1630
mpool_free(engine->mempool, new);
1633
new->length = strlen(tokens[2]) / 2;
1634
new->tname = cli_mpool_strdup(engine->mempool, tokens[3]);
1636
mpool_free(engine->mempool, new->magic);
1637
mpool_free(engine->mempool, new);
1641
new->next = engine->ftypes;
1642
engine->ftypes = new;
1645
cli_dbgmsg("cli_loadftm: Unsupported mode %u\n", atoi(tokens[0]));
1652
cli_errmsg("Problem parsing %s filetype database at line %u\n", internal ? "built-in" : "external", line);
1657
cli_errmsg("Empty %s filetype database\n", internal ? "built-in" : "external");
1661
cli_dbgmsg("Loaded %u filetype definitions\n", sigs);
1665
#define INFO_NSTR "11088894983048545473659556106627194923928941791795047620591658697413581043322715912172496806525381055880964520618400224333320534660299233983755341740679502866829909679955734391392668378361221524205396631090105151641270857277080310734320951653700508941717419168723942507890702904702707587451621691050754307850383399865346487203798464178537392211402786481359824461197231102895415093770394216666324484593935762408468516826633192140826667923494822045805347809932848454845886971706424360558667862775876072059437703365380209101697738577515476935085469455279994113145977994084618328482151013142393373316337519977244732747977"
1666
#define INFO_ESTR "100002049"
1667
#define INFO_TOKENS 3
1668
static int cli_loadinfo(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio)
1670
const char *tokens[INFO_TOKENS + 1];
1671
char buffer[FILEBUFF];
1672
unsigned int line = 0, tokens_count, len;
1673
unsigned char hash[32];
1674
struct cli_dbinfo *last = NULL, *new;
1675
int ret = CL_SUCCESS, dsig = 0;
1680
cli_errmsg("cli_loadinfo: .info files can only be loaded from within database container files\n");
1684
while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
1686
if(!strncmp(buffer, "DSIG:", 5)) {
1688
sha256_final(&ctx, hash);
1689
if(cli_versig2(hash, buffer + 5, INFO_NSTR, INFO_ESTR) != CL_SUCCESS) {
1690
cli_errmsg("cli_loadinfo: Incorrect digital signature\n");
1695
len = strlen(buffer);
1696
if(dbio->usebuf && buffer[len - 1] != '\n' && len + 1 < FILEBUFF) {
1697
/* cli_dbgets in buffered mode strips \n */
1699
buffer[len + 1] = 0;
1701
sha256_update(&ctx, buffer, strlen(buffer));
1703
if(!strncmp("ClamAV-VDB:", buffer, 11)) {
1704
if(engine->dbinfo) { /* shouldn't be initialized at this point */
1705
cli_errmsg("cli_loadinfo: engine->dbinfo already initialized\n");
1709
last = engine->dbinfo = (struct cli_dbinfo *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_bm_patt));
1710
if(!engine->dbinfo) {
1714
engine->dbinfo->cvd = cl_cvdparse(buffer);
1715
if(!engine->dbinfo->cvd) {
1716
cli_errmsg("cli_loadinfo: Can't parse header entry\n");
1724
cli_errmsg("cli_loadinfo: Incorrect file format\n");
1728
tokens_count = cli_strtokenize(buffer, ':', INFO_TOKENS + 1, tokens);
1729
if(tokens_count != INFO_TOKENS) {
1733
new = (struct cli_dbinfo *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_dbinfo));
1738
new->name = cli_mpool_strdup(engine->mempool, tokens[0]);
1740
mpool_free(engine->mempool, new);
1745
if(!cli_isnumber(tokens[1])) {
1746
cli_errmsg("cli_loadinfo: Invalid value in the size field\n");
1747
mpool_free(engine->mempool, new->name);
1748
mpool_free(engine->mempool, new);
1752
new->size = atoi(tokens[1]);
1754
if(strlen(tokens[2]) != 64 || !(new->hash = cli_mpool_hex2str(engine->mempool, tokens[2]))) {
1755
cli_errmsg("cli_loadinfo: Malformed SHA256 string at line %u\n", line);
1756
mpool_free(engine->mempool, new->name);
1757
mpool_free(engine->mempool, new);
1766
cli_errmsg("cli_loadinfo: Digital signature not found\n");
1771
cli_errmsg("cli_loadinfo: Problem parsing database at line %u\n", line);
1778
#define IGN_MAX_TOKENS 3
1779
static int cli_loadign(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio)
1781
const char *tokens[IGN_MAX_TOKENS + 1], *signame, *hash = NULL;
1782
char buffer[FILEBUFF];
1783
unsigned int line = 0, tokens_count, len;
1784
struct cli_bm_patt *new;
1785
int ret = CL_SUCCESS;
1787
if(!engine->ignored) {
1788
engine->ignored = (struct cli_matcher *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_matcher));
1789
if(!engine->ignored)
1792
engine->ignored->mempool = engine->mempool;
1794
if((ret = cli_bm_init(engine->ignored))) {
1795
cli_errmsg("cli_loadign: Can't initialise AC pattern matcher\n");
1800
while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
1804
tokens_count = cli_strtokenize(buffer, ':', IGN_MAX_TOKENS + 1, tokens);
1805
if(tokens_count > IGN_MAX_TOKENS) {
1810
if(tokens_count == 1) {
1812
} else if(tokens_count == 2) {
1813
signame = tokens[0];
1815
} else { /* old mode */
1816
signame = tokens[2];
1818
if(!(len = strlen(signame))) {
1819
cli_errmsg("cli_loadign: No signature name provided\n");
1824
new = (struct cli_bm_patt *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_bm_patt));
1829
new->pattern = (unsigned char *) cli_mpool_strdup(engine->mempool, signame);
1831
mpool_free(engine->mempool, new);
1836
if(strlen(hash) != 32 || !(new->virname = (char *) cli_mpool_hex2str(engine->mempool, hash))) {
1837
cli_errmsg("cli_loadign: Malformed MD5 string at line %u\n", line);
1838
mpool_free(engine->mempool, new->pattern);
1839
mpool_free(engine->mempool, new);
1845
new->boundary |= BM_BOUNDARY_EOL;
1847
if((ret = cli_bm_addpatt(engine->ignored, new, "0"))) {
1849
mpool_free(engine->mempool, new->virname);
1850
mpool_free(engine->mempool, new->pattern);
1851
mpool_free(engine->mempool, new);
1857
cli_errmsg("cli_loadign: Problem parsing database at line %u\n", line);
1868
#define MD5_TOKENS 5
1869
static int cli_loadhash(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int mode, unsigned int options, struct cli_dbio *dbio, const char *dbname)
1871
const char *tokens[MD5_TOKENS + 1];
1872
char buffer[FILEBUFF], *buffer_cpy = NULL;
1873
const char *pt, *virname;
1874
int ret = CL_SUCCESS;
1875
unsigned int size_field = 1, md5_field = 0, line = 0, sigs = 0, tokens_count;
1876
struct cli_matcher *db = NULL;
1880
if(mode == MD5_MDB) {
1886
if(!(buffer_cpy = cli_malloc(FILEBUFF)))
1889
while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
1893
strcpy(buffer_cpy, buffer);
1895
tokens_count = cli_strtokenize(buffer, ':', MD5_TOKENS + 1, tokens);
1896
if(tokens_count < 3) {
1900
if(tokens_count > MD5_TOKENS - 2) {
1901
unsigned int req_fl = atoi(tokens[MD5_TOKENS - 2]);
1903
if(tokens_count > MD5_TOKENS) {
1908
if(cl_retflevel() < req_fl)
1910
if(tokens_count == MD5_TOKENS) {
1911
req_fl = atoi(tokens[MD5_TOKENS - 1]);
1912
if(cl_retflevel() > req_fl)
1917
size = strtol(tokens[size_field], (char **)&pt, 10);
1918
if(*pt || !size || size >= 0xffffffff) {
1919
cli_errmsg("cli_loadhash: Invalid value for the size field\n");
1924
pt = tokens[2]; /* virname */
1925
if(engine->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)))
1926
if(cli_chkpua(pt, engine->pua_cats, options))
1929
if(engine->ignored && cli_chkign(engine->ignored, pt, buffer_cpy))
1932
if(engine->cb_sigload) {
1933
const char *dot = strchr(dbname, '.');
1938
if(engine->cb_sigload(dot, pt, engine->cb_sigload_ctx)) {
1939
cli_dbgmsg("cli_loadhash: skipping %s (%s) due to callback\n", pt, dot);
1944
virname = cli_mpool_virname(engine->mempool, pt, options & CL_DB_OFFICIAL);
1951
db = engine->hm_hdb;
1952
else if(mode == MD5_MDB)
1953
db = engine->hm_mdb;
1958
if(!(db = mpool_calloc(engine->mempool, 1, sizeof(*db)))) {
1963
db->mempool = engine->mempool;
1966
engine->hm_hdb = db;
1967
else if(mode == MD5_MDB)
1968
engine->hm_mdb = db;
1973
if((ret = hm_addhash(db, tokens[md5_field], size, virname))) {
1974
cli_errmsg("cli_loadhash: Malformed MD5 string at line %u\n", line);
1975
mpool_free(engine->mempool, (void *)virname);
1985
cli_errmsg("cli_loadhash: Empty database file\n");
1990
cli_errmsg("cli_loadhash: Problem parsing database at line %u\n", line);
2001
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)
2003
const char *tokens[MD_TOKENS + 1];
2004
char buffer[FILEBUFF], *buffer_cpy = NULL;
2005
unsigned int line = 0, sigs = 0, tokens_count;
2006
int ret = CL_SUCCESS;
2007
struct cli_cdb *new;
2011
if(!(buffer_cpy = cli_malloc(FILEBUFF)))
2014
while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
2016
if(buffer[0] == '#')
2021
strcpy(buffer_cpy, buffer);
2023
tokens_count = cli_strtokenize(buffer, ':', MD_TOKENS + 1, tokens);
2024
if(tokens_count != MD_TOKENS) {
2029
if(strcmp(tokens[1], "*") && !cli_isnumber(tokens[1])) {
2030
cli_errmsg("cli_loadmd: Invalid value for the 'encrypted' field\n");
2034
if(strcmp(tokens[3], "*") && !cli_isnumber(tokens[3])) {
2035
cli_errmsg("cli_loadmd: Invalid value for the 'original size' field\n");
2039
if(strcmp(tokens[4], "*") && !cli_isnumber(tokens[4])) {
2040
cli_errmsg("cli_loadmd: Invalid value for the 'compressed size' field\n");
2044
if(strcmp(tokens[6], "*") && !cli_isnumber(tokens[6])) {
2045
cli_errmsg("cli_loadmd: Invalid value for the 'compression method' field\n");
2049
if(strcmp(tokens[7], "*") && !cli_isnumber(tokens[7])) {
2050
cli_errmsg("cli_loadmd: Invalid value for the 'file number' field\n");
2054
if(strcmp(tokens[8], "*") && !cli_isnumber(tokens[8])) {
2055
cli_errmsg("cli_loadmd: Invalid value for the 'max depth' field\n");
2060
new = (struct cli_cdb *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_cdb));
2066
new->virname = cli_mpool_virname(engine->mempool, tokens[0], options & CL_DB_OFFICIAL);
2068
mpool_free(engine->mempool, new);
2072
new->ctype = (type == 1) ? CL_TYPE_ZIP : CL_TYPE_RAR;
2074
if(engine->ignored && cli_chkign(engine->ignored, new->virname, buffer/*_cpy*/)) {
2075
mpool_free(engine->mempool, new->virname);
2076
mpool_free(engine->mempool, new);
2080
if(engine->cb_sigload && engine->cb_sigload("md", new->virname, engine->cb_sigload_ctx)) {
2081
cli_dbgmsg("cli_loadmd: skipping %s due to callback\n", new->virname);
2082
mpool_free(engine->mempool, new->virname);
2083
mpool_free(engine->mempool, new);
2087
new->encrypted = strcmp(tokens[1], "*") ? atoi(tokens[1]) : 2;
2089
if(strcmp(tokens[2], "*") && cli_regcomp(&new->name, tokens[2], REG_EXTENDED | REG_NOSUB)) {
2090
cli_errmsg("cli_loadmd: Can't compile regular expression %s in signature for %s\n", tokens[2], tokens[0]);
2091
mpool_free(engine->mempool, new->virname);
2092
mpool_free(engine->mempool, new);
2096
new->csize[0] = new->csize[1] = CLI_OFF_ANY;
2098
if(!strcmp(tokens[3], "*"))
2099
new->fsizer[0] = new->fsizer[1] = CLI_OFF_ANY;
2101
new->fsizer[0] = new->fsizer[1] = atoi(tokens[3]);
2103
if(!strcmp(tokens[4], "*"))
2104
new->fsizec[0] = new->fsizec[1] = CLI_OFF_ANY;
2106
new->fsizec[0] = new->fsizec[1] = atoi(tokens[4]);
2108
if(strcmp(tokens[5], "*")) {
2109
new->res1 = cli_hex2num(tokens[5]);
2110
if(new->res1 == -1) {
2111
mpool_free(engine->mempool, new->virname);
2112
mpool_free(engine->mempool, new);
2113
if(new->name.re_magic)
2114
cli_regfree(&new->name);
2120
/* tokens[6] - not used */
2122
new->filepos[0] = new->filepos[1] = strcmp(tokens[7], "*") ? atoi(tokens[7]) : (int) CLI_OFF_ANY;
2124
/* tokens[8] - not used */
2126
new->next = engine->cdb;
2134
cli_errmsg("Empty database file\n");
2139
cli_errmsg("Problem parsing database at line %d\n", line);
2149
/* 0 1 2 3 4 5 6 7 8 9 10 11
2150
* VirusName:ContainerType:ContainerSize:FileNameREGEX:FileSizeInContainer:FileSizeReal:IsEncrypted:FilePos:Res1:Res2[:MinFL[:MaxFL]]
2153
#define CDB_TOKENS 12
2154
static int cli_loadcdb(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio)
2156
const char *tokens[CDB_TOKENS + 1];
2157
char buffer[FILEBUFF], *buffer_cpy = NULL;
2158
unsigned int line = 0, sigs = 0, tokens_count, n0, n1;
2159
int ret = CL_SUCCESS;
2160
struct cli_cdb *new;
2164
if(!(buffer_cpy = cli_malloc(FILEBUFF)))
2167
while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
2169
if(buffer[0] == '#')
2174
strcpy(buffer_cpy, buffer);
2176
tokens_count = cli_strtokenize(buffer, ':', CDB_TOKENS + 1, tokens);
2177
if(tokens_count > CDB_TOKENS || tokens_count < CDB_TOKENS - 2) {
2182
if(tokens_count > 10) { /* min version */
2183
if(!cli_isnumber(tokens[10])) {
2187
if((unsigned int) atoi(tokens[10]) > cl_retflevel()) {
2188
cli_dbgmsg("cli_loadcdb: Container signature for %s not loaded (required f-level: %u)\n", tokens[0], atoi(tokens[10]));
2191
if(tokens_count == CDB_TOKENS) { /* max version */
2192
if(!cli_isnumber(tokens[11])) {
2196
if((unsigned int) atoi(tokens[11]) < cl_retflevel())
2201
new = (struct cli_cdb *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_cdb));
2207
new->virname = cli_mpool_virname(engine->mempool, tokens[0], options & CL_DB_OFFICIAL);
2209
mpool_free(engine->mempool, new);
2214
if(engine->ignored && cli_chkign(engine->ignored, new->virname, buffer/*_cpy*/)) {
2215
mpool_free(engine->mempool, new->virname);
2216
mpool_free(engine->mempool, new);
2220
if(engine->cb_sigload && engine->cb_sigload("cdb", new->virname, engine->cb_sigload_ctx)) {
2221
cli_dbgmsg("cli_loadcdb: skipping %s due to callback\n", new->virname);
2222
mpool_free(engine->mempool, new->virname);
2223
mpool_free(engine->mempool, new);
2227
if(!strcmp(tokens[1], "*")) {
2228
new->ctype = CL_TYPE_ANY;
2229
} else if((new->ctype = cli_ftcode(tokens[1])) == CL_TYPE_ERROR) {
2230
cli_dbgmsg("cli_loadcdb: Unknown container type %s in signature for %s, skipping\n", tokens[1], tokens[0]);
2231
mpool_free(engine->mempool, new->virname);
2232
mpool_free(engine->mempool, new);
2236
if(strcmp(tokens[3], "*") && cli_regcomp(&new->name, tokens[3], REG_EXTENDED | REG_NOSUB)) {
2237
cli_errmsg("cli_loadcdb: Can't compile regular expression %s in signature for %s\n", tokens[3], tokens[0]);
2238
mpool_free(engine->mempool, new->virname);
2239
mpool_free(engine->mempool, new);
2244
#define CDBRANGE(token_str, dest) \
2245
if(strcmp(token_str, "*")) { \
2246
if(strchr(token_str, '-')) { \
2247
if(sscanf(token_str, "%u-%u", &n0, &n1) != 2) { \
2254
if(!cli_isnumber(token_str)) \
2257
dest[0] = dest[1] = atoi(token_str); \
2259
if(ret != CL_SUCCESS) { \
2260
cli_errmsg("cli_loadcdb: Invalid value %s in signature for %s\n",\
2261
token_str, tokens[0]); \
2262
if(new->name.re_magic) \
2263
cli_regfree(&new->name); \
2264
mpool_free(engine->mempool, new->virname); \
2265
mpool_free(engine->mempool, new); \
2270
dest[0] = dest[1] = CLI_OFF_ANY; \
2273
CDBRANGE(tokens[2], new->csize);
2274
CDBRANGE(tokens[4], new->fsizec);
2275
CDBRANGE(tokens[5], new->fsizer);
2276
CDBRANGE(tokens[7], new->filepos);
2278
if(!strcmp(tokens[6], "*")) {
2281
if(strcmp(tokens[6], "0") && strcmp(tokens[6], "1")) {
2282
cli_errmsg("cli_loadcdb: Invalid encryption flag value in signature for %s\n", tokens[0]);
2283
if(new->name.re_magic)
2284
cli_regfree(&new->name);
2285
mpool_free(engine->mempool, new->virname);
2286
mpool_free(engine->mempool, new);
2290
new->encrypted = *tokens[6] - 0x30;
2293
if(strcmp(tokens[9], "*")) {
2294
new->res2 = cli_mpool_strdup(engine->mempool, tokens[9]);
2296
cli_errmsg("cli_loadcdb: Can't allocate memory for res2 in signature for %s\n", tokens[0]);
2297
if(new->name.re_magic)
2298
cli_regfree(&new->name);
2299
mpool_free(engine->mempool, new->virname);
2300
mpool_free(engine->mempool, new);
2306
new->next = engine->cdb;
2314
cli_errmsg("Empty database file\n");
2319
cli_errmsg("Problem parsing database at line %u\n", line);
2329
static int cli_loaddbdir(const char *dirname, struct cl_engine *engine, unsigned int *signo, unsigned int options);
2331
int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio)
921
new->next = last->next;
926
if(!(*engine)->md5_hlist) {
927
cli_dbgmsg("Initializing md5 list structure\n");
928
(*engine)->md5_hlist = (struct cli_md5_node **) cli_calloc(256, sizeof(struct cli_md5_node *));
929
if(!(*engine)->md5_hlist) {
935
new->next = (*engine)->md5_hlist[new->md5[0] & 0xff];
936
(*engine)->md5_hlist[new->md5[0] & 0xff] = new;
941
cli_errmsg("Empty database file\n");
947
cli_errmsg("Problem parsing database at line %d\n", line);
958
static int cli_loadmd(FILE *fd, struct cl_engine **engine, unsigned int *signo, int type, unsigned int options)
960
char buffer[FILEBUFF], *pt;
961
int line = 0, comments = 0, ret = 0, crc32;
962
struct cli_meta_node *new;
965
if((ret = cli_initengine(engine, options))) {
970
while(fgets(buffer, FILEBUFF, fd)) {
972
if(buffer[0] == '#') {
979
new = (struct cli_meta_node *) cli_calloc(1, sizeof(struct cli_meta_node));
985
if(!(new->virname = cli_strtok(buffer, 0, ":"))) {
991
if(!(pt = cli_strtok(buffer, 1, ":"))) {
997
new->encrypted = atoi(pt);
1001
if(!(new->filename = cli_strtok(buffer, 2, ":"))) {
1007
if(!strcmp(new->filename, "*")) {
1008
free(new->filename);
1009
new->filename = NULL;
1013
if(!(pt = cli_strtok(buffer, 3, ":"))) {
1014
free(new->filename);
1020
if(!strcmp(pt, "*"))
1023
new->size = atoi(pt);
1027
if(!(pt = cli_strtok(buffer, 4, ":"))) {
1028
free(new->filename);
1034
if(!strcmp(pt, "*"))
1037
new->csize = atoi(pt);
1041
if(!(pt = cli_strtok(buffer, 5, ":"))) {
1042
free(new->filename);
1048
if(!strcmp(pt, "*")) {
1051
crc32 = cli_hex2num(pt);
1056
new->crc32 = (unsigned int) crc32;
1061
if(!(pt = cli_strtok(buffer, 6, ":"))) {
1062
free(new->filename);
1068
if(!strcmp(pt, "*"))
1071
new->method = atoi(pt);
1075
if(!(pt = cli_strtok(buffer, 7, ":"))) {
1076
free(new->filename);
1082
if(!strcmp(pt, "*"))
1085
new->fileno = atoi(pt);
1089
if(!(pt = cli_strtok(buffer, 8, ":"))) {
1090
free(new->filename);
1096
if(!strcmp(pt, "*"))
1099
new->maxdepth = atoi(pt);
1104
new->next = (*engine)->zip_mlist;
1105
(*engine)->zip_mlist = new;
1107
new->next = (*engine)->rar_mlist;
1108
(*engine)->rar_mlist = new;
1113
cli_errmsg("Empty database file\n");
1119
cli_errmsg("Problem parsing database at line %d\n", line);
1125
*signo += (line - comments);
1130
static int cli_loaddbdir(const char *dirname, struct cl_engine **engine, unsigned int *signo, unsigned int options);
1132
static int cli_load(const char *filename, struct cl_engine **engine, unsigned int *signo, unsigned int options)
2334
1135
int ret = CL_SUCCESS;
2335
1136
uint8_t skipped = 0;
2337
char buff[FILEBUFF];
2340
if(dbio && dbio->chkonly) {
2341
while(cli_dbgets(buff, FILEBUFF, NULL, dbio));
2345
if(!dbio && (fs = fopen(filename, "rb")) == NULL) {
2346
if(options & CL_DB_DIRECTORY) { /* bb#1624 */
2347
if(access(filename, R_OK)) {
2348
if(errno == ENOENT) {
2349
cli_dbgmsg("Detected race condition, ignoring old file %s\n", filename);
1139
if(cli_strbcasestr(filename, ".inc"))
1140
return cli_loaddbdir(filename, engine, signo, options);
1142
if((fd = fopen(filename, "rb")) == NULL) {
2354
1143
cli_errmsg("cli_load(): Can't open file %s\n", filename);
2355
1144
return CL_EOPEN;
2358
if((dbname = strrchr(filename, *PATHSEP)))
2363
if(cli_strbcasestr(dbname, ".db")) {
2364
ret = cli_loaddb(fs, engine, signo, options, dbio, dbname);
2366
} else if(cli_strbcasestr(dbname, ".cvd")) {
2367
ret = cli_cvdload(fs, engine, signo, options, 0, filename, 0);
2369
} else if(cli_strbcasestr(dbname, ".cld")) {
2370
ret = cli_cvdload(fs, engine, signo, options, 1, filename, 0);
2372
} else if(cli_strbcasestr(dbname, ".hdb") || cli_strbcasestr(dbname, ".hsb")) {
2373
ret = cli_loadhash(fs, engine, signo, MD5_HDB, options, dbio, dbname);
2374
} else if(cli_strbcasestr(dbname, ".hdu") || cli_strbcasestr(dbname, ".hsu")) {
2375
if(options & CL_DB_PUA)
2376
ret = cli_loadhash(fs, engine, signo, MD5_HDB, options | CL_DB_PUA_MODE, dbio, dbname);
2380
} else if(cli_strbcasestr(dbname, ".fp") || cli_strbcasestr(dbname, ".sfp")) {
2381
ret = cli_loadhash(fs, engine, signo, MD5_FP, options, dbio, dbname);
2382
} else if(cli_strbcasestr(dbname, ".mdb") || cli_strbcasestr(dbname, ".msb")) {
2383
ret = cli_loadhash(fs, engine, signo, MD5_MDB, options, dbio, dbname);
2385
} else if(cli_strbcasestr(dbname, ".mdu") || cli_strbcasestr(dbname, ".msu")) {
2386
if(options & CL_DB_PUA)
2387
ret = cli_loadhash(fs, engine, signo, MD5_MDB, options | CL_DB_PUA_MODE, dbio, dbname);
2391
} else if(cli_strbcasestr(dbname, ".ndb")) {
2392
ret = cli_loadndb(fs, engine, signo, 0, options, dbio, dbname);
2394
} else if(cli_strbcasestr(dbname, ".ndu")) {
2395
if(!(options & CL_DB_PUA))
2398
ret = cli_loadndb(fs, engine, signo, 0, options | CL_DB_PUA_MODE, dbio, dbname);
2400
} else if(cli_strbcasestr(filename, ".ldb")) {
2401
ret = cli_loadldb(fs, engine, signo, options, dbio, dbname);
2403
} else if(cli_strbcasestr(filename, ".ldu")) {
2404
if(options & CL_DB_PUA)
2405
ret = cli_loadldb(fs, engine, signo, options | CL_DB_PUA_MODE, dbio, dbname);
2408
} else if(cli_strbcasestr(filename, ".cbc")) {
2409
if(options & CL_DB_BYTECODE)
2410
ret = cli_loadcbc(fs, engine, signo, options, dbio, dbname);
2413
} else if(cli_strbcasestr(dbname, ".sdb")) {
2414
ret = cli_loadndb(fs, engine, signo, 1, options, dbio, dbname);
2416
} else if(cli_strbcasestr(dbname, ".zmd")) {
2417
ret = cli_loadmd(fs, engine, signo, 1, options, dbio, dbname);
2419
} else if(cli_strbcasestr(dbname, ".rmd")) {
2420
ret = cli_loadmd(fs, engine, signo, 2, options, dbio, dbname);
2422
} else if(cli_strbcasestr(dbname, ".cfg")) {
2423
ret = cli_dconf_load(fs, engine, options, dbio);
2425
} else if(cli_strbcasestr(dbname, ".info")) {
2426
ret = cli_loadinfo(fs, engine, options, dbio);
2428
} else if(cli_strbcasestr(dbname, ".wdb")) {
2429
if(options & CL_DB_PHISHING_URLS) {
2430
ret = cli_loadwdb(fs, engine, options, dbio);
2433
} else if(cli_strbcasestr(dbname, ".pdb") || cli_strbcasestr(dbname, ".gdb")) {
2434
if(options & CL_DB_PHISHING_URLS) {
2435
ret = cli_loadpdb(fs, engine, signo, options, dbio);
2438
} else if(cli_strbcasestr(dbname, ".ftm")) {
2439
ret = cli_loadftm(fs, engine, options, 0, dbio);
2441
} else if(cli_strbcasestr(dbname, ".ign") || cli_strbcasestr(dbname, ".ign2")) {
2442
ret = cli_loadign(fs, engine, options, dbio);
2444
} else if(cli_strbcasestr(dbname, ".idb")) {
2445
ret = cli_loadidb(fs, engine, signo, options, dbio);
2447
} else if(cli_strbcasestr(dbname, ".cdb")) {
2448
ret = cli_loadcdb(fs, engine, signo, options, dbio);
1147
if(cli_strbcasestr(filename, ".db")) {
1148
if(options & CL_DB_NCORE)
1151
ret = cli_loaddb(fd, engine, signo, options);
1153
} else if(cli_strbcasestr(filename, ".cvd")) {
1156
if(strstr(filename, "daily.cvd"))
1159
ret = cli_cvdload(fd, engine, signo, warn, options);
1161
} else if(cli_strbcasestr(filename, ".hdb")) {
1162
ret = cli_loadhdb(fd, engine, signo, 0, options);
1164
} else if(cli_strbcasestr(filename, ".fp")) {
1165
ret = cli_loadhdb(fd, engine, signo, 1, options);
1167
} else if(cli_strbcasestr(filename, ".mdb")) {
1168
ret = cli_loadhdb(fd, engine, signo, 2, options);
1170
} else if(cli_strbcasestr(filename, ".ndb")) {
1171
if(options & CL_DB_NCORE)
1174
ret = cli_loadndb(fd, engine, signo, 0, options);
1176
} else if(cli_strbcasestr(filename, ".sdb")) {
1177
/* FIXME: Add support in ncore mode */
1178
if(options & CL_DB_NCORE)
1181
ret = cli_loadndb(fd, engine, signo, 1, options);
1183
} else if(cli_strbcasestr(filename, ".zmd")) {
1184
ret = cli_loadmd(fd, engine, signo, 1, options);
1186
} else if(cli_strbcasestr(filename, ".rmd")) {
1187
ret = cli_loadmd(fd, engine, signo, 2, options);
1189
} else if(cli_strbcasestr(filename, ".cfg")) {
1190
ret = cli_dconf_load(fd, engine, options);
1192
} else if(cli_strbcasestr(filename, ".ncdb")) {
1194
if(options & CL_DB_NCORE)
1195
ret = cli_ncore_load(filename, engine, signo, options);
1199
#ifdef CL_EXPERIMENTAL
1200
} else if(cli_strbcasestr(filename, ".wdb")) {
1201
if(options & CL_DB_PHISHING_URLS)
1202
ret = cli_loadwdb(fd, engine, options);
1205
} else if(cli_strbcasestr(filename, ".pdb")) {
1206
if(options & CL_DB_PHISHING_URLS)
1207
ret = cli_loadpdb(fd, engine, options);
2450
1212
cli_dbgmsg("cli_load: unknown extension - assuming old database format\n");
2451
ret = cli_loaddb(fs, engine, signo, options, dbio, dbname);
1213
ret = cli_loaddb(fd, engine, signo, options);