164
161
if(container == CL_TYPE_MAIL) {
165
162
fd = open(fname, O_RDONLY|O_BINARY);
167
cli_warnmsg("Cannot open file %s: %s, mode: %x\n", fname, strerror(errno), statbuf.st_mode);
165
cli_warnmsg("Cannot open file %s: %s, mode: %x\n", fname, cli_strerror(errno, err, sizeof(err)), statbuf.st_mode);
278
275
if(lseek(desc, sfx_offset, SEEK_SET) == -1)
281
278
/* generate the temporary directory */
282
if(!(dir = cli_gentemp(NULL)))
279
if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
285
282
if(mkdir(dir, 0700)) {
288
285
return CL_ETMPDIR;
291
if((ret = unrar_open(desc, dir, &rar_state)) != UNRAR_OK) {
292
if(!cli_leavetemps_flag)
288
if((ret = cli_unrar_open(desc, dir, &rar_state)) != UNRAR_OK) {
289
if(!ctx->engine->keeptmp)
295
292
if(ret == UNRAR_PASSWD) {
305
302
} if(ret == UNRAR_EMEM) {
314
311
rar_state.ofd = -1;
315
ret = unrar_extract_next_prepare(&rar_state,dir);
312
ret = cli_unrar_extract_next_prepare(&rar_state,dir);
316
313
if(ret != UNRAR_OK) {
317
314
if(ret == UNRAR_BREAK)
319
316
else if(ret == UNRAR_EMEM)
325
if((ret=cli_checklimits("RAR", ctx, rar_state.metadata_tail->unpack_size, rar_state.metadata_tail->pack_size, 0)!=CL_CLEAN)) {
322
if(ctx->engine->maxscansize && ctx->scansize >= ctx->engine->maxscansize) {
326
323
free(rar_state.file_header->filename);
327
324
free(rar_state.file_header);
331
ret = unrar_extract_next(&rar_state,dir);
328
if(ctx->engine->maxscansize && ctx->scansize + ctx->engine->maxfilesize >= ctx->engine->maxscansize)
329
rar_state.maxfilesize = ctx->engine->maxscansize - ctx->scansize;
331
rar_state.maxfilesize = ctx->engine->maxfilesize;
333
ret = cli_unrar_extract_next(&rar_state,dir);
332
334
if(ret == UNRAR_OK)
333
335
ret = CL_SUCCESS;
334
336
else if(ret == UNRAR_EMEM)
339
341
if(rar_state.ofd > 0) {
340
342
lseek(rar_state.ofd,0,SEEK_SET);
341
343
rc = cli_magic_scandesc(rar_state.ofd,ctx);
342
344
close(rar_state.ofd);
343
if(!cli_leavetemps_flag)
344
if (cli_unlink(rar_state.filename)) ret = CL_EIO;
345
if(!ctx->engine->keeptmp)
346
if (cli_unlink(rar_state.filename)) ret = CL_EUNLINK;
345
347
if(rc == CL_VIRUS ) {
346
348
cli_dbgmsg("RAR: infected with %s\n",*ctx->virname);
406
407
ret = cli_unarj_open(desc, dir);
407
408
if (ret != CL_SUCCESS) {
408
if(!cli_leavetemps_flag)
409
if(!ctx->engine->keeptmp)
411
412
cli_dbgmsg("ARJ: Error: %s\n", cl_strerror(ret));
415
metadata.filename = NULL;
417
metadata.filename = NULL;
418
418
ret = cli_unarj_prepare_file(desc, dir, &metadata);
419
419
if (ret != CL_SUCCESS) {
422
422
if ((ret = cli_checklimits("ARJ", ctx, metadata.orig_size, metadata.comp_size, 0))!=CL_CLEAN) {
423
423
ret = CL_SUCCESS;
424
if (metadata.filename)
425
free(metadata.filename);
426
428
ret = cli_unarj_extract_file(desc, dir, &metadata);
470
476
if((gd = gzdopen(dup(desc), "rb")) == NULL) {
471
477
cli_dbgmsg("GZip: Can't open descriptor %d\n", desc);
475
if((ret = cli_gentempfd(NULL, &tmpname, &fd))) {
481
if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd))) {
476
482
cli_dbgmsg("GZip: Can't generate temporary file.\n");
482
488
cli_dbgmsg("GZip: Unable to malloc %u bytes.\n", FILEBUFF);
485
if(!cli_leavetemps_flag) {
491
if(!ctx->engine->keeptmp) {
486
492
if(cli_unlink(tmpname)) {
500
506
if(cli_writen(fd, buff, bytes) != bytes) {
501
507
cli_dbgmsg("GZip: Can't write to file.\n");
503
if(!cli_leavetemps_flag) {
509
if(!ctx->engine->keeptmp) {
504
510
if (cli_unlink(tmpname)) {
530
536
if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS ) {
531
537
cli_dbgmsg("GZip: Infected with %s\n", *ctx->virname);
533
if(!cli_leavetemps_flag) {
539
if(!ctx->engine->keeptmp) {
534
540
if (cli_unlink(tmpname)) {
543
if(!cli_leavetemps_flag)
544
if (cli_unlink(tmpname)) ret = CL_EIO;
549
if(!ctx->engine->keeptmp)
550
if (cli_unlink(tmpname)) ret = CL_EUNLINK;
565
571
static int cli_scanbzip(int desc, cli_ctx *ctx)
567
573
int fd, bytes, ret = CL_CLEAN, bzerror = 0;
569
574
unsigned long int size = 0;
576
581
if((fs = fdopen(dup(desc), "rb")) == NULL) {
577
582
cli_dbgmsg("Bzip: Can't open descriptor %d.\n", desc);
582
if(ctx->limits->archivememlim)
585
if((bfd = BZ2_bzReadOpen(&bzerror, fs, 0, memlim, NULL, 0)) == NULL) {
586
if((bfd = BZ2_bzReadOpen(&bzerror, fs, 0, 0, NULL, 0)) == NULL) {
586
587
cli_dbgmsg("Bzip: Can't initialize bzip2 library (descriptor: %d).\n", desc);
591
if((ret = cli_gentempfd(NULL, &tmpname, &fd))) {
592
if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd))) {
592
593
cli_dbgmsg("Bzip: Can't generate temporary file.\n");
593
594
BZ2_bzReadClose(&bzerror, bfd);
598
599
if(!(buff = (char *) cli_malloc(FILEBUFF))) {
599
600
cli_dbgmsg("Bzip: Unable to malloc %u bytes.\n", FILEBUFF);
601
if(!cli_leavetemps_flag) {
602
if(!ctx->engine->keeptmp) {
602
603
if (cli_unlink(tmpname)) {
605
606
BZ2_bzReadClose(&bzerror, bfd);
622
623
cli_dbgmsg("Bzip: Can't write to file.\n");
623
624
BZ2_bzReadClose(&bzerror, bfd);
625
if(!cli_leavetemps_flag) {
626
if(!ctx->engine->keeptmp) {
626
627
if (cli_unlink(tmpname)) {
654
655
cli_dbgmsg("Bzip: Infected with %s\n", *ctx->virname);
657
if(!cli_leavetemps_flag)
658
if (cli_unlink(tmpname)) ret = CL_EIO;
658
if(!ctx->engine->keeptmp)
659
if (cli_unlink(tmpname)) ret = CL_EUNLINK;
672
673
cli_dbgmsg("in cli_scanszdd()\n");
674
if((ret = cli_gentempfd(NULL, &tmpname, &ofd))) {
675
if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &ofd))) {
675
676
cli_dbgmsg("MSEXPAND: Can't generate temporary file/descriptor\n");
691
692
lseek(ofd, 0, SEEK_SET);
692
693
ret = cli_magic_scandesc(ofd, ctx);
694
if(!cli_leavetemps_flag)
695
if (cli_unlink(tmpname)) ret = CL_EIO;
695
if(!ctx->engine->keeptmp)
696
if (cli_unlink(tmpname)) ret = CL_EUNLINK;
715
716
for(file = cab.files; file; file = file->next) {
718
if(cli_checklimits("CAB", ctx, file->length, 0, 0)!=CL_CLEAN)
721
if(!(tempname = cli_gentemp(NULL))) {
719
if(!(tempname = cli_gentemp(ctx->engine->tmpdir))) {
725
cli_dbgmsg("CAB: Extracting file %s to %s, size %u\n", file->name, tempname, file->length);
726
if((ret = cab_extract(file, tempname)))
724
if(ctx->engine->maxscansize && ctx->scansize >= ctx->engine->maxscansize) {
728
if(ctx->engine->maxscansize && ctx->scansize + ctx->engine->maxfilesize >= ctx->engine->maxscansize)
729
file->max_size = ctx->engine->maxscansize - ctx->scansize;
731
file->max_size = ctx->engine->maxfilesize;
733
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
file->written_size = 0;
735
if((ret = cab_extract(file, tempname))) {
727
736
cli_dbgmsg("CAB: Failed to extract file: %s\n", cl_strerror(ret));
738
if(file->length != file->written_size)
739
cli_dbgmsg("CAB: Length from header %u but wrote %u bytes\n", (unsigned int) file->length, (unsigned int) file->written_size);
729
741
ret = cli_scanfile(tempname, ctx);
731
if(!cli_leavetemps_flag) {
743
if(!ctx->engine->keeptmp) {
732
744
if (cli_unlink(tempname)) {
784
796
/* cli_dbgmsg("Project content:\n%s", data); */
786
798
*ctx->scanned += data_len / CL_COUNT_PRECISION;
787
if(cli_scanbuff(data, data_len, ctx, CL_TYPE_MSOLE2) == CL_VIRUS) {
799
if(cli_scanbuff(data, data_len, 0, ctx, CL_TYPE_MSOLE2, NULL) == CL_VIRUS) {
808
820
vbaname[sizeof(vbaname)-1] = '\0';
809
821
fd = open(vbaname, O_RDONLY|O_BINARY);
810
822
if (fd == -1) continue;
811
if ((fullname = cli_ppt_vba_read(fd))) {
823
if ((fullname = cli_ppt_vba_read(fd, ctx))) {
812
824
if(cli_scandir(fullname, ctx, 0) == CL_VIRUS) {
815
if(!cli_leavetemps_flag)
827
if(!ctx->engine->keeptmp)
816
828
cli_rmdirs(fullname);
842
854
cli_dbgmsg("Project content:\n%s", data);
844
856
*ctx->scanned += vba_project->length[i] / CL_COUNT_PRECISION;
845
if(cli_scanbuff(data, vba_project->length[i], ctx, CL_TYPE_MSOLE2) == CL_VIRUS) {
857
if(cli_scanbuff(data, vba_project->length[i], 0, ctx, CL_TYPE_MSOLE2, NULL) == CL_VIRUS) {
1015
1027
char *tmpname = NULL;
1016
1028
int ofd = -1, ret;
1018
const struct cli_matcher *root = ctx->engine->root[7];
1019
uint32_t maxpatlen = root ? root->maxpatlen : 0;
1030
const struct cli_matcher *troot = ctx->engine->root[7];
1031
uint32_t maxpatlen = troot ? troot->maxpatlen : 0, offset = 0;
1032
struct cli_matcher *groot = ctx->engine->root[0];
1033
struct cli_ac_data gmdata, tmdata;
1034
struct cli_ac_data *mdata[2];
1021
1036
cli_dbgmsg("in cli_scanscript()\n");
1023
1038
if(fstat(desc, &sb) == -1) {
1024
1039
cli_errmsg("cli_scanscript: fstat() failed for descriptor %d\n", desc);
1028
1043
/* don't normalize files that are too large */
1029
if(sb.st_size > 524288) {
1030
cli_dbgmsg("cli_scanscript: exiting (file larger than 400 kB)\n");
1044
if(sb.st_size > 5242880) {
1045
cli_dbgmsg("cli_scanscript: exiting (file larger than 5 MB)\n");
1031
1046
return CL_CLEAN;
1034
1049
/* dump to disk only if explicitly asked to,
1035
1050
* otherwise we can process just in-memory */
1036
if(cli_leavetemps_flag) {
1037
if((ret = cli_gentempfd(NULL, &tmpname, &ofd))) {
1051
if(ctx->engine->keeptmp) {
1052
if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &ofd))) {
1038
1053
cli_dbgmsg("cli_scanscript: Can't generate temporary file/descriptor\n");
1048
1063
text_normalize_init(&state, normalized, SCANBUFF + maxpatlen);
1049
1064
ret = CL_CLEAN;
1066
if ((ret = cli_ac_initdata(&tmdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
1069
if ((ret = cli_ac_initdata(&gmdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN))) {
1070
cli_ac_freedata(&tmdata);
1052
1077
nread = cli_readn(desc, buff, sizeof(buff));
1053
1078
if(nread <= 0 || state.out_pos + nread > state.out_len) {
1059
1084
/* we can continue to scan in memory */
1061
1086
/* when we flush the buffer also scan */
1062
if(cli_scanbuff(state.out, state.out_pos, ctx, CL_TYPE_TEXT_ASCII) == CL_VIRUS) {
1087
if(cli_scanbuff(state.out, state.out_pos, offset, ctx, CL_TYPE_TEXT_ASCII, mdata) == CL_VIRUS) {
1063
1088
ret = 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;
1066
1096
/* carry over maxpatlen from previous buffer */
1067
1097
if (state.out_pos > maxpatlen)
1068
memcpy(state.out, state.out + state.out_pos - maxpatlen, maxpatlen);
1098
memmove(state.out, state.out + state.out_pos - maxpatlen, maxpatlen);
1069
1099
text_normalize_reset(&state);
1070
1100
state.out_pos = maxpatlen;
1076
1106
* and using while(){} loop would mean code duplication */
1077
1107
} while (nread > 0);
1079
if(cli_leavetemps_flag) {
1109
cli_ac_freedata(&tmdata);
1110
cli_ac_freedata(&gmdata);
1111
if(ctx->engine->keeptmp) {
1094
1126
cli_dbgmsg("in cli_scanhtml_utf16()\n");
1096
if(!(tempname = cli_gentemp(NULL)))
1128
if(!(tempname = cli_gentemp(ctx->engine->tmpdir)))
1097
1129
return CL_EMEM;
1099
1131
if((fd = open(tempname, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
1100
1132
cli_errmsg("cli_scanhtml_utf16: Can't create file %s\n", tempname);
1101
1133
free(tempname);
1105
1137
cli_dbgmsg("cli_scanhtml_utf16: using tempfile %s\n", tempname);
1123
1155
ret = cli_scanhtml(fd, ctx);
1126
if(!cli_leavetemps_flag) {
1127
if (cli_unlink(tempname)) ret = CL_EIO;
1158
if(!ctx->engine->keeptmp) {
1159
if (cli_unlink(tempname)) ret = CL_EUNLINK;
1129
1161
cli_dbgmsg("cli_scanhtml_utf16: Decoded HTML data saved in %s\n", tempname);
1130
1162
free(tempname);
1141
1173
cli_dbgmsg("in cli_scanole2()\n");
1143
if(ctx->limits && ctx->limits->maxreclevel && ctx->recursion >= ctx->limits->maxreclevel)
1175
if(ctx->engine->maxreclevel && ctx->recursion >= ctx->engine->maxreclevel)
1144
1176
return CL_EMAXREC;
1146
1178
/* generate the temporary directory */
1147
if(!(dir = cli_gentemp(NULL)))
1179
if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
1148
1180
return CL_EMEM;
1150
1182
if(mkdir(dir, 0700)) {
1156
1188
ret = cli_ole2_extract(desc, dir, ctx, &vba);
1157
1189
if(ret!=CL_CLEAN && ret!=CL_VIRUS) {
1158
1190
cli_dbgmsg("OLE2: %s\n", cl_strerror(ret));
1159
if(!cli_leavetemps_flag)
1191
if(!ctx->engine->keeptmp)
1160
1192
cli_rmdirs(dir);
1254
1286
return CL_ETMPDIR;
1257
ret = cli_chm_open(desc, dir, &metadata);
1289
ret = cli_chm_open(desc, dir, &metadata, ctx);
1258
1290
if (ret != CL_SUCCESS) {
1259
if(!cli_leavetemps_flag)
1291
if(!ctx->engine->keeptmp)
1260
1292
cli_rmdirs(dir);
1262
1294
cli_dbgmsg("CHM: Error: %s\n", cl_strerror(ret));
1268
1300
if (ret != CL_SUCCESS) {
1271
ret = cli_chm_extract_file(desc, dir, &metadata);
1303
ret = cli_chm_extract_file(desc, dir, &metadata, ctx);
1272
1304
if (ret == CL_SUCCESS) {
1273
1305
lseek(metadata.ofd, 0, SEEK_SET);
1274
1306
rc = cli_magic_scandesc(metadata.ofd, ctx);
1304
1336
cli_dbgmsg("in cli_scanscrenc()\n");
1306
if(!(tempname = cli_gentemp(NULL)))
1338
if(!(tempname = cli_gentemp(ctx->engine->tmpdir)))
1307
1339
return CL_EMEM;
1309
1341
if(mkdir(tempname, 0700)) {
1315
1347
if (html_screnc_decode(desc, tempname))
1316
1348
ret = cli_scandir(tempname, ctx, 0);
1318
if(!cli_leavetemps_flag)
1350
if(!ctx->engine->keeptmp)
1319
1351
cli_rmdirs(tempname);
1321
1353
free(tempname);
1325
static int cli_scanriff(int desc, const char **virname)
1357
static int cli_scanriff(int desc, cli_ctx *ctx)
1327
1359
int ret = CL_CLEAN;
1329
1361
if(cli_check_riff_exploit(desc) == 2) {
1331
*virname = "Exploit.W32.MS05-002";
1362
if(!cli_checkfp(desc, ctx)) {
1364
*ctx->virname = "Exploit.W32.MS05-002";
1339
1373
int ret = CL_CLEAN;
1341
1375
if(cli_check_jpeg_exploit(desc, ctx) == 1) {
1343
*ctx->virname = "Exploit.W32.MS04-028";
1376
if(!cli_checkfp(desc, ctx)) {
1378
*ctx->virname = "Exploit.W32.MS04-028";
1468
1504
return CL_ETMPDIR;
1471
ret = cli_tnef(dir, desc);
1507
ret = cli_tnef(dir, desc, ctx);
1473
1509
if(ret == CL_CLEAN)
1474
1510
ret = cli_scandir(dir, ctx, 0);
1476
if(!cli_leavetemps_flag)
1512
if(!ctx->engine->keeptmp)
1477
1513
cli_rmdirs(dir);
1515
1551
cli_dbgmsg("Starting cli_scanmail(), recursion = %u\n", ctx->recursion);
1517
1553
/* generate the temporary directory */
1518
if(!(dir = cli_gentemp(NULL)))
1554
if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
1519
1555
return CL_EMEM;
1521
1557
if(mkdir(dir, 0700)) {
1550
1586
unsigned int cc_count = 0;
1551
1587
unsigned int ssn_count = 0;
1553
const struct cl_limits *lim = NULL;
1554
1589
int (*ccfunc)(const unsigned char *buffer, int length);
1555
1590
int (*ssnfunc)(const unsigned char *buffer, int length);
1558
if(ctx == NULL || ctx->limits == NULL)
1559
1594
return CL_ENULLARG;
1563
if(lim->min_cc_count == 1)
1596
if(ctx->engine->min_cc_count == 1)
1564
1597
ccfunc = dlp_has_cc;
1566
1599
ccfunc = dlp_get_cc_count;
1568
1601
switch((ctx->options & CL_SCAN_STRUCTURED_SSN_NORMAL) | (ctx->options & CL_SCAN_STRUCTURED_SSN_STRIPPED)) {
1570
1603
case (CL_SCAN_STRUCTURED_SSN_NORMAL | CL_SCAN_STRUCTURED_SSN_STRIPPED):
1571
if(lim->min_ssn_count == 1)
1604
if(ctx->engine->min_ssn_count == 1)
1572
1605
ssnfunc = dlp_has_ssn;
1574
1607
ssnfunc = dlp_get_ssn_count;
1577
1610
case CL_SCAN_STRUCTURED_SSN_NORMAL:
1578
if(lim->min_ssn_count == 1)
1611
if(ctx->engine->min_ssn_count == 1)
1579
1612
ssnfunc = dlp_has_normal_ssn;
1581
1614
ssnfunc = dlp_get_normal_ssn_count;
1584
1617
case CL_SCAN_STRUCTURED_SSN_STRIPPED:
1585
if(lim->min_ssn_count == 1)
1618
if(ctx->engine->min_ssn_count == 1)
1586
1619
ssnfunc = dlp_has_stripped_ssn;
1588
1621
ssnfunc = dlp_get_stripped_ssn_count;
1595
1628
while(!done && ((result = cli_readn(desc, buf, 8191)) > 0)) {
1596
if((cc_count += ccfunc((const unsigned char *)buf, result)) >= lim->min_cc_count)
1629
if((cc_count += ccfunc((const unsigned char *)buf, result)) >= ctx->engine->min_cc_count)
1599
if(ssnfunc && ((ssn_count += ssnfunc((const unsigned char *)buf, result)) >= lim->min_ssn_count))
1632
if(ssnfunc && ((ssn_count += ssnfunc((const unsigned char *)buf, result)) >= ctx->engine->min_ssn_count))
1603
if(cc_count != 0 && cc_count >= lim->min_cc_count) {
1636
if(cc_count != 0 && cc_count >= ctx->engine->min_cc_count) {
1604
1637
cli_dbgmsg("cli_scan_structured: %u credit card numbers detected\n", cc_count);
1605
1638
*ctx->virname = "Structured.CreditCardNumber";
1639
return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
1609
if(ssn_count != 0 && ssn_count >= lim->min_ssn_count) {
1642
if(ssn_count != 0 && ssn_count >= ctx->engine->min_ssn_count) {
1610
1643
cli_dbgmsg("cli_scan_structured: %u social security numbers detected\n", ssn_count);
1611
1644
*ctx->virname = "Structured.SSN";
1645
return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
1615
1648
return CL_CLEAN;
1622
1655
char buff[512];
1626
tmpname = cli_gentemp(NULL);
1658
tmpname = cli_gentemp(ctx->engine->tmpdir);
1628
1660
return CL_EMEM;
1630
1662
if((fd = open(tmpname, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
1631
1663
cli_errmsg("cli_scanembpe: Can't create file %s\n", tmpname);
1636
1668
while((bytes = read(desc, buff, sizeof(buff))) > 0) {
1642
1674
if(cli_writen(fd, buff, bytes) != bytes) {
1643
1675
cli_dbgmsg("cli_scanembpe: Can't write to temporary file\n");
1645
if(!cli_leavetemps_flag) {
1677
if(!ctx->engine->keeptmp) {
1646
1678
if (cli_unlink(tmpname)) {
1658
1690
if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS) {
1659
1691
cli_dbgmsg("cli_scanembpe: Infected with %s\n", *ctx->virname);
1661
if(!cli_leavetemps_flag) {
1693
if(!ctx->engine->keeptmp) {
1662
1694
if (cli_unlink(tmpname)) {
1689
1721
uint32_t lastzip, lastrar;
1690
1722
struct cli_exe_info peinfo;
1691
1723
unsigned int acmode = AC_SCAN_VIR, break_loop = 0;
1694
if(typercg) switch(type) {
1695
case CL_TYPE_TEXT_ASCII:
1698
case CL_TYPE_MSOLE2:
1699
acmode |= AC_SCAN_FT;
1727
if(ctx->engine->maxreclevel && ctx->recursion >= ctx->engine->maxreclevel)
1731
acmode |= AC_SCAN_FT;
1704
1733
if(lseek(desc, 0, SEEK_SET) < 0) {
1705
1734
cli_errmsg("cli_scanraw: lseek() failed\n");
1709
1738
ret = cli_scandesc(desc, ctx, type == CL_TYPE_TEXT_ASCII ? 0 : type, 0, &ftoffset, acmode);
1711
1740
if(ret >= CL_TYPENO) {
1714
1744
if(type == CL_TYPE_TEXT_ASCII) {
1723
if(nret != CL_VIRUS && (type == CL_TYPE_MSEXE || type == CL_TYPE_ZIP || type == CL_TYPE_MSOLE2)) {
1753
if(nret != CL_VIRUS) {
1724
1754
lastzip = lastrar = 0xdeadbeef;
1725
1755
fpt = ftoffset;
1757
if(fpt->offset) switch(fpt->type) {
1728
1758
case CL_TYPE_RARSFX:
1730
if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_RAR)) {
1731
cli_dbgmsg("RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
1759
cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
1760
if(type != CL_TYPE_RAR && have_rar && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR)) {
1761
cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
1732
1762
nret = cli_scanrar(desc, ctx, fpt->offset, &lastrar);
1737
1766
case CL_TYPE_ZIPSFX:
1738
if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_ZIP) && fpt->offset) {
1739
cli_dbgmsg("ZIP-SFX signature found at %u\n", (unsigned int) fpt->offset);
1767
if(type != CL_TYPE_ZIP && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) {
1768
cli_dbgmsg("ZIP/ZIP-SFX signature found at %u\n", (unsigned int) fpt->offset);
1740
1769
nret = cli_unzip_single(desc, ctx, fpt->offset);
1744
1773
case CL_TYPE_CABSFX:
1745
if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_CAB)) {
1746
cli_dbgmsg("CAB-SFX signature found at %u\n", (unsigned int) fpt->offset);
1774
if(type != CL_TYPE_MSCAB && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CAB)) {
1775
cli_dbgmsg("CAB/CAB-SFX signature found at %u\n", (unsigned int) fpt->offset);
1747
1776
nret = cli_scanmscab(desc, ctx, fpt->offset);
1750
1779
case CL_TYPE_ARJSFX:
1751
if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_ARJ)) {
1780
if(type != CL_TYPE_ARJ && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ARJ)) {
1752
1781
cli_dbgmsg("ARJ-SFX signature found at %u\n", (unsigned int) fpt->offset);
1753
1782
nret = cli_scanarj(desc, ctx, fpt->offset, &lastrar);
1771
1800
case CL_TYPE_PDF:
1772
if(SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF)) {
1801
if(type != CL_TYPE_PDF && SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF)) {
1773
1802
cli_dbgmsg("PDF signature found at %u\n", (unsigned int) fpt->offset);
1774
1803
nret = cli_scanpdf(desc, ctx, fpt->offset);
1778
1807
case CL_TYPE_MSEXE:
1779
if(SCAN_PE && ctx->dconf->pe && fpt->offset) {
1780
cli_dbgmsg("PE signature found at %u\n", (unsigned int) fpt->offset);
1808
if(SCAN_PE && (type == CL_TYPE_MSEXE || type == CL_TYPE_ZIP || type == CL_TYPE_MSOLE2) && ctx->dconf->pe) {
1810
if(sb.st_size > 10485760)
1781
1812
memset(&peinfo, 0, sizeof(struct cli_exe_info));
1782
1813
peinfo.offset = fpt->offset;
1783
1814
lseek(desc, fpt->offset, SEEK_SET);
1784
1815
if(cli_peheader(desc, &peinfo) == 0) {
1785
cli_dbgmsg("*** Detected embedded PE file ***\n");
1816
cli_dbgmsg("*** Detected embedded PE file at %u ***\n", (unsigned int) fpt->offset);
1786
1817
if(peinfo.section)
1787
1818
free(peinfo.section);
1849
1878
struct stat sb;
1850
1879
uint8_t typercg = 1;
1881
if(ctx->engine->maxreclevel && ctx->recursion > ctx->engine->maxreclevel) {
1882
cli_dbgmsg("cli_magic_scandesc: Archive recursion limit exceeded (%u, max: %u)\n", ctx->recursion, ctx->engine->maxreclevel);
1853
1886
if(fstat(desc, &sb) == -1) {
1854
1887
cli_errmsg("magic_scandesc: Can't fstat descriptor %d\n", desc);
1858
1891
if(sb.st_size <= 5) {
1863
1896
if(!ctx->engine) {
1864
1897
cli_errmsg("CRITICAL: engine == NULL\n");
1901
if(!(ctx->engine->dboptions & CL_DB_COMPILED)) {
1902
cli_errmsg("CRITICAL: engine not compiled\n");
1865
1903
return CL_EMALFDB;
1868
if(!ctx->options) { /* raw mode (stdin, etc.) */
1869
cli_dbgmsg("Raw mode: No support for special files\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 */
1910
if(ctx->recursion == ctx->engine->maxreclevel)
1911
cli_dbgmsg("cli_magic_scandesc: Hit recursion limit, only scanning raw file\n");
1913
cli_dbgmsg("Raw mode: No support for special files\n");
1870
1914
if((ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR)) == CL_VIRUS)
1871
1915
cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
1875
if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN)
1878
if((SCAN_MAIL || SCAN_ARCHIVE) && ctx->limits && ctx->limits->maxreclevel && ctx->recursion > ctx->limits->maxreclevel) {
1879
cli_dbgmsg("Archive recursion limit exceeded (level = %u).\n", ctx->recursion);
1883
1919
lseek(desc, 0, SEEK_SET);
1884
1920
type = cli_filetype2(desc, ctx->engine);
1885
1921
if(type == CL_TYPE_ERROR) {
1886
1922
cli_dbgmsg("cli_magic_scandesc: cli_filetype2 returned CL_TYPE_ERROR\n");
1889
1925
lseek(desc, 0, SEEK_SET);
1903
1939
case CL_TYPE_RAR:
1905
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR))
1940
if(have_rar && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR))
1906
1941
ret = cli_scanrar(desc, ctx, 0, NULL);
1908
cli_warnmsg("RAR code not compiled-in\n");
1912
1944
case CL_TYPE_ZIP:
2046
2078
case CL_TYPE_BINARY_DATA:
2047
2079
if(SCAN_ALGO && (DCONF_OTHER & OTHER_CONF_MYDOOMLOG))
2048
ret = cli_check_mydoom_log(desc, ctx->virname);
2080
ret = cli_check_mydoom_log(desc, ctx);
2051
2083
case CL_TYPE_TEXT_ASCII:
2115
int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options)
2147
int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions)
2118
struct cl_limits l_limits;
2122
cli_errmsg("cl_scandesc: limits == NULL\n");
2125
2152
memset(&ctx, '\0', sizeof(cli_ctx));
2126
2153
ctx.engine = engine;
2127
2154
ctx.virname = virname;
2128
2155
ctx.scanned = scanned;
2129
ctx.options = options;
2156
ctx.options = scanoptions;
2130
2157
ctx.found_possibly_unwanted = 0;
2131
2158
ctx.dconf = (struct cli_dconf *) engine->dconf;
2132
ctx.limits = &l_limits;
2133
memcpy(&l_limits, limits, sizeof(struct cl_limits));
2135
2160
rc = cli_magic_scandesc(desc, &ctx);
2136
2161
if(rc == CL_CLEAN && ctx.found_possibly_unwanted)
2176
int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options)
2201
int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions)
2181
2206
if((fd = open(filename, O_RDONLY|O_BINARY)) == -1)
2182
2207
return CL_EOPEN;
2184
ret = cl_scandesc(fd, virname, scanned, engine, limits, options);
2209
ret = cl_scandesc(fd, virname, scanned, engine, scanoptions);