git-svn: trunk@5074
Tomasz Kojm authored on 2009/06/11 05:50:49... | ... |
@@ -1,3 +1,26 @@ |
1 |
+Wed Jun 10 19:01:11 CEST 2009 (tk) |
|
2 |
+---------------------------------- |
|
3 |
+ * V 0.95.2 |
|
4 |
+ |
|
5 |
+Wed Jun 10 18:04:53 CEST 2009 (tk) |
|
6 |
+---------------------------------- |
|
7 |
+ * libclamav: detect and handle archives hidden inside other files (eg. images), |
|
8 |
+ which can be unpacked by WinZip, WinRAR and other tools (bb#1554) |
|
9 |
+ Reported by ROGER Mickael and Thierry Zoller |
|
10 |
+ |
|
11 |
+Wed Jun 10 18:02:31 CEST 2009 (tk) |
|
12 |
+---------------------------------- |
|
13 |
+ * libclamav/mspack.c, cab.c: don't rely on file sizes stored in CAB headers (bb#1562) |
|
14 |
+ Reported by Thierry*Zoller <Thierry*Zoller.lu> |
|
15 |
+ |
|
16 |
+Wed Jun 10 17:58:47 CEST 2009 (acab) |
|
17 |
+------------------------------------ |
|
18 |
+ * libclamunrar/unrarvm.c: fix handling of some broken rar files |
|
19 |
+ |
|
20 |
+Wed Jun 10 17:58:30 CEST 2009 (edwin) |
|
21 |
+------------------------------------- |
|
22 |
+ * libclamav/mbox.c: handle malformed emails with embedded \0s (bb #1573) |
|
23 |
+ |
|
1 | 24 |
Fri May 29 14:37:08 EEST 2009 (edwin) |
2 | 25 |
------------------------------------- |
3 | 26 |
* clamdtop/clamdtop.c: Add missing #include, fixed bb #1619. |
... | ... |
@@ -1,7 +1,9 @@ |
1 |
-0.95.1 |
|
1 |
+0.95.2 |
|
2 | 2 |
------ |
3 | 3 |
|
4 |
-This is a bugfix release only, please see the ChangeLog for details. |
|
4 |
+This version improves handling of archives, adds support for --file-list |
|
5 |
+in clamscan and clamdscan, and fixes various issues found in previous |
|
6 |
+releases. |
|
5 | 7 |
|
6 | 8 |
-- |
7 | 9 |
The ClamAV team (http://www.clamav.net/team) |
... | ... |
@@ -2,6 +2,16 @@ Note: This README/NEWS file refers to the source tarball. Some things described |
2 | 2 |
here may not be available in binary packages. |
3 | 3 |
-- |
4 | 4 |
|
5 |
+0.95.2 |
|
6 |
+------ |
|
7 |
+ |
|
8 |
+This version improves handling of archives, adds support for --file-list |
|
9 |
+in clamscan and clamdscan, and fixes various issues found in previous |
|
10 |
+releases. |
|
11 |
+ |
|
12 |
+-- |
|
13 |
+The ClamAV team (http://www.clamav.net/team) |
|
14 |
+ |
|
5 | 15 |
0.95.1 |
6 | 16 |
------ |
7 | 17 |
|
... | ... |
@@ -71,7 +71,7 @@ |
71 | 71 |
\vspace{3cm} |
72 | 72 |
\begin{flushright} |
73 | 73 |
\rule[-1ex]{8cm}{3pt}\\ |
74 |
- \huge Clam AntiVirus 0.95.1\\ |
|
74 |
+ \huge Clam AntiVirus 0.95.2\\ |
|
75 | 75 |
\huge \emph{User Manual}\\ |
76 | 76 |
\end{flushright} |
77 | 77 |
|
... | ... |
@@ -127,7 +127,7 @@ |
127 | 127 |
\item{POSIX compliant, portable} |
128 | 128 |
\item{Fast scanning} |
129 | 129 |
\item{Supports on-access scanning (Linux and FreeBSD only)} |
130 |
- \item{Detects over 530.000 viruses, worms and trojans, including |
|
130 |
+ \item{Detects over 570.000 viruses, worms and trojans, including |
|
131 | 131 |
Microsoft Office macro viruses, mobile malware, and other threats} |
132 | 132 |
\item{Scans within archives and compressed files (also protects |
133 | 133 |
against archive bombs), built-in support includes: |
... | ... |
@@ -56,7 +56,7 @@ original version by: Nikos Drakos, CBLU, University of Leeds |
56 | 56 |
<BR> |
57 | 57 |
<BR> |
58 | 58 |
<DIV ALIGN="RIGHT"> |
59 |
-<BR> <BIG CLASS="HUGE">Clam AntiVirus 0.95 |
|
59 |
+<BR> <BIG CLASS="HUGE">Clam AntiVirus 0.95.2 |
|
60 | 60 |
<BR> <BIG CLASS="HUGE"><SPAN CLASS="textit">User Manual</SPAN> |
61 | 61 |
<BR> |
62 | 62 |
</BIG></BIG></DIV> |
... | ... |
@@ -225,7 +225,7 @@ original version by: Nikos Drakos, CBLU, University of Leeds |
225 | 225 |
<BR><HR> |
226 | 226 |
<ADDRESS> |
227 | 227 |
Tomasz Kojm |
228 |
-2009-03-23 |
|
228 |
+2009-06-10 |
|
229 | 229 |
</ADDRESS> |
230 | 230 |
</BODY> |
231 | 231 |
</HTML> |
... | ... |
@@ -56,7 +56,7 @@ original version by: Nikos Drakos, CBLU, University of Leeds |
56 | 56 |
<BR> |
57 | 57 |
<BR> |
58 | 58 |
<DIV ALIGN="RIGHT"> |
59 |
-<BR> <BIG CLASS="HUGE">Clam AntiVirus 0.95.1 |
|
59 |
+<BR> <BIG CLASS="HUGE">Clam AntiVirus 0.95.2 |
|
60 | 60 |
<BR> <BIG CLASS="HUGE"><SPAN CLASS="textit">User Manual</SPAN> |
61 | 61 |
<BR> |
62 | 62 |
</BIG></BIG></DIV> |
... | ... |
@@ -225,7 +225,7 @@ original version by: Nikos Drakos, CBLU, University of Leeds |
225 | 225 |
<BR><HR> |
226 | 226 |
<ADDRESS> |
227 | 227 |
Tomasz Kojm |
228 |
-2009-03-23 |
|
228 |
+2009-06-10 |
|
229 | 229 |
</ADDRESS> |
230 | 230 |
</BODY> |
231 | 231 |
</HTML> |
... | ... |
@@ -67,7 +67,7 @@ Features</A> |
67 | 67 |
</LI> |
68 | 68 |
<LI>Supports on-access scanning (Linux and FreeBSD only) |
69 | 69 |
</LI> |
70 |
-<LI>Detects over 530.000 viruses, worms and trojans, including |
|
70 |
+<LI>Detects over 570.000 viruses, worms and trojans, including |
|
71 | 71 |
Microsoft Office macro viruses, mobile malware, and other threats |
72 | 72 |
</LI> |
73 | 73 |
<LI>Scans within archives and compressed files (also protects |
... | ... |
@@ -183,7 +183,7 @@ Features</A> |
183 | 183 |
<!--End of Navigation Panel--> |
184 | 184 |
<ADDRESS> |
185 | 185 |
Tomasz Kojm |
186 |
-2009-03-23 |
|
186 |
+2009-06-10 |
|
187 | 187 |
</ADDRESS> |
188 | 188 |
</BODY> |
189 | 189 |
</HTML> |
... | ... |
@@ -64,11 +64,11 @@ Mathematics Department, Macquarie University, Sydney. |
64 | 64 |
The command line arguments were: <BR> |
65 | 65 |
<STRONG>latex2html</STRONG> <TT>-local_icons clamdoc.tex</TT> |
66 | 66 |
<P> |
67 |
-The translation was initiated by Tomasz Kojm on 2009-03-23 |
|
67 |
+The translation was initiated by Tomasz Kojm on 2009-06-10 |
|
68 | 68 |
<BR><HR> |
69 | 69 |
<ADDRESS> |
70 | 70 |
Tomasz Kojm |
71 |
-2009-03-23 |
|
71 |
+2009-06-10 |
|
72 | 72 |
</ADDRESS> |
73 | 73 |
</BODY> |
74 | 74 |
</HTML> |
... | ... |
@@ -49,6 +49,7 @@ |
49 | 49 |
#include "mspack.h" |
50 | 50 |
#include "cltypes.h" |
51 | 51 |
#include "chmunpack.h" |
52 |
+#include "cab.h" |
|
52 | 53 |
|
53 | 54 |
#ifndef HAVE_ATTRIB_PACKED |
54 | 55 |
#define __attribute__(x) |
... | ... |
@@ -682,7 +683,7 @@ static int read_sys_reset_table(int fd, chm_metadata_t *metadata, lzx_reset_tabl |
682 | 682 |
/* This section interfaces to the mspack files. As such, this is a */ |
683 | 683 |
/* little bit dirty compared to my usual code */ |
684 | 684 |
|
685 |
-static int chm_decompress_stream(int fd, chm_metadata_t *metadata, const char *dirname) |
|
685 |
+static int chm_decompress_stream(int fd, chm_metadata_t *metadata, const char *dirname, cli_ctx *ctx) |
|
686 | 686 |
{ |
687 | 687 |
lzx_content_t lzx_content; |
688 | 688 |
lzx_reset_table_t lzx_reset_table; |
... | ... |
@@ -690,6 +691,7 @@ static int chm_decompress_stream(int fd, chm_metadata_t *metadata, const char *d |
690 | 690 |
int window_bits, length, tmpfd, retval=-1; |
691 | 691 |
struct lzx_stream * stream; |
692 | 692 |
char filename[1024]; |
693 |
+ struct cab_file file; |
|
693 | 694 |
|
694 | 695 |
snprintf(filename, 1024, "%s/clamav-unchm.bin", dirname); |
695 | 696 |
tmpfd = open(filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU); |
... | ... |
@@ -753,10 +755,12 @@ static int chm_decompress_stream(int fd, chm_metadata_t *metadata, const char *d |
753 | 753 |
if ((uint64_t) lseek(fd, lzx_content.offset, SEEK_SET) != lzx_content.offset) { |
754 | 754 |
goto abort; |
755 | 755 |
} |
756 |
- |
|
756 |
+ |
|
757 |
+ memset(&file, 0, sizeof(struct cab_file)); |
|
758 |
+ file.max_size = ctx->engine->maxfilesize; |
|
757 | 759 |
stream = lzx_init(fd, tmpfd, window_bits, |
758 | 760 |
lzx_control.reset_interval / LZX_FRAME_SIZE, |
759 |
- 4096, length, NULL, NULL); |
|
761 |
+ 4096, length, &file, NULL); |
|
760 | 762 |
if (!stream) { |
761 | 763 |
cli_dbgmsg("lzx_init failed\n"); |
762 | 764 |
goto abort; |
... | ... |
@@ -811,9 +815,10 @@ void cli_chm_close(chm_metadata_t *metadata) |
811 | 811 |
#endif |
812 | 812 |
} |
813 | 813 |
|
814 |
-int cli_chm_extract_file(int fd, char *dirname, chm_metadata_t *metadata) |
|
814 |
+int cli_chm_extract_file(int fd, char *dirname, chm_metadata_t *metadata, cli_ctx *ctx) |
|
815 | 815 |
{ |
816 | 816 |
char filename[1024]; |
817 |
+ uint64_t len; |
|
817 | 818 |
|
818 | 819 |
cli_dbgmsg("in cli_chm_extract_file\n"); |
819 | 820 |
|
... | ... |
@@ -826,8 +831,9 @@ int cli_chm_extract_file(int fd, char *dirname, chm_metadata_t *metadata) |
826 | 826 |
if (metadata->ofd < 0) { |
827 | 827 |
return CL_ECREAT; |
828 | 828 |
} |
829 |
- if (chm_copy_file_data(metadata->ufd, metadata->ofd, metadata->file_length) != metadata->file_length) { |
|
830 |
- cli_dbgmsg("failed to copy %lu bytes\n", (unsigned long int) metadata->file_length); |
|
829 |
+ len = ctx->engine->maxfilesize ? (MIN(ctx->engine->maxfilesize, metadata->file_length)) : metadata->file_length; |
|
830 |
+ if (chm_copy_file_data(metadata->ufd, metadata->ofd, len) != len) { |
|
831 |
+ cli_dbgmsg("failed to copy %lu bytes\n", (unsigned long int) len); |
|
831 | 832 |
close(metadata->ofd); |
832 | 833 |
return CL_EFORMAT; /* most likely a corrupted file */ |
833 | 834 |
} |
... | ... |
@@ -857,7 +863,7 @@ int cli_chm_prepare_file(int fd, char *dirname, chm_metadata_t *metadata) |
857 | 857 |
return retval; |
858 | 858 |
} |
859 | 859 |
|
860 |
-int cli_chm_open(int fd, const char *dirname, chm_metadata_t *metadata) |
|
860 |
+int cli_chm_open(int fd, const char *dirname, chm_metadata_t *metadata, cli_ctx *ctx) |
|
861 | 861 |
{ |
862 | 862 |
struct stat statbuf; |
863 | 863 |
int retval; |
... | ... |
@@ -926,7 +932,7 @@ int cli_chm_open(int fd, const char *dirname, chm_metadata_t *metadata) |
926 | 926 |
goto abort; |
927 | 927 |
} |
928 | 928 |
|
929 |
- metadata->ufd = chm_decompress_stream(fd, metadata, dirname); |
|
929 |
+ metadata->ufd = chm_decompress_stream(fd, metadata, dirname, ctx); |
|
930 | 930 |
if (metadata->ufd == -1) { |
931 | 931 |
goto abort; |
932 | 932 |
} |
... | ... |
@@ -28,6 +28,7 @@ |
28 | 28 |
#endif |
29 | 29 |
|
30 | 30 |
#include "cltypes.h" |
31 |
+#include "others.h" |
|
31 | 32 |
|
32 | 33 |
#ifndef HAVE_ATTRIB_PACKED |
33 | 34 |
#define __attribute__(x) |
... | ... |
@@ -113,8 +114,8 @@ typedef struct chm_metadata_tag { |
113 | 113 |
uint16_t chunk_entries; |
114 | 114 |
} chm_metadata_t; |
115 | 115 |
|
116 |
-int cli_chm_open(int fd, const char *dirname, chm_metadata_t *metadata); |
|
116 |
+int cli_chm_open(int fd, const char *dirname, chm_metadata_t *metadata, cli_ctx *ctx); |
|
117 | 117 |
int cli_chm_prepare_file(int fd, char *dirname, chm_metadata_t *metadata); |
118 |
-int cli_chm_extract_file(int fd, char *dirname, chm_metadata_t *metadata); |
|
118 |
+int cli_chm_extract_file(int fd, char *dirname, chm_metadata_t *metadata, cli_ctx *ctx); |
|
119 | 119 |
void cli_chm_close(chm_metadata_t *metadata); |
120 | 120 |
#endif |
... | ... |
@@ -991,7 +991,7 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
991 | 991 |
if((pt->type > type || pt->type >= CL_TYPE_SFX || pt->type == CL_TYPE_MSEXE) && (!pt->rtype || ftype == pt->rtype)) { |
992 | 992 |
cli_dbgmsg("Matched signature for file type %s\n", pt->virname); |
993 | 993 |
type = pt->type; |
994 |
- if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < MAX_EMBEDDED_OBJ || type == CL_TYPE_ZIPSFX) && ((ftype == CL_TYPE_MSEXE && type >= CL_TYPE_SFX) || ((ftype == CL_TYPE_MSEXE || ftype == CL_TYPE_ZIP || ftype == CL_TYPE_MSOLE2) && type == CL_TYPE_MSEXE))) { |
|
994 |
+ if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < MAX_EMBEDDED_OBJ || type == CL_TYPE_ZIPSFX) && (type >= CL_TYPE_SFX || ((ftype == CL_TYPE_MSEXE || ftype == CL_TYPE_ZIP || ftype == CL_TYPE_MSOLE2) && type == CL_TYPE_MSEXE))) { |
|
995 | 995 |
/* FIXME: we don't know which offset of the first part is the correct one */ |
996 | 996 |
for(j = 1; j <= CLI_DEFAULT_AC_TRACKLEN && offmatrix[0][j] != -1; j++) { |
997 | 997 |
if(ac_addtype(ftoffset, type, offmatrix[pt->parts - 1][j], ctx)) { |
... | ... |
@@ -1053,7 +1053,7 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
1053 | 1053 |
if((pt->type > type || pt->type >= CL_TYPE_SFX || pt->type == CL_TYPE_MSEXE) && (!pt->rtype || ftype == pt->rtype)) { |
1054 | 1054 |
cli_dbgmsg("Matched signature for file type %s at %u\n", pt->virname, realoff); |
1055 | 1055 |
type = pt->type; |
1056 |
- if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < MAX_EMBEDDED_OBJ || type == CL_TYPE_ZIPSFX) && ((ftype == CL_TYPE_MSEXE && type >= CL_TYPE_SFX) || ((ftype == CL_TYPE_MSEXE || ftype == CL_TYPE_ZIP || ftype == CL_TYPE_MSOLE2) && type == CL_TYPE_MSEXE))) { |
|
1056 |
+ if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < MAX_EMBEDDED_OBJ || type == CL_TYPE_ZIPSFX) && (type >= CL_TYPE_SFX || ((ftype == CL_TYPE_MSEXE || ftype == CL_TYPE_ZIP || ftype == CL_TYPE_MSOLE2) && type == CL_TYPE_MSEXE))) { |
|
1057 | 1057 |
|
1058 | 1058 |
if(ac_addtype(ftoffset, type, realoff, ctx)) { |
1059 | 1059 |
if(info.exeinfo.section) |
... | ... |
@@ -347,6 +347,23 @@ static int mszip_read_lens(struct mszip_stream *zip) { |
347 | 347 |
return 0; |
348 | 348 |
} |
349 | 349 |
|
350 |
+static int mspack_write(int fd, const void *buff, unsigned int count, struct cab_file *file) |
|
351 |
+{ |
|
352 |
+ int ret; |
|
353 |
+ |
|
354 |
+ if(file->max_size) { |
|
355 |
+ if(file->written_size >= file->max_size) |
|
356 |
+ return CL_BREAK; |
|
357 |
+ |
|
358 |
+ if(file->written_size + count > file->max_size) |
|
359 |
+ count = file->max_size - file->written_size; |
|
360 |
+ } |
|
361 |
+ if((ret = cli_writen(fd, buff, count)) > 0) |
|
362 |
+ file->written_size += ret; |
|
363 |
+ |
|
364 |
+ return (ret == -1) ? CL_EWRITE : CL_SUCCESS; |
|
365 |
+} |
|
366 |
+ |
|
350 | 367 |
/* a clean implementation of RFC 1951 / inflate */ |
351 | 368 |
static int mszip_inflate(struct mszip_stream *zip) { |
352 | 369 |
unsigned int last_block, block_type, distance, length, this_run, i; |
... | ... |
@@ -613,7 +630,7 @@ int mszip_decompress(struct mszip_stream *zip, off_t out_bytes) { |
613 | 613 |
register int bits_left; |
614 | 614 |
unsigned char *i_ptr, *i_end; |
615 | 615 |
|
616 |
- int i, state, error; |
|
616 |
+ int i, ret, state, error; |
|
617 | 617 |
|
618 | 618 |
/* easy answers */ |
619 | 619 |
if (!zip || (out_bytes < 0)) return CL_ENULLARG; |
... | ... |
@@ -623,8 +640,8 @@ int mszip_decompress(struct mszip_stream *zip, off_t out_bytes) { |
623 | 623 |
i = zip->o_end - zip->o_ptr; |
624 | 624 |
if ((off_t) i > out_bytes) i = (int) out_bytes; |
625 | 625 |
if (i) { |
626 |
- if (zip->wflag && cli_writen(zip->ofd, zip->o_ptr, i) != i) { |
|
627 |
- return zip->error = CL_EWRITE; |
|
626 |
+ if (zip->wflag && (ret = mspack_write(zip->ofd, zip->o_ptr, i, zip->file)) != CL_SUCCESS) { |
|
627 |
+ return zip->error = ret; |
|
628 | 628 |
} |
629 | 629 |
zip->o_ptr += i; |
630 | 630 |
out_bytes -= i; |
... | ... |
@@ -669,8 +686,8 @@ int mszip_decompress(struct mszip_stream *zip, off_t out_bytes) { |
669 | 669 |
/* write a frame */ |
670 | 670 |
i = (out_bytes < (off_t)zip->bytes_output) ? |
671 | 671 |
(int)out_bytes : zip->bytes_output; |
672 |
- if (zip->wflag && cli_writen(zip->ofd, zip->o_ptr, i) != i) { |
|
673 |
- return zip->error = CL_EWRITE; |
|
672 |
+ if (zip->wflag && (ret = mspack_write(zip->ofd, zip->o_ptr, i, zip->file)) != CL_SUCCESS) { |
|
673 |
+ return zip->error = ret; |
|
674 | 674 |
} |
675 | 675 |
|
676 | 676 |
/* mspack errors (i.e. read errors) are fatal and can't be recovered */ |
... | ... |
@@ -1085,7 +1102,7 @@ int lzx_decompress(struct lzx_stream *lzx, off_t out_bytes) { |
1085 | 1085 |
unsigned char *i_ptr, *i_end; |
1086 | 1086 |
|
1087 | 1087 |
int match_length, length_footer, extra, verbatim_bits, bytes_todo; |
1088 |
- int this_run, main_element, aligned_bits, j; |
|
1088 |
+ int this_run, main_element, aligned_bits, j, ret; |
|
1089 | 1089 |
unsigned char *window, *runsrc, *rundest, buf[12]; |
1090 | 1090 |
unsigned int frame_size=0, end_frame, match_offset, window_posn; |
1091 | 1091 |
unsigned int R0, R1, R2; |
... | ... |
@@ -1098,8 +1115,8 @@ int lzx_decompress(struct lzx_stream *lzx, off_t out_bytes) { |
1098 | 1098 |
i = lzx->o_end - lzx->o_ptr; |
1099 | 1099 |
if ((off_t) i > out_bytes) i = (int) out_bytes; |
1100 | 1100 |
if (i) { |
1101 |
- if (lzx->wflag && cli_writen(lzx->ofd, lzx->o_ptr, i) != i) { |
|
1102 |
- return lzx->error = CL_EWRITE; |
|
1101 |
+ if (lzx->wflag && (ret = mspack_write(lzx->ofd, lzx->o_ptr, i, lzx->file)) != CL_SUCCESS) { |
|
1102 |
+ return lzx->error = ret; |
|
1103 | 1103 |
} |
1104 | 1104 |
lzx->o_ptr += i; |
1105 | 1105 |
lzx->offset += i; |
... | ... |
@@ -1474,8 +1491,8 @@ int lzx_decompress(struct lzx_stream *lzx, off_t out_bytes) { |
1474 | 1474 |
|
1475 | 1475 |
/* write a frame */ |
1476 | 1476 |
i = (out_bytes < (off_t)frame_size) ? (unsigned int)out_bytes : frame_size; |
1477 |
- if (lzx->wflag && cli_writen(lzx->ofd, lzx->o_ptr, i) != i) { |
|
1478 |
- return lzx->error = CL_EWRITE; |
|
1477 |
+ if (lzx->wflag && (ret = mspack_write(lzx->ofd, lzx->o_ptr, i, lzx->file)) != CL_SUCCESS) { |
|
1478 |
+ return lzx->error = ret; |
|
1479 | 1479 |
} |
1480 | 1480 |
lzx->o_ptr += i; |
1481 | 1481 |
lzx->offset += i; |
... | ... |
@@ -1794,7 +1811,7 @@ struct qtm_stream *qtm_init(int fd, int ofd, |
1794 | 1794 |
int qtm_decompress(struct qtm_stream *qtm, off_t out_bytes) { |
1795 | 1795 |
unsigned int frame_start, frame_end, window_posn, match_offset, range; |
1796 | 1796 |
unsigned char *window, *i_ptr, *i_end, *runsrc, *rundest; |
1797 |
- int i, j, selector, extra, sym, match_length; |
|
1797 |
+ int i, j, selector, extra, sym, match_length, ret; |
|
1798 | 1798 |
unsigned short H, L, C, symf; |
1799 | 1799 |
|
1800 | 1800 |
register unsigned int bit_buffer; |
... | ... |
@@ -1809,8 +1826,8 @@ int qtm_decompress(struct qtm_stream *qtm, off_t out_bytes) { |
1809 | 1809 |
i = qtm->o_end - qtm->o_ptr; |
1810 | 1810 |
if ((off_t) i > out_bytes) i = (int) out_bytes; |
1811 | 1811 |
if (i) { |
1812 |
- if (qtm->wflag && cli_writen(qtm->ofd, qtm->o_ptr, i) != i) { |
|
1813 |
- return qtm->error = CL_EWRITE; |
|
1812 |
+ if (qtm->wflag && (ret = mspack_write(qtm->ofd, qtm->o_ptr, i, qtm->file)) != CL_SUCCESS) { |
|
1813 |
+ return qtm->error = ret; |
|
1814 | 1814 |
} |
1815 | 1815 |
qtm->o_ptr += i; |
1816 | 1816 |
out_bytes -= i; |
... | ... |
@@ -1928,8 +1945,8 @@ int qtm_decompress(struct qtm_stream *qtm, off_t out_bytes) { |
1928 | 1928 |
if (window_posn == qtm->window_size) { |
1929 | 1929 |
/* flush all currently stored data */ |
1930 | 1930 |
i = (qtm->o_end - qtm->o_ptr); |
1931 |
- if (qtm->wflag && cli_writen(qtm->ofd, qtm->o_ptr, i) != i) { |
|
1932 |
- return qtm->error = CL_EWRITE; |
|
1931 |
+ if (qtm->wflag && (ret = mspack_write(qtm->ofd, qtm->o_ptr, i, qtm->file)) != CL_SUCCESS) { |
|
1932 |
+ return qtm->error = ret; |
|
1933 | 1933 |
} |
1934 | 1934 |
out_bytes -= i; |
1935 | 1935 |
qtm->o_ptr = &window[0]; |
... | ... |
@@ -1944,8 +1961,8 @@ int qtm_decompress(struct qtm_stream *qtm, off_t out_bytes) { |
1944 | 1944 |
|
1945 | 1945 |
if (out_bytes) { |
1946 | 1946 |
i = (int) out_bytes; |
1947 |
- if (qtm->wflag && cli_writen(qtm->ofd, qtm->o_ptr, i) != i) { |
|
1948 |
- return qtm->error = CL_EWRITE; |
|
1947 |
+ if (qtm->wflag && (ret = mspack_write(qtm->ofd, qtm->o_ptr, i, qtm->file)) != CL_SUCCESS) { |
|
1948 |
+ return qtm->error = ret; |
|
1949 | 1949 |
} |
1950 | 1950 |
qtm->o_ptr += i; |
1951 | 1951 |
} |
... | ... |
@@ -711,19 +711,30 @@ static int cli_scanmscab(int desc, cli_ctx *ctx, off_t sfx_offset) |
711 | 711 |
for(file = cab.files; file; file = file->next) { |
712 | 712 |
files++; |
713 | 713 |
|
714 |
- if(cli_checklimits("CAB", ctx, file->length, 0, 0)!=CL_CLEAN) |
|
715 |
- continue; |
|
716 |
- |
|
717 | 714 |
if(!(tempname = cli_gentemp(ctx->engine->tmpdir))) { |
718 | 715 |
ret = CL_EMEM; |
719 | 716 |
break; |
720 | 717 |
} |
721 |
- cli_dbgmsg("CAB: Extracting file %s to %s, size %u\n", file->name, tempname, file->length); |
|
722 |
- if((ret = cab_extract(file, tempname))) |
|
723 |
- cli_dbgmsg("CAB: Failed to extract file: %s\n", cl_strerror(ret)); |
|
718 |
+ |
|
719 |
+ if(ctx->engine->maxscansize && ctx->scansize >= ctx->engine->maxscansize) { |
|
720 |
+ ret = CL_CLEAN; |
|
721 |
+ break; |
|
722 |
+ } |
|
723 |
+ if(ctx->engine->maxscansize && ctx->scansize + ctx->engine->maxfilesize >= ctx->engine->maxscansize) |
|
724 |
+ file->max_size = ctx->engine->maxscansize - ctx->scansize; |
|
724 | 725 |
else |
725 |
- ret = cli_scanfile(tempname, ctx); |
|
726 |
+ file->max_size = ctx->engine->maxfilesize; |
|
726 | 727 |
|
728 |
+ cli_dbgmsg("CAB: Extracting file %s to %s, size %u, max_size: %u\n", file->name, tempname, file->length, (unsigned int) file->max_size); |
|
729 |
+ file->written_size = 0; |
|
730 |
+ if((ret = cab_extract(file, tempname))) { |
|
731 |
+ cli_dbgmsg("CAB: Failed to extract file: %s\n", cl_strerror(ret)); |
|
732 |
+ } else { |
|
733 |
+ if(file->length != file->written_size) |
|
734 |
+ cli_dbgmsg("CAB: Length from header %u but wrote %u bytes\n", (unsigned int) file->length, (unsigned int) file->written_size); |
|
735 |
+ |
|
736 |
+ ret = cli_scanfile(tempname, ctx); |
|
737 |
+ } |
|
727 | 738 |
if(!ctx->engine->keeptmp) { |
728 | 739 |
if (cli_unlink(tempname)) { |
729 | 740 |
free(tempname); |
... | ... |
@@ -1268,7 +1279,7 @@ static int cli_scanmschm(int desc, cli_ctx *ctx) |
1268 | 1268 |
return CL_ETMPDIR; |
1269 | 1269 |
} |
1270 | 1270 |
|
1271 |
- ret = cli_chm_open(desc, dir, &metadata); |
|
1271 |
+ ret = cli_chm_open(desc, dir, &metadata, ctx); |
|
1272 | 1272 |
if (ret != CL_SUCCESS) { |
1273 | 1273 |
if(!ctx->engine->keeptmp) |
1274 | 1274 |
cli_rmdirs(dir); |
... | ... |
@@ -1282,7 +1293,7 @@ static int cli_scanmschm(int desc, cli_ctx *ctx) |
1282 | 1282 |
if (ret != CL_SUCCESS) { |
1283 | 1283 |
break; |
1284 | 1284 |
} |
1285 |
- ret = cli_chm_extract_file(desc, dir, &metadata); |
|
1285 |
+ ret = cli_chm_extract_file(desc, dir, &metadata, ctx); |
|
1286 | 1286 |
if (ret == CL_SUCCESS) { |
1287 | 1287 |
lseek(metadata.ofd, 0, SEEK_SET); |
1288 | 1288 |
rc = cli_magic_scandesc(metadata.ofd, ctx); |
... | ... |
@@ -1706,15 +1717,11 @@ static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type, uint8_t typercg, |
1706 | 1706 |
struct stat sb; |
1707 | 1707 |
|
1708 | 1708 |
|
1709 |
- if(typercg) switch(type) { |
|
1710 |
- case CL_TYPE_TEXT_ASCII: |
|
1711 |
- case CL_TYPE_MSEXE: |
|
1712 |
- case CL_TYPE_ZIP: |
|
1713 |
- case CL_TYPE_MSOLE2: |
|
1714 |
- acmode |= AC_SCAN_FT; |
|
1715 |
- default: |
|
1716 |
- break; |
|
1717 |
- } |
|
1709 |
+ if(ctx->engine->maxreclevel && ctx->recursion >= ctx->engine->maxreclevel) |
|
1710 |
+ return CL_EMAXREC; |
|
1711 |
+ |
|
1712 |
+ if(typercg) |
|
1713 |
+ acmode |= AC_SCAN_FT; |
|
1718 | 1714 |
|
1719 | 1715 |
if(lseek(desc, 0, SEEK_SET) < 0) { |
1720 | 1716 |
cli_errmsg("cli_scanraw: lseek() failed\n"); |
... | ... |
@@ -1724,6 +1731,7 @@ static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type, uint8_t typercg, |
1724 | 1724 |
ret = cli_scandesc(desc, ctx, type == CL_TYPE_TEXT_ASCII ? 0 : type, 0, &ftoffset, acmode); |
1725 | 1725 |
|
1726 | 1726 |
if(ret >= CL_TYPENO) { |
1727 |
+ ctx->recursion++; |
|
1727 | 1728 |
|
1728 | 1729 |
/* |
1729 | 1730 |
if(type == CL_TYPE_TEXT_ASCII) { |
... | ... |
@@ -1735,33 +1743,34 @@ static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type, uint8_t typercg, |
1735 | 1735 |
} |
1736 | 1736 |
*/ |
1737 | 1737 |
|
1738 |
- if(nret != CL_VIRUS && (type == CL_TYPE_MSEXE || type == CL_TYPE_ZIP || type == CL_TYPE_MSOLE2)) { |
|
1738 |
+ if(nret != CL_VIRUS) { |
|
1739 | 1739 |
lastzip = lastrar = 0xdeadbeef; |
1740 | 1740 |
fpt = ftoffset; |
1741 | 1741 |
while(fpt) { |
1742 |
- switch(fpt->type) { |
|
1742 |
+ if(fpt->offset) switch(fpt->type) { |
|
1743 | 1743 |
case CL_TYPE_RARSFX: |
1744 |
- if(have_rar && SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_RAR)) { |
|
1745 |
- cli_dbgmsg("RAR-SFX signature found at %u\n", (unsigned int) fpt->offset); |
|
1744 |
+ cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset); |
|
1745 |
+ if(type != CL_TYPE_RAR && have_rar && SCAN_ARCHIVE && fpt->offset < 102400 && (DCONF_ARCH & ARCH_CONF_RAR)) { |
|
1746 |
+ cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset); |
|
1746 | 1747 |
nret = cli_scanrar(desc, ctx, fpt->offset, &lastrar); |
1747 | 1748 |
} |
1748 | 1749 |
break; |
1749 | 1750 |
|
1750 | 1751 |
case CL_TYPE_ZIPSFX: |
1751 |
- if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_ZIP) && fpt->offset) { |
|
1752 |
- cli_dbgmsg("ZIP-SFX signature found at %u\n", (unsigned int) fpt->offset); |
|
1752 |
+ if(type != CL_TYPE_ZIP && SCAN_ARCHIVE && fpt->offset < 102400 && (DCONF_ARCH & ARCH_CONF_ZIP)) { |
|
1753 |
+ cli_dbgmsg("ZIP/ZIP-SFX signature found at %u\n", (unsigned int) fpt->offset); |
|
1753 | 1754 |
nret = cli_unzip_single(desc, ctx, fpt->offset); |
1754 | 1755 |
} |
1755 | 1756 |
break; |
1756 | 1757 |
|
1757 | 1758 |
case CL_TYPE_CABSFX: |
1758 |
- if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_CAB)) { |
|
1759 |
- cli_dbgmsg("CAB-SFX signature found at %u\n", (unsigned int) fpt->offset); |
|
1759 |
+ if(type != CL_TYPE_MSCAB && SCAN_ARCHIVE && fpt->offset < 102400 && (DCONF_ARCH & ARCH_CONF_CAB)) { |
|
1760 |
+ cli_dbgmsg("CAB/CAB-SFX signature found at %u\n", (unsigned int) fpt->offset); |
|
1760 | 1761 |
nret = cli_scanmscab(desc, ctx, fpt->offset); |
1761 | 1762 |
} |
1762 | 1763 |
break; |
1763 | 1764 |
case CL_TYPE_ARJSFX: |
1764 |
- if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_ARJ)) { |
|
1765 |
+ if(type != CL_TYPE_ARJ && SCAN_ARCHIVE && fpt->offset < 102400 && (DCONF_ARCH & ARCH_CONF_ARJ)) { |
|
1765 | 1766 |
cli_dbgmsg("ARJ-SFX signature found at %u\n", (unsigned int) fpt->offset); |
1766 | 1767 |
nret = cli_scanarj(desc, ctx, fpt->offset, &lastrar); |
1767 | 1768 |
} |
... | ... |
@@ -1782,14 +1791,14 @@ static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type, uint8_t typercg, |
1782 | 1782 |
break; |
1783 | 1783 |
|
1784 | 1784 |
case CL_TYPE_PDF: |
1785 |
- if(SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF)) { |
|
1785 |
+ if(type != CL_TYPE_PDF && SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF)) { |
|
1786 | 1786 |
cli_dbgmsg("PDF signature found at %u\n", (unsigned int) fpt->offset); |
1787 | 1787 |
nret = cli_scanpdf(desc, ctx, fpt->offset); |
1788 | 1788 |
} |
1789 | 1789 |
break; |
1790 | 1790 |
|
1791 | 1791 |
case CL_TYPE_MSEXE: |
1792 |
- if(SCAN_PE && ctx->dconf->pe && fpt->offset) { |
|
1792 |
+ if(SCAN_PE && (type == CL_TYPE_MSEXE || type == CL_TYPE_ZIP || type == CL_TYPE_MSOLE2) && ctx->dconf->pe) { |
|
1793 | 1793 |
fstat(desc, &sb); |
1794 | 1794 |
if(sb.st_size > 10485760) |
1795 | 1795 |
break; |
... | ... |
@@ -1823,8 +1832,6 @@ static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type, uint8_t typercg, |
1823 | 1823 |
} |
1824 | 1824 |
} |
1825 | 1825 |
|
1826 |
- ctx->recursion++; |
|
1827 |
- |
|
1828 | 1826 |
if(nret != CL_VIRUS) switch(ret) { |
1829 | 1827 |
case CL_TYPE_HTML: |
1830 | 1828 |
if(SCAN_HTML && type == CL_TYPE_TEXT_ASCII && (DCONF_DOC & DOC_CONF_HTML)) { |
... | ... |
@@ -1864,6 +1871,10 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx) |
1864 | 1864 |
struct stat sb; |
1865 | 1865 |
uint8_t typercg = 1; |
1866 | 1866 |
|
1867 |
+ if(ctx->engine->maxreclevel && ctx->recursion > ctx->engine->maxreclevel) { |
|
1868 |
+ cli_dbgmsg("cli_magic_scandesc: Archive recursion limit exceeded (%u, max: %u)\n", ctx->recursion, ctx->engine->maxreclevel); |
|
1869 |
+ return CL_CLEAN; |
|
1870 |
+ } |
|
1867 | 1871 |
|
1868 | 1872 |
if(fstat(desc, &sb) == -1) { |
1869 | 1873 |
cli_errmsg("magic_scandesc: Can't fstat descriptor %d\n", desc); |
... | ... |
@@ -1885,19 +1896,17 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx) |
1885 | 1885 |
return CL_EMALFDB; |
1886 | 1886 |
} |
1887 | 1887 |
|
1888 |
- if(!ctx->options) { /* raw mode (stdin, etc.) */ |
|
1889 |
- cli_dbgmsg("Raw mode: No support for special files\n"); |
|
1890 |
- if((ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR)) == CL_VIRUS) |
|
1891 |
- cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc); |
|
1892 |
- return ret; |
|
1893 |
- } |
|
1894 |
- |
|
1895 | 1888 |
if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN) |
1896 | 1889 |
return CL_CLEAN; |
1897 | 1890 |
|
1898 |
- if((SCAN_MAIL || SCAN_ARCHIVE) && ctx->engine->maxreclevel && ctx->recursion > ctx->engine->maxreclevel) { |
|
1899 |
- cli_dbgmsg("Archive recursion limit exceeded (level = %u).\n", ctx->recursion); |
|
1900 |
- return CL_CLEAN; |
|
1891 |
+ if(!ctx->options || (ctx->recursion == ctx->engine->maxreclevel)) { /* raw mode (stdin, etc.) or last level of recursion */ |
|
1892 |
+ if(ctx->recursion == ctx->engine->maxreclevel) |
|
1893 |
+ cli_dbgmsg("cli_magic_scandesc: Hit recursion limit, only scanning raw file\n"); |
|
1894 |
+ else |
|
1895 |
+ cli_dbgmsg("Raw mode: No support for special files\n"); |
|
1896 |
+ if((ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR)) == CL_VIRUS) |
|
1897 |
+ cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc); |
|
1898 |
+ return ret; |
|
1901 | 1899 |
} |
1902 | 1900 |
|
1903 | 1901 |
lseek(desc, 0, SEEK_SET); |
... | ... |
@@ -352,7 +352,7 @@ static void execute_standard_filter(rarvm_data_t *rarvm_data, rarvm_standard_fil |
352 | 352 |
data_size = rarvm_data->R[4]; |
353 | 353 |
file_offset = rarvm_data->R[6]; |
354 | 354 |
|
355 |
- if ((data_size >= VM_GLOBALMEMADDR) || (data_size < 4)) { |
|
355 |
+ if (((unsigned int)data_size >= VM_GLOBALMEMADDR) || (data_size < 4)) { |
|
356 | 356 |
break; |
357 | 357 |
} |
358 | 358 |
|
... | ... |
@@ -382,7 +382,7 @@ static void execute_standard_filter(rarvm_data_t *rarvm_data, rarvm_standard_fil |
382 | 382 |
data_size = rarvm_data->R[4]; |
383 | 383 |
file_offset = rarvm_data->R[6]; |
384 | 384 |
|
385 |
- if ((data_size >= VM_GLOBALMEMADDR) || (data_size < 21)) { |
|
385 |
+ if (((unsigned int)data_size >= VM_GLOBALMEMADDR) || (data_size < 21)) { |
|
386 | 386 |
break; |
387 | 387 |
} |
388 | 388 |
|
... | ... |
@@ -425,7 +425,7 @@ static void execute_standard_filter(rarvm_data_t *rarvm_data, rarvm_standard_fil |
425 | 425 |
border = data_size*2; |
426 | 426 |
|
427 | 427 |
SET_VALUE(FALSE, &rarvm_data->mem[VM_GLOBALMEMADDR+0x20], data_size); |
428 |
- if (data_size >= VM_GLOBALMEMADDR/2) { |
|
428 |
+ if ((unsigned int)data_size >= VM_GLOBALMEMADDR/2) { |
|
429 | 429 |
break; |
430 | 430 |
} |
431 | 431 |
for (cur_channel=0 ; cur_channel < channels ; cur_channel++) { |
... | ... |
@@ -444,7 +444,7 @@ static void execute_standard_filter(rarvm_data_t *rarvm_data, rarvm_standard_fil |
444 | 444 |
dest_data = src_data + data_size; |
445 | 445 |
|
446 | 446 |
SET_VALUE(FALSE, &rarvm_data->mem[VM_GLOBALMEMADDR+0x20], data_size); |
447 |
- if (data_size >= VM_GLOBALMEMADDR/2) { |
|
447 |
+ if ((unsigned int)data_size >= VM_GLOBALMEMADDR/2) { |
|
448 | 448 |
break; |
449 | 449 |
} |
450 | 450 |
for (cur_channel=0 ; cur_channel < channels; cur_channel++) { |
... | ... |
@@ -488,7 +488,7 @@ static void execute_standard_filter(rarvm_data_t *rarvm_data, rarvm_standard_fil |
488 | 488 |
dest_data = src_data + data_size; |
489 | 489 |
|
490 | 490 |
SET_VALUE(FALSE, &rarvm_data->mem[VM_GLOBALMEMADDR+0x20], data_size); |
491 |
- if (data_size >= VM_GLOBALMEMADDR/2) { |
|
491 |
+ if ((unsigned int)data_size >= VM_GLOBALMEMADDR/2) { |
|
492 | 492 |
break; |
493 | 493 |
} |
494 | 494 |
for (cur_channel=0 ; cur_channel < channels ; cur_channel++) { |
... | ... |
@@ -549,7 +549,7 @@ static void execute_standard_filter(rarvm_data_t *rarvm_data, rarvm_standard_fil |
549 | 549 |
data_size = rarvm_data->R[4]; |
550 | 550 |
src_pos = 0; |
551 | 551 |
dest_pos = data_size; |
552 |
- if (data_size >= VM_GLOBALMEMADDR/2) { |
|
552 |
+ if ((unsigned int)data_size >= VM_GLOBALMEMADDR/2) { |
|
553 | 553 |
break; |
554 | 554 |
} |
555 | 555 |
while (src_pos < data_size) { |