212
194
(unsigned int) metadata->unpack_size, metadata->method,
213
195
metadata->pack_size ? (unsigned int) (metadata->unpack_size / metadata->pack_size) : 0);
216
mdata = ctx->engine->rar_mlist;
218
if(mdata->encrypted != metadata->encrypted)
221
if(mdata->crc32 && (unsigned int) mdata->crc32 != metadata->crc)
224
if(mdata->csize > 0 && (unsigned int) mdata->csize != metadata->pack_size)
227
if(mdata->size >= 0 && (unsigned int) mdata->size != metadata->unpack_size)
230
if(mdata->method >= 0 && mdata->method != metadata->method)
233
if(mdata->fileno && mdata->fileno != files)
236
if(mdata->maxdepth && ctx->recursion > mdata->maxdepth)
239
if(mdata->filename && !cli_matchregex(metadata->filename, mdata->filename))
244
} while((mdata = mdata->next));
247
*ctx->virname = mdata->virname;
248
return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
197
if(cli_matchmeta(ctx, metadata->filename, metadata->pack_size, metadata->unpack_size, metadata->encrypted, files, metadata->crc, NULL) == CL_VIRUS)
251
200
if(DETECT_ENCRYPTED && metadata->encrypted) {
252
201
cli_dbgmsg("RAR: Encrypted files found in archive.\n");
253
202
lseek(desc, 0, SEEK_SET);
254
ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR);
203
ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR, NULL);
255
204
if(ret != CL_VIRUS) {
256
*ctx->virname = "Encrypted.RAR";
205
cli_append_virus(ctx, "Heuristics.Encrypted.RAR");
465
static int cli_scangzip(int desc, cli_ctx *ctx)
428
static int cli_scangzip_with_zib_from_the_80s(cli_ctx *ctx, unsigned char *buff) {
429
int fd, ret, outsize = 0, bytes;
430
fmap_t *map = *ctx->fmap;
438
lseek(fd, 0, SEEK_SET);
439
if(!(gz = gzdopen(fd, "rb"))) {
444
if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
445
cli_dbgmsg("GZip: Can't generate temporary file.\n");
450
while((bytes = gzread(gz, buff, FILEBUFF)) > 0) {
452
if(cli_checklimits("GZip", ctx, outsize, 0, 0)!=CL_CLEAN)
454
if(cli_writen(fd, buff, bytes) != bytes) {
457
if(cli_unlink(tmpname)) {
468
if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS) {
469
cli_dbgmsg("GZip: Infected with %s\n", cli_get_last_virus(ctx));
471
if(!ctx->engine->keeptmp) {
472
if (cli_unlink(tmpname)) {
481
if(!ctx->engine->keeptmp)
482
if (cli_unlink(tmpname)) ret = CL_EUNLINK;
487
static int cli_scangzip(cli_ctx *ctx)
467
int fd, bytes, ret = CL_CLEAN;
468
unsigned long int size = 0;
489
int fd, ret = CL_CLEAN;
490
unsigned char buff[FILEBUFF];
493
size_t at = 0, outsize = 0;
494
fmap_t *map = *ctx->fmap;
474
496
cli_dbgmsg("in cli_scangzip()\n");
476
if((gd = gzdopen(dup(desc), "rb")) == NULL) {
477
cli_dbgmsg("GZip: Can't open descriptor %d\n", desc);
498
memset(&z, 0, sizeof(z));
499
if((ret = inflateInit2(&z, MAX_WBITS + 16)) != Z_OK) {
500
cli_dbgmsg("GZip: InflateInit failed: %d\n", ret);
501
return cli_scangzip_with_zib_from_the_80s(ctx, buff);
481
if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd))) {
504
if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
482
505
cli_dbgmsg("GZip: Can't generate temporary file.\n");
487
if(!(buff = (char *) cli_malloc(FILEBUFF))) {
488
cli_dbgmsg("GZip: Unable to malloc %u bytes.\n", FILEBUFF);
491
if(!ctx->engine->keeptmp) {
492
if(cli_unlink(tmpname)) {
500
while((bytes = gzread(gd, buff, FILEBUFF)) > 0) {
503
if(cli_checklimits("GZip", ctx, size + FILEBUFF, 0, 0)!=CL_CLEAN)
506
if(cli_writen(fd, buff, bytes) != bytes) {
507
cli_dbgmsg("GZip: Can't write to file.\n");
510
while (at < map->len) {
511
unsigned int bytes = MIN(map->len - at, map->pgsz);
512
if(!(z.next_in = fmap_need_off_once(map, at, bytes))) {
513
cli_dbgmsg("GZip: Can't read %u bytes @ %lu.\n", bytes, (long unsigned)at);
509
if(!ctx->engine->keeptmp) {
510
if (cli_unlink(tmpname)) {
516
if (cli_unlink(tmpname)) {
527
z.avail_out = sizeof(buff);
529
inf = inflate(&z, Z_NO_FLUSH);
530
if(inf != Z_OK && inf != Z_STREAM_END && inf != Z_BUF_ERROR) {
531
cli_dbgmsg("GZip: Bad stream.\n");
535
if(cli_writen(fd, buff, sizeof(buff) - z.avail_out) < 0) {
538
if (cli_unlink(tmpname)) {
514
540
return CL_EUNLINK;
527
if(ret == CL_VIRUS) {
529
if(!ctx->engine->keeptmp)
530
if (cli_unlink(tmpname)) ret = CL_EUNLINK;
535
lseek(fd, 0, SEEK_SET);
536
if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS ) {
537
cli_dbgmsg("GZip: Infected with %s\n", *ctx->virname);
545
outsize += sizeof(buff) - z.avail_out;
546
if(cli_checklimits("GZip", ctx, outsize, 0, 0)!=CL_CLEAN) {
550
if(inf == Z_STREAM_END) {
555
} while (z.avail_out == 0);
560
if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS) {
561
cli_dbgmsg("GZip: Infected with %s\n", cli_get_last_virus(ctx));
539
563
if(!ctx->engine->keeptmp) {
540
564
if (cli_unlink(tmpname)) {
716
740
for(file = cab.files; file; file = file->next) {
743
if(cli_matchmeta(ctx, file->name, 0, file->length, 0, files, 0, NULL) == CL_VIRUS) {
751
if(ctx->engine->maxscansize && ctx->scansize >= ctx->engine->maxscansize) {
719
756
if(!(tempname = cli_gentemp(ctx->engine->tmpdir))) {
724
if(ctx->engine->maxscansize && ctx->scansize >= ctx->engine->maxscansize) {
728
761
if(ctx->engine->maxscansize && ctx->scansize + ctx->engine->maxfilesize >= ctx->engine->maxscansize)
729
762
file->max_size = ctx->engine->maxscansize - ctx->scansize;
731
file->max_size = ctx->engine->maxfilesize;
764
file->max_size = ctx->engine->maxfilesize ? ctx->engine->maxfilesize : 0xffffffff;
733
766
cli_dbgmsg("CAB: Extracting file %s to %s, size %u, max_size: %u\n", file->name, tempname, file->length, (unsigned int) file->max_size);
734
767
file->written_size = 0;
735
768
if((ret = cab_extract(file, tempname))) {
736
769
cli_dbgmsg("CAB: Failed to extract file: %s\n", cl_strerror(ret));
738
if(file->length != file->written_size)
771
corrupted_input = ctx->corrupted_input;
772
if(file->length != file->written_size) {
739
773
cli_dbgmsg("CAB: Length from header %u but wrote %u bytes\n", (unsigned int) file->length, (unsigned int) file->written_size);
774
ctx->corrupted_input = 1;
741
776
ret = cli_scanfile(tempname, ctx);
777
ctx->corrupted_input = corrupted_input;
743
779
if(!ctx->engine->keeptmp) {
744
if (cli_unlink(tempname)) {
780
if (!access(tempname, R_OK) && cli_unlink(tempname)) {
746
782
ret = CL_EUNLINK;
787
if(ret == CL_VIRUS) {
801
static int vba_scandata(const unsigned char *data, unsigned int len, cli_ctx *ctx)
803
struct cli_matcher *groot = ctx->engine->root[0];
804
struct cli_matcher *troot = ctx->engine->root[2];
805
struct cli_ac_data gmdata, tmdata;
806
struct cli_ac_data *mdata[2];
808
unsigned int viruses_found = 0;
810
if((ret = cli_ac_initdata(&tmdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
813
if((ret = cli_ac_initdata(&gmdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) {
814
cli_ac_freedata(&tmdata);
820
ret = cli_scanbuff(data, len, 0, ctx, CL_TYPE_MSOLE2, mdata);
822
if(ret != CL_VIRUS || SCAN_ALL) {
825
ret = cli_lsig_eval(ctx, troot, &tmdata, NULL, NULL);
826
if(ret != CL_VIRUS || SCAN_ALL)
829
ret = cli_lsig_eval(ctx, groot, &gmdata, NULL, NULL);
831
cli_ac_freedata(&tmdata);
832
cli_ac_freedata(&gmdata);
759
839
static int cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U)
761
int ret = CL_CLEAN, i, j, fd, data_len;
841
int ret = CL_CLEAN, i, j, fd, data_len, hasmacros = 0;
762
842
vba_project_t *vba_project;
764
844
struct dirent *dent;
975
1077
cli_dbgmsg("cli_scanhtml: using tempdir %s\n", tempname);
977
html_normalise_fd(desc, tempname, NULL, ctx->dconf);
978
snprintf(fullname, 1024, "%s/nocomment.html", tempname);
1079
html_normalise_map(map, tempname, NULL, ctx->dconf);
1080
snprintf(fullname, 1024, "%s"PATHSEP"nocomment.html", tempname);
979
1081
fd = open(fullname, O_RDONLY|O_BINARY);
981
ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR);
1083
if ((ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL)) == CL_VIRUS)
985
if(ret == CL_CLEAN && sb.st_size < 2097152) {
1088
if((ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) && map->len < 2097152) {
986
1089
/* limit to 2 MB, we're not interesting in scanning large files in notags form */
987
1090
/* TODO: don't even create notags if file is over 2 MB */
988
snprintf(fullname, 1024, "%s/notags.html", tempname);
989
fd = open(fullname, O_RDONLY|O_BINARY);
991
ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR);
996
if(ret == CL_CLEAN) {
997
snprintf(fullname, 1024, "%s/javascript", tempname);
998
fd = open(fullname, O_RDONLY|O_BINARY);
1000
ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR);
1001
if (ret == CL_CLEAN) {
1002
lseek(fd, 0, SEEK_SET);
1003
ret = cli_scandesc(fd, ctx, CL_TYPE_TEXT_ASCII, 0, NULL, AC_SCAN_VIR);
1009
if (ret == CL_CLEAN) {
1010
snprintf(fullname, 1024, "%s/rfc2397", tempname);
1011
ret = cli_scandir(fullname, ctx, 0);
1091
snprintf(fullname, 1024, "%s"PATHSEP"notags.html", tempname);
1092
fd = open(fullname, O_RDONLY|O_BINARY);
1094
if ((ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL)) == CL_VIRUS)
1100
if(ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) {
1101
snprintf(fullname, 1024, "%s"PATHSEP"javascript", tempname);
1102
fd = open(fullname, O_RDONLY|O_BINARY);
1104
if ((ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL)) == CL_VIRUS)
1106
if (ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) {
1107
if ((ret = cli_scandesc(fd, ctx, CL_TYPE_TEXT_ASCII, 0, NULL, AC_SCAN_VIR, NULL)) == CL_VIRUS)
1114
if (ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) {
1115
snprintf(fullname, 1024, "%s"PATHSEP"rfc2397", tempname);
1116
ret = cli_scandir(fullname, ctx);
1014
1119
if(!ctx->engine->keeptmp)
1015
1120
cli_rmdirs(tempname);
1017
1122
free(tempname);
1123
if (SCAN_ALL && viruses_found)
1021
static int cli_scanscript(int desc, cli_ctx *ctx)
1128
static int cli_scanscript(cli_ctx *ctx)
1023
unsigned char buff[FILEBUFF];
1130
unsigned char *buff;
1024
1131
unsigned char* normalized;
1025
1132
struct text_norm_state state;
1027
1133
char *tmpname = NULL;
1028
1134
int ofd = -1, ret;
1030
const struct cli_matcher *troot = ctx->engine->root[7];
1135
struct cli_matcher *troot = ctx->engine->root[7];
1031
1136
uint32_t maxpatlen = troot ? troot->maxpatlen : 0, offset = 0;
1032
1137
struct cli_matcher *groot = ctx->engine->root[0];
1033
1138
struct cli_ac_data gmdata, tmdata;
1034
1139
struct cli_ac_data *mdata[2];
1140
fmap_t *map = *ctx->fmap;
1142
unsigned int viruses_found = 0;
1036
1144
cli_dbgmsg("in cli_scanscript()\n");
1038
if(fstat(desc, &sb) == -1) {
1039
cli_errmsg("cli_scanscript: fstat() failed for descriptor %d\n", desc);
1043
/* don't normalize files that are too large */
1044
if(sb.st_size > 5242880) {
1146
if(map->len > 5242880) {
1045
1147
cli_dbgmsg("cli_scanscript: exiting (file larger than 5 MB)\n");
1046
1148
return CL_CLEAN;
1063
1166
text_normalize_init(&state, normalized, SCANBUFF + maxpatlen);
1064
1167
ret = CL_CLEAN;
1066
if ((ret = cli_ac_initdata(&tmdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
1169
if ((ret = cli_ac_initdata(&tmdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
1069
if ((ret = cli_ac_initdata(&gmdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN))) {
1172
if ((ret = cli_ac_initdata(&gmdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) {
1070
1173
cli_ac_freedata(&tmdata);
1073
1176
mdata[0] = &tmdata;
1074
1177
mdata[1] = &gmdata;
1077
nread = cli_readn(desc, buff, sizeof(buff));
1078
if(nread <= 0 || state.out_pos + nread > state.out_len) {
1079
/* flush if error/EOF, or too little buffer space left */
1080
if((ofd != -1) && (write(ofd, state.out, state.out_pos) == -1)) {
1081
cli_errmsg("cli_scanscript: can't write to file %s\n",tmpname);
1084
/* we can continue to scan in memory */
1086
/* when we flush the buffer also scan */
1087
if(cli_scanbuff(state.out, state.out_pos, offset, ctx, CL_TYPE_TEXT_ASCII, mdata) == CL_VIRUS) {
1090
ret = cli_checkfp(ofd, ctx) ? CL_CLEAN : CL_VIRUS;
1094
*ctx->scanned += state.out_pos / CL_COUNT_PRECISION;
1095
offset += state.out_pos;
1096
/* carry over maxpatlen from previous buffer */
1097
if (state.out_pos > maxpatlen)
1098
memmove(state.out, state.out + state.out_pos - maxpatlen, maxpatlen);
1099
text_normalize_reset(&state);
1100
state.out_pos = maxpatlen;
1102
if(nread > 0 && (text_normalize_buffer(&state, buff, nread) != nread)) {
1103
cli_dbgmsg("cli_scanscript: short read during normalizing\n");
1105
/* used a do {}while() here, since we need to flush our buffers at the end,
1106
* and using while(){} loop would mean code duplication */
1107
} while (nread > 0);
1109
cli_ac_freedata(&tmdata);
1110
cli_ac_freedata(&gmdata);
1180
size_t len = MIN(map->pgsz, map->len - at);
1181
buff = fmap_need_off_once(map, at, len);
1183
if(!buff || !len || state.out_pos + len > state.out_len) {
1184
/* flush if error/EOF, or too little buffer space left */
1185
if((ofd != -1) && (write(ofd, state.out, state.out_pos) == -1)) {
1186
cli_errmsg("cli_scanscript: can't write to file %s\n",tmpname);
1189
/* we can continue to scan in memory */
1191
/* when we flush the buffer also scan */
1192
if(cli_scanbuff(state.out, state.out_pos, offset, ctx, CL_TYPE_TEXT_ASCII, mdata) == CL_VIRUS) {
1201
*ctx->scanned += state.out_pos / CL_COUNT_PRECISION;
1202
offset += state.out_pos;
1203
/* carry over maxpatlen from previous buffer */
1204
if (state.out_pos > maxpatlen)
1205
memmove(state.out, state.out + state.out_pos - maxpatlen, maxpatlen);
1206
text_normalize_reset(&state);
1207
state.out_pos = maxpatlen;
1210
if(text_normalize_buffer(&state, buff, len) != len) {
1211
cli_dbgmsg("cli_scanscript: short read during normalizing\n");
1111
1214
if(ctx->engine->keeptmp) {
1115
1218
free(normalized);
1219
if(ret != CL_VIRUS || SCAN_ALL) {
1220
if ((ret = cli_lsig_eval(ctx, troot, &tmdata, NULL, NULL)) == CL_VIRUS)
1222
if(ret != CL_VIRUS || SCAN_ALL)
1223
if ((ret = cli_lsig_eval(ctx, groot, &gmdata, NULL, NULL)) == CL_VIRUS)
1226
cli_ac_freedata(&tmdata);
1227
cli_ac_freedata(&gmdata);
1229
if (SCAN_ALL && viruses_found)
1120
static int cli_scanhtml_utf16(int desc, cli_ctx *ctx)
1234
static int cli_scanhtml_utf16(cli_ctx *ctx)
1122
char *tempname, buff[512], *decoded;
1236
char *tempname, *decoded, *buff;
1123
1237
int ret = CL_CLEAN, fd, bytes;
1239
fmap_t *map = *ctx->fmap;
1126
1241
cli_dbgmsg("in cli_scanhtml_utf16()\n");
1731
1872
acmode |= AC_SCAN_FT;
1733
if(lseek(desc, 0, SEEK_SET) < 0) {
1734
cli_errmsg("cli_scanraw: lseek() failed\n");
1738
ret = cli_scandesc(desc, ctx, type == CL_TYPE_TEXT_ASCII ? 0 : type, 0, &ftoffset, acmode);
1874
ret = cli_fmap_scandesc(ctx, type == CL_TYPE_TEXT_ASCII ? 0 : type, 0, &ftoffset, acmode, NULL, refhash);
1740
1876
if(ret >= CL_TYPENO) {
1741
1877
ctx->recursion++;
1744
if(type == CL_TYPE_TEXT_ASCII) {
1745
lseek(desc, 0, SEEK_SET);
1747
nret = cli_scandesc(desc, ctx, 0, ret, 1, NULL);
1748
if(nret == CL_VIRUS)
1749
cli_dbgmsg("%s found in descriptor %d when scanning file type %u\n", *ctx->virname, desc, ret);
1753
1878
if(nret != CL_VIRUS) {
1754
1879
lastzip = lastrar = 0xdeadbeef;
1755
1880
fpt = ftoffset;
1757
1882
if(fpt->offset) switch(fpt->type) {
1758
1883
case CL_TYPE_RARSFX:
1759
cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
1760
1884
if(type != CL_TYPE_RAR && have_rar && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR)) {
1885
ctx->container_type = CL_TYPE_RAR;
1886
ctx->container_size = map->len - fpt->offset; /* not precise */
1761
1887
cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
1762
nret = cli_scanrar(desc, ctx, fpt->offset, &lastrar);
1888
nret = cli_scanrar(map->fd, ctx, fpt->offset, &lastrar);
1766
1892
case CL_TYPE_ZIPSFX:
1767
1893
if(type != CL_TYPE_ZIP && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) {
1894
ctx->container_type = CL_TYPE_ZIP;
1895
ctx->container_size = map->len - fpt->offset; /* not precise */
1768
1896
cli_dbgmsg("ZIP/ZIP-SFX signature found at %u\n", (unsigned int) fpt->offset);
1769
nret = cli_unzip_single(desc, ctx, fpt->offset);
1897
nret = cli_unzip_single(ctx, fpt->offset);
1773
1901
case CL_TYPE_CABSFX:
1774
1902
if(type != CL_TYPE_MSCAB && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CAB)) {
1903
ctx->container_type = CL_TYPE_MSCAB;
1904
ctx->container_size = map->len - fpt->offset; /* not precise */
1775
1905
cli_dbgmsg("CAB/CAB-SFX signature found at %u\n", (unsigned int) fpt->offset);
1776
nret = cli_scanmscab(desc, ctx, fpt->offset);
1906
nret = cli_scanmscab(map->fd, ctx, fpt->offset);
1779
1909
case CL_TYPE_ARJSFX:
1780
1910
if(type != CL_TYPE_ARJ && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ARJ)) {
1911
ctx->container_type = CL_TYPE_ARJ;
1912
ctx->container_size = map->len - fpt->offset; /* not precise */
1781
1913
cli_dbgmsg("ARJ-SFX signature found at %u\n", (unsigned int) fpt->offset);
1782
nret = cli_scanarj(desc, ctx, fpt->offset, &lastrar);
1914
nret = cli_scanarj(map->fd, ctx, fpt->offset, &lastrar);
1786
1918
case CL_TYPE_NULSFT:
1787
1919
if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_NSIS) && fpt->offset > 4) {
1920
ctx->container_type = CL_TYPE_NULSFT;
1921
ctx->container_size = map->len - fpt->offset; /* not precise */
1788
1922
cli_dbgmsg("NSIS signature found at %u\n", (unsigned int) fpt->offset-4);
1789
nret = cli_scannulsft(desc, ctx, fpt->offset - 4);
1923
nret = cli_scannulsft(map->fd, ctx, fpt->offset - 4);
1793
1927
case CL_TYPE_AUTOIT:
1794
1928
if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_AUTOIT)) {
1929
ctx->container_type = CL_TYPE_AUTOIT;
1930
ctx->container_size = map->len - fpt->offset; /* not precise */
1795
1931
cli_dbgmsg("AUTOIT signature found at %u\n", (unsigned int) fpt->offset);
1796
nret = cli_scanautoit(desc, ctx, fpt->offset + 23);
1932
nret = cli_scanautoit(ctx, fpt->offset + 23);
1936
case CL_TYPE_ISHIELD_MSI:
1937
if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_ISHIELD)) {
1938
ctx->container_type = CL_TYPE_AUTOIT;
1939
ctx->container_size = map->len - fpt->offset; /* not precise */
1940
cli_dbgmsg("ISHIELD-MSI signature found at %u\n", (unsigned int) fpt->offset);
1941
nret = cli_scanishield_msi(ctx, fpt->offset + 14);
1800
1945
case CL_TYPE_PDF:
1801
1946
if(type != CL_TYPE_PDF && SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF)) {
1947
ctx->container_type = CL_TYPE_PDF;
1948
ctx->container_size = map->len - fpt->offset; /* not precise */
1802
1949
cli_dbgmsg("PDF signature found at %u\n", (unsigned int) fpt->offset);
1803
nret = cli_scanpdf(desc, ctx, fpt->offset);
1950
nret = cli_scanpdf(ctx, fpt->offset);
1807
1954
case CL_TYPE_MSEXE:
1808
1955
if(SCAN_PE && (type == CL_TYPE_MSEXE || type == CL_TYPE_ZIP || type == CL_TYPE_MSOLE2) && ctx->dconf->pe) {
1810
if(sb.st_size > 10485760)
1956
if(map->len > 10485760)
1958
ctx->container_type = CL_TYPE_MSEXE; /* PE is a container for another executable here */
1959
ctx->container_size = map->len - fpt->offset; /* not precise */
1812
1960
memset(&peinfo, 0, sizeof(struct cli_exe_info));
1813
1961
peinfo.offset = fpt->offset;
1814
lseek(desc, fpt->offset, SEEK_SET);
1815
if(cli_peheader(desc, &peinfo) == 0) {
1962
if(cli_peheader(map, &peinfo) == 0) {
1816
1963
cli_dbgmsg("*** Detected embedded PE file at %u ***\n", (unsigned int) fpt->offset);
1817
1964
if(peinfo.section)
1818
1965
free(peinfo.section);
1966
cli_hashset_destroy(&peinfo.vinfo);
1820
lseek(desc, fpt->offset, SEEK_SET);
1821
nret = cli_scanembpe(desc, ctx);
1968
nret = cli_scanembpe(ctx, fpt->offset);
1822
1969
break_loop = 1; /* we can stop here and other
1823
1970
* embedded executables will
1824
1971
* be found recursively
1868
2023
if(ret == CL_VIRUS)
1869
cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
2024
cli_dbgmsg("%s found\n", cli_get_last_virus(ctx));
1874
int cli_magic_scandesc(int desc, cli_ctx *ctx)
2030
static void emax_reached(cli_ctx *ctx) {
2031
fmap_t **ctx_fmap = ctx->fmap;
2035
fmap_t *map = *ctx_fmap;
2036
map->dont_cache_flag = 1;
2039
cli_dbgmsg("emax_reached: marked parents as non cacheable\n");
2042
#define LINESTR(x) #x
2043
#define LINESTR2(x) LINESTR(x)
2044
#define __AT__ " at line "LINESTR2(__LINE__)
2045
#define ret_from_magicscan(retcode) do { \
2046
cli_dbgmsg("cli_magic_scandesc: returning %d %s\n", retcode, __AT__); \
2047
if(ctx->engine->cb_post_scan) { \
2048
switch(ctx->engine->cb_post_scan(desc, retcode, retcode == CL_VIRUS ? cli_get_last_virus(ctx) : NULL, ctx->cb_ctx)) { \
2050
cli_dbgmsg("cli_magic_scandesc: file whitelisted by callback\n"); \
2053
cli_dbgmsg("cli_magic_scandesc: file blacklisted by callback\n"); \
2054
cli_append_virus(ctx, "Detected.By.Callback"); \
2059
cli_warnmsg("cli_magic_scandesc: ignoring bad return code from callback\n"); \
2065
static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
1877
cli_file_t type, dettype = 0;
2067
int ret = CL_CLEAN, res;
2068
cli_file_t dettype = 0;
1878
2069
struct stat sb;
1879
2070
uint8_t typercg = 1;
2071
cli_file_t current_container_type = ctx->container_type;
2072
size_t current_container_size = ctx->container_size, hashed_size;
2073
unsigned char hash[16];
2074
bitset_t *old_hook_lsig_matches;
2075
unsigned int viruses_found = 0;
2077
#ifdef HAVE__INTERNAL__SHA_COLLECT
2078
if(ctx->sha_collect>0) ctx->sha_collect = 0;
2081
cli_dbgmsg("in cli_magic_scandesc (reclevel: %u/%u)\n", ctx->recursion, ctx->engine->maxreclevel);
1881
2082
if(ctx->engine->maxreclevel && ctx->recursion > ctx->engine->maxreclevel) {
1882
2083
cli_dbgmsg("cli_magic_scandesc: Archive recursion limit exceeded (%u, max: %u)\n", ctx->recursion, ctx->engine->maxreclevel);
2085
ret_from_magicscan(CL_CLEAN);
1886
2088
if(fstat(desc, &sb) == -1) {
1887
2089
cli_errmsg("magic_scandesc: Can't fstat descriptor %d\n", desc);
2090
ret_from_magicscan(CL_ESTAT);
1891
2093
if(sb.st_size <= 5) {
1892
2094
cli_dbgmsg("Small data (%u bytes)\n", (unsigned int) sb.st_size);
2095
ret_from_magicscan(CL_CLEAN);
1896
2098
if(!ctx->engine) {
1897
2099
cli_errmsg("CRITICAL: engine == NULL\n");
2100
ret_from_magicscan(CL_ENULLARG);
1901
2103
if(!(ctx->engine->dboptions & CL_DB_COMPILED)) {
1902
2104
cli_errmsg("CRITICAL: engine not compiled\n");
1906
if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN)
1909
if(!ctx->options || (ctx->recursion == ctx->engine->maxreclevel)) { /* raw mode (stdin, etc.) or last level of recursion */
2105
ret_from_magicscan(CL_EMALFDB);
2108
if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN) {
2110
ret_from_magicscan(CL_CLEAN);
2114
if(!(*ctx->fmap = fmap(desc, 0, sb.st_size))) {
2115
cli_errmsg("CRITICAL: fmap() failed\n");
2117
ret_from_magicscan(CL_EMEM);
2120
if(ctx->engine->cb_pre_scan) {
2121
switch(ctx->engine->cb_pre_scan(desc, ctx->cb_ctx)) {
2123
cli_dbgmsg("cli_magic_scandesc: file whitelisted by callback\n");
2126
ret_from_magicscan(CL_CLEAN);
2128
cli_dbgmsg("cli_magic_scandesc: file blacklisted by callback\n");
2129
cli_append_virus(ctx, "Detected.By.Callback");
2132
ret_from_magicscan(CL_VIRUS);
2136
cli_warnmsg("cli_magic_scandesc: ignoring bad return code from callback\n");
2140
res = cache_check(hash, ctx);
2141
if(res != CL_VIRUS) {
2144
ret_from_magicscan(res);
2146
hashed_size = (*ctx->fmap)->len;
2147
old_hook_lsig_matches = ctx->hook_lsig_matches;
2148
ctx->hook_lsig_matches = NULL;
2150
if(!(ctx->options&~CL_SCAN_ALLMATCHES) || (ctx->recursion == ctx->engine->maxreclevel)) { /* raw mode (stdin, etc.) or last level of recursion */
1910
2151
if(ctx->recursion == ctx->engine->maxreclevel)
1911
2152
cli_dbgmsg("cli_magic_scandesc: Hit recursion limit, only scanning raw file\n");
1913
2154
cli_dbgmsg("Raw mode: No support for special files\n");
1914
if((ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR)) == CL_VIRUS)
1915
cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
2156
if((ret = cli_fmap_scandesc(ctx, 0, 0, NULL, AC_SCAN_VIR, NULL, hash)) == CL_VIRUS)
2157
cli_dbgmsg("%s found in descriptor %d\n", cli_get_last_virus(ctx), desc);
2158
else if(ret == CL_CLEAN) {
2159
if(ctx->recursion != ctx->engine->maxreclevel)
2160
cache_add(hash, hashed_size, ctx); /* Only cache if limits are not reached */
2165
ctx->hook_lsig_matches = old_hook_lsig_matches;
2168
ret_from_magicscan(ret);
1919
lseek(desc, 0, SEEK_SET);
1920
type = cli_filetype2(desc, ctx->engine);
2171
if(type == CL_TYPE_ANY)
2172
type = cli_filetype2(*ctx->fmap, ctx->engine); /* FIXMEFMAP: port to fmap */
1921
2173
if(type == CL_TYPE_ERROR) {
1922
2174
cli_dbgmsg("cli_magic_scandesc: cli_filetype2 returned CL_TYPE_ERROR\n");
1925
lseek(desc, 0, SEEK_SET);
2177
ctx->hook_lsig_matches = old_hook_lsig_matches;
2178
ret_from_magicscan(CL_EREAD);
2181
#ifdef HAVE__INTERNAL__SHA_COLLECT
2182
if(!ctx->sha_collect && type==CL_TYPE_MSEXE) ctx->sha_collect = 1;
2184
lseek(desc, 0, SEEK_SET); /* FIXMEFMAP: remove ? */
2186
ctx->hook_lsig_matches = cli_bitset_init();
2187
if (!ctx->hook_lsig_matches) {
2188
ctx->hook_lsig_matches = old_hook_lsig_matches;
2190
ret_from_magicscan(CL_EMEM);
1927
2193
if(type != CL_TYPE_IGNORED && ctx->engine->sdb) {
1928
if((ret = cli_scanraw(desc, ctx, type, 0, &dettype)) == CL_VIRUS)
1930
lseek(desc, 0, SEEK_SET);
2194
if((ret = cli_scanraw(ctx, type, 0, &dettype, hash)) == CL_VIRUS) {
2195
ret = cli_checkfp(hash, hashed_size, ctx);
2198
cli_bitset_free(ctx->hook_lsig_matches);
2199
ctx->hook_lsig_matches = old_hook_lsig_matches;
2200
ret_from_magicscan(ret);
2202
lseek(desc, 0, SEEK_SET); /* FIXMEFMAP: remove ? */
1933
2205
ctx->recursion++;
1936
2207
case CL_TYPE_IGNORED:
1939
2210
case CL_TYPE_RAR:
2211
ctx->container_type = CL_TYPE_RAR;
2212
ctx->container_size = sb.st_size;
1940
2213
if(have_rar && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR))
1941
2214
ret = cli_scanrar(desc, ctx, 0, NULL);
1944
2217
case CL_TYPE_ZIP:
2218
ctx->container_type = CL_TYPE_ZIP;
2219
ctx->container_size = sb.st_size;
1945
2220
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP))
1946
ret = cli_unzip(desc, ctx);
2221
ret = cli_unzip(ctx);
1949
2224
case CL_TYPE_GZ:
1950
2225
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_GZ))
1951
ret = cli_scangzip(desc, ctx);
2226
ret = cli_scangzip(ctx);
1954
2229
case CL_TYPE_BZ:
1955
2230
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_BZ))
1956
2231
ret = cli_scanbzip(desc, ctx);
1958
2234
case CL_TYPE_ARJ:
2235
ctx->container_type = CL_TYPE_ARJ;
2236
ctx->container_size = sb.st_size;
1959
2237
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ARJ))
1960
2238
ret = cli_scanarj(desc, ctx, 0, NULL);
1963
2241
case CL_TYPE_NULSFT:
1964
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_NSIS))
2242
ctx->container_type = CL_TYPE_NULSFT;
2243
ctx->container_size = sb.st_size;
2244
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_NSIS))
1965
2245
ret = cli_scannulsft(desc, ctx, 0);
1968
2248
case CL_TYPE_AUTOIT:
2249
ctx->container_type = CL_TYPE_AUTOIT;
2250
ctx->container_size = sb.st_size;
1969
2251
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_AUTOIT))
1970
ret = cli_scanautoit(desc, ctx, 23);
2252
ret = cli_scanautoit(ctx, 23);
1973
2255
case CL_TYPE_MSSZDD:
2013
2301
case CL_TYPE_UUENCODED:
2014
2302
if(DCONF_OTHER & OTHER_CONF_UUENC)
2015
ret = cli_scanuuencoded(desc, ctx);
2303
ret = cli_scanuuencoded(ctx);
2018
2306
case CL_TYPE_MSCHM:
2307
ctx->container_type = CL_TYPE_MSCHM;
2308
ctx->container_size = sb.st_size;
2019
2309
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CHM))
2020
2310
ret = cli_scanmschm(desc, ctx);
2023
2313
case CL_TYPE_MSOLE2:
2314
ctx->container_type = CL_TYPE_MSOLE2;
2315
ctx->container_size = sb.st_size;
2024
2316
if(SCAN_OLE2 && (DCONF_ARCH & ARCH_CONF_OLE2))
2025
ret = cli_scanole2(desc, ctx);
2317
ret = cli_scanole2(ctx);
2321
ctx->container_type = CL_TYPE_7Z;
2322
ctx->container_size = sb.st_size;
2323
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_7Z))
2324
ret = cli_7unz(desc, ctx);
2028
2327
case CL_TYPE_POSIX_TAR:
2328
ctx->container_type = CL_TYPE_POSIX_TAR;
2329
ctx->container_size = sb.st_size;
2029
2330
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_TAR))
2030
2331
ret = cli_scantar(desc, ctx, 1);
2033
2334
case CL_TYPE_OLD_TAR:
2335
ctx->container_type = CL_TYPE_OLD_TAR;
2336
ctx->container_size = sb.st_size;
2034
2337
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_TAR))
2035
2338
ret = cli_scantar(desc, ctx, 0);
2341
case CL_TYPE_CPIO_OLD:
2342
ctx->container_type = CL_TYPE_CPIO_OLD;
2343
ctx->container_size = sb.st_size;
2344
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
2345
ret = cli_scancpio_old(desc, ctx);
2348
case CL_TYPE_CPIO_ODC:
2349
ctx->container_type = CL_TYPE_CPIO_ODC;
2350
ctx->container_size = sb.st_size;
2351
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
2352
ret = cli_scancpio_odc(desc, ctx);
2355
case CL_TYPE_CPIO_NEWC:
2356
ctx->container_type = CL_TYPE_CPIO_NEWC;
2357
ctx->container_size = sb.st_size;
2358
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
2359
ret = cli_scancpio_newc(desc, ctx, 0);
2362
case CL_TYPE_CPIO_CRC:
2363
ctx->container_type = CL_TYPE_CPIO_CRC;
2364
ctx->container_size = sb.st_size;
2365
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
2366
ret = cli_scancpio_newc(desc, ctx, 1);
2038
2369
case CL_TYPE_BINHEX:
2039
2370
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_BINHEX))
2040
ret = cli_scanbinhex(desc, ctx);
2371
ret = cli_binhex(ctx);
2043
2374
case CL_TYPE_SCRENC:
2106
2459
/* CL_TYPE_HTML: raw HTML files are not scanned, unless safety measure activated via DCONF */
2107
2460
if(type != CL_TYPE_IGNORED && (type != CL_TYPE_HTML || !(DCONF_DOC & DOC_CONF_HTML_SKIPRAW)) && !ctx->engine->sdb) {
2108
if(cli_scanraw(desc, ctx, type, typercg, &dettype) == CL_VIRUS)
2461
res = cli_scanraw(ctx, type, typercg, &dettype, hash);
2462
if(res != CL_CLEAN) {
2464
/* List of scan halts, runtime errors only! */
2474
cli_dbgmsg("Descriptor[%d]: cli_scanraw error %s\n", desc, cl_strerror(res));
2477
cli_bitset_free(ctx->hook_lsig_matches);
2478
ctx->hook_lsig_matches = old_hook_lsig_matches;
2479
ret_from_magicscan(res);
2480
/* CL_VIRUS = malware found, check FP and report */
2482
ret = cli_checkfp(hash, hashed_size, ctx);
2487
cli_bitset_free(ctx->hook_lsig_matches);
2488
ctx->hook_lsig_matches = old_hook_lsig_matches;
2489
ret_from_magicscan(ret);
2490
/* "MAX" conditions should still fully scan the current file */
2495
cli_dbgmsg("Descriptor[%d]: Continuing after cli_scanraw reached %s\n",
2496
desc, cl_strerror(res));
2498
/* Other errors must not block further scans below
2499
* This specifically includes CL_EFORMAT & CL_EREAD & CL_EUNPACK
2500
* Malformed/truncated files could report as any of these three.
2504
cli_dbgmsg("Descriptor[%d]: Continuing after cli_scanraw error %s\n",
2505
desc, cl_strerror(res));
2112
2510
ctx->recursion++;
2113
2511
lseek(desc, 0, SEEK_SET);
2513
/* bytecode hooks triggered by a lsig must be a hook
2514
* called from one of the functions here */
2115
2515
case CL_TYPE_TEXT_ASCII:
2116
2516
case CL_TYPE_TEXT_UTF16BE:
2117
2517
case CL_TYPE_TEXT_UTF16LE:
2118
2518
case CL_TYPE_TEXT_UTF8:
2119
if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML)
2120
ret = cli_scanscript(desc, ctx);
2519
if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML && ret != CL_VIRUS)
2520
ret = cli_scanscript(ctx);
2521
if(SCAN_MAIL && (DCONF_MAIL & MAIL_CONF_MBOX) && ret != CL_VIRUS && (ctx->container_type == CL_TYPE_MAIL || dettype == CL_TYPE_MAIL)) {
2522
ret = cli_fmap_scandesc(ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR, NULL, NULL);
2122
2525
/* Due to performance reasons all executables were first scanned
2123
2526
* in raw mode. Now we will try to unpack them
2125
2528
case CL_TYPE_MSEXE:
2126
if(SCAN_PE && ctx->dconf->pe)
2127
ret = cli_scanpe(desc, ctx);
2529
if(SCAN_PE && ctx->dconf->pe) {
2530
unsigned int corrupted_input = ctx->corrupted_input;
2531
ret = cli_scanpe(ctx);
2532
ctx->corrupted_input = corrupted_input;
2540
ret = cli_checkfp(hash, hashed_size, ctx);
2133
2541
ctx->recursion--;
2544
cli_bitset_free(ctx->hook_lsig_matches);
2545
ctx->hook_lsig_matches = old_hook_lsig_matches;
2548
/* Malformed file cases */
2136
2549
case CL_EFORMAT:
2552
/* Limits exceeded */
2137
2553
case CL_EMAXREC:
2138
2554
case CL_EMAXSIZE:
2139
2555
case CL_EMAXFILES:
2140
2556
cli_dbgmsg("Descriptor[%d]: %s\n", desc, cl_strerror(ret));
2557
ret_from_magicscan(CL_CLEAN);
2559
cache_add(hash, hashed_size, ctx);
2560
ret_from_magicscan(CL_CLEAN);
2562
ret_from_magicscan(ret);
2566
int cli_magic_scandesc(int desc, cli_ctx *ctx)
2568
return magic_scandesc(desc, ctx, CL_TYPE_ANY);
2571
int cli_magic_scandesc_type(int desc, cli_ctx *ctx, cli_file_t type)
2573
return magic_scandesc(desc, ctx, type);
2147
2576
int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions)
2578
return cl_scandesc_callback(desc, virname, scanned, engine, scanoptions, NULL);
2581
int cl_scandesc_callback(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions, void *context)
2155
2589
ctx.scanned = scanned;
2156
2590
ctx.options = scanoptions;
2157
2591
ctx.found_possibly_unwanted = 0;
2592
ctx.container_type = CL_TYPE_ANY;
2593
ctx.container_size = 0;
2158
2594
ctx.dconf = (struct cli_dconf *) engine->dconf;
2595
ctx.cb_ctx = context;
2596
ctx.fmap = cli_calloc(sizeof(fmap_t *), ctx.engine->maxreclevel + 2);
2599
if (!(ctx.hook_lsig_matches = cli_bitset_init())) {
2604
#ifdef HAVE__INTERNAL__SHA_COLLECT
2605
if(scanoptions & CL_SCAN_INTERNAL_COLLECT_SHA) {
2609
snprintf(link, sizeof(link), "/proc/self/fd/%u", desc);
2610
link[sizeof(link)-1]='\0';
2611
if((linksz=readlink(link, ctx.entry_filename, sizeof(ctx.entry_filename)))==-1) {
2612
cli_errmsg("failed to resolve filename for descriptor %d (%s)\n", desc, link);
2613
strcpy(ctx.entry_filename, "NO_IDEA");
2615
ctx.entry_filename[linksz]='\0';
2619
cli_logg_setup(&ctx);
2160
2620
rc = cli_magic_scandesc(desc, &ctx);
2622
if (ctx.options & CL_SCAN_ALLMATCHES) {
2623
*virname = (char *)ctx.virname; /* temp hack for scanall mode until api augmentation */
2624
if (rc == CL_CLEAN && ctx.num_viruses)
2628
cli_bitset_free(ctx.hook_lsig_matches);
2161
2630
if(rc == CL_CLEAN && ctx.found_possibly_unwanted)
2166
2636
int cli_found_possibly_unwanted(cli_ctx* ctx)
2169
cli_dbgmsg("found Possibly Unwanted: %s\n",*ctx->virname);
2170
if(ctx->options & CL_SCAN_HEURISTIC_PRECEDENCE) {
2171
/* we found a heuristic match, don't scan further,
2172
* but consider it a virus. */
2173
cli_dbgmsg("cli_found_possibly_unwanted: CL_VIRUS\n");
2176
/* heuristic scan isn't taking precedence, keep scanning.
2177
* If this is part of an archive, and
2178
* we find a real malware we report that instead of the
2179
* heuristic match */
2180
ctx->found_possibly_unwanted = 1;
2182
cli_warnmsg("cli_found_possibly_unwanted called, but virname is not set\n");
2638
if(cli_get_last_virus(ctx)) {
2639
cli_dbgmsg("found Possibly Unwanted: %s\n", cli_get_last_virus(ctx));
2640
if(ctx->options & CL_SCAN_HEURISTIC_PRECEDENCE) {
2641
/* we found a heuristic match, don't scan further,
2642
* but consider it a virus. */
2643
cli_dbgmsg("cli_found_possibly_unwanted: CL_VIRUS\n");
2646
/* heuristic scan isn't taking precedence, keep scanning.
2647
* If this is part of an archive, and
2648
* we find a real malware we report that instead of the
2649
* heuristic match */
2650
ctx->found_possibly_unwanted = 1;
2652
cli_warnmsg("cli_found_possibly_unwanted called, but virname is not set\n");
2187
2658
static int cli_scanfile(const char *filename, cli_ctx *ctx)