Steve Morgan authored on 2013/10/09 06:48:58
Showing 15 changed files
... ...
@@ -1,3 +1,7 @@
1
+Thu Oct 3 10:49:11 2013 EDT 2013 (dar)
2
+------------------------------------
3
+ * bb #1570: Support ADC compression in DMG
4
+
1 5
 Wed Oct 2 11:22:40 2013 EDT 2013 (dar)
2 6
 ------------------------------------
3 7
  * bb #9053: ClamAV 0.98 can't be compiled on FreeBSD 7
... ...
@@ -316,6 +316,7 @@
316 316
     \begin{verbatim}
317 317
 	$ ./configure --enable-milter
318 318
     \end{verbatim}
319
+    See section /ref{sec:clamavmilter} for more details on clamav-milter.
319 320
 
320 321
     \subsection{Running unit tests}\label{unit-testing}
321 322
 	ClamAV includes unit tests that allow you to test that the compiled binaries work correctly on your platform.
... ...
@@ -391,8 +392,36 @@ $ CK_FORK=no ./libtool --mode=execute valgrind unit_tests/check-clamav
391 391
 	 \end{verbatim}	
392 392
 	\end{itemize}
393 393
 
394
+    \subsection{Obtain Latest ClamAV anti-virus signature databases}
395
+    Before you can run ClamAV in daemon mode (clamd), 'clamdscan',
396
+    or 'clamscan' which is ClamAV's command line virus scanner,
397
+    you must have ClamAV Virus Database (.cvd) file(s) installed
398
+    in the appropriate location on your system.  The default
399
+    location for these database files are /usr/local/share/clamav
400
+    (in Linux/Unix).
401
+    \\\\
402
+    Here is a listing of currently available ClamAV Virus Database Files:
403
+    \\\\
404
+    bytecode.cvd        (signatures to detect bytecode in files)
405
+    main.cvd            (main ClamAV virus database file)
406
+    daily.cvd           (daily update file for ClamAV virus databases)
407
+    safebrowsing.cvd    (virus signatures for safe browsing)
408
+    \\\\
409
+    These files can be downloaded via HTTP from the main ClamAV website
410
+    or via the 'freshclam' utility on a periodic basis.  Using 'freshclam'
411
+    is the preferred method of keeping the ClamAV virus database files
412
+    up to date without manual intervention (see section \ref{conf:freshclam} for
413
+    information on how to configure 'freshclam' for automatic updating and section
414
+    \ref{sec:freshclam} for additional details on freshclam).
415
+
394 416
     \section{Configuration}
395 417
 
418
+    \subsubsection{clamconf}
419
+    Before proceeding with the steps below, you should
420
+    run the 'clamconf' command, which gives important information
421
+    about your ClamAV configuration. See section \ref{sec:clamconf} 
422
+    for more details.
423
+
396 424
     \subsection{clamd}
397 425
     Before you start using the daemon you have to edit the configuration file
398 426
     (in other case \verb+clamd+ won't run):
... ...
@@ -437,14 +466,31 @@ $ CK_FORK=no ./libtool --mode=execute valgrind unit_tests/check-clamav
437 437
     Now configure Clamuko in \verb+clamd.conf+ and read the \ref{clamuko}
438 438
     section.
439 439
 
440
-    \subsection{clamav-milter}
440
+    \subsection{clamav-milter}\label{sec:clamavmilter}
441 441
     ClamAV $\ge0.95$ includes a new, redesigned clamav-milter. The most notable
442 442
     difference is that the internal mode has been dropped and now a working
443 443
     clamd companion is required. The second important difference is that now
444
-    the milter has got its own configuration and log files. To compile ClamAV
445
-    with the clamav-milter just run \verb+./configure+ \verb+--enable-milter+
446
-    and make as usual. Please consult your MTA's manual on how to connect it
447
-    with the milter.
444
+    the milter has got its own configuration and log files. 
445
+
446
+    To compile ClamAV with the clamav-milter just run \verb+./configure+
447
+    \verb+--enable-milter+ and make as usual. In order to use the 
448
+    '--enable-milter' option with 'configure', your system MUST have the milter 
449
+    library installed.  If you use the '--enable-milter' option without the 
450
+    library being installed, you will most likely see output like this during 
451
+    'configure':
452
+    \begin{verbatim}
453
+        checking for libiconv_open in -liconv... no
454
+        checking for iconv... yes
455
+        checking whether in_port_t is defined... yes
456
+        checking for in_addr_t definition... yes
457
+        checking for mi_stop in -lmilter... no
458
+        checking for library containing strlcpy... no
459
+        checking for mi_stop in -lmilter... no
460
+        configure: error: Cannot find libmilter
461
+    \end{verbatim}
462
+    At which point the 'configure' script will stop processing.
463
+    \\\\
464
+    Please consult your MTA's manual on how to connect ClamAV with the milter.
448 465
 
449 466
     \subsection{Testing}
450 467
     Try to scan recursively the source directory:
... ...
@@ -462,7 +508,7 @@ $ CK_FORK=no ./libtool --mode=execute valgrind unit_tests/check-clamav
462 462
     Please note that the scanned files must be accessible by the user running
463 463
     \verb+clamd+ or you will get an error.
464 464
 
465
-    \subsection{Setting up auto-updating}
465
+    \subsection{Setting up auto-updating}\label{conf:freshclam}
466 466
     \verb+freshclam+ is the automatic database update tool for Clam AntiVirus.
467 467
     It can work in two modes:
468 468
     \begin{itemize}
... ...
@@ -704,6 +750,108 @@ N * * * *	/usr/local/bin/freshclam --quiet
704 704
     more better and safe idea is to use the \textbf{samba-vscan} module.
705 705
     NFS is not supported because Dazuko doesn't intercept NFS access calls.
706 706
 
707
+    \subsection{Clamdtop}
708
+    \verb+clamdtop+ is a tool to monitor one or multiple instances of clamd.  It
709
+    has a (color) ncurses interface, that shows the jobs in clamd's queue,
710
+    memory usage, and information about the loaded signature database.
711
+    You can specify on the command-line to which clamd(s) it should connect
712
+    to. By default it will attempt to connect to the local clamd as defined
713
+    in clamd.conf.
714
+    \\\\
715
+    For more detailed help, type 'man clamdtop' or 'clamdtop --help'.
716
+
717
+    \subsection{Clamscan}
718
+    \verb+clamscan+ is ClamAV's command line virus scanner.  It can be used to
719
+    scan files and/or directories for viruses.  In order for clamscan
720
+    to work proper, the ClamAV virus database files must be installed on
721
+    the system you are using clamscan on.
722
+    \\\\
723
+    The general usage of clamscan is: clamscan [options] [file/directory/-]
724
+    \\\\
725
+    For more detailed help, type 'man clamscan' or 'clamscan --help'.
726
+
727
+    \subsection{ClamBC}
728
+    \verb+clambc+ is Clam Anti-Virus' bytecode testing tool.  It can be
729
+    used to test files which contain bytecode. For more detailed help,
730
+    type 'man clambc' or 'clambc --help'.
731
+
732
+    \subsection{Freshclam}\ref{sec:freshclam}
733
+    \verb+freshclam+ is ClamAV's virus database update tool and reads it's
734
+    configuration from the file 'freshclam.conf' (this may be
735
+    overriden by command line options). Here is a sample usage including cdiffs:
736
+    \begin{verbatim}
737
+        $ freshclam
738
+
739
+        ClamAV update process started at Mon Oct  7 08:15:10 2013
740
+        main.cld is up to date (version: 55, sigs: 2424225, f-level: 60, builder: neo)
741
+        Downloading daily-17945.cdiff [100%]
742
+        Downloading daily-17946.cdiff [100%]
743
+        Downloading daily-17947.cdiff [100%]
744
+        daily.cld updated (version: 17947, sigs: 406951, f-level: 63, builder: neo)
745
+        Downloading bytecode-227.cdiff [100%]
746
+        Downloading bytecode-228.cdiff [100%]
747
+        bytecode.cld updated (version: 228, sigs: 43, f-level: 63, builder: neo)
748
+        Database updated (2831219 signatures) from database.clamav.net (IP: 64.6.100.177)
749
+    \end{verbatim}
750
+    For more detailed help, type 'man clamscan' or 'clamscan --help'.
751
+
752
+    \subsection{Clamconf}\label{sec:clamconf}
753
+    \verb+clamconf+ is the Clam Anti-Virus configuration utility.  It is used
754
+    for displaying values of configurations options in ClamAV, which
755
+    will show the contents of clamd.conf (or tell you if it is not
756
+    properly configured), the contents of freshclam.conf, and display
757
+    information about software settings, database, platform, and build
758
+    information. Here is a sample clamconf output:
759
+    \begin{verbatim}
760
+        $ clamconf
761
+
762
+        Checking configuration files in /etc/clamav
763
+
764
+        Config file: clamd.conf
765
+        -----------------------
766
+        ERROR: Please edit the example config file /etc/clamav/clamd.conf
767
+
768
+        Config file: freshclam.conf
769
+        ---------------------------
770
+        ERROR: Please edit the example config file /etc/clamav/freshclam.conf
771
+
772
+        clamav-milter.conf not found
773
+
774
+        Software settings
775
+        -----------------
776
+        Version: 0.97.6
777
+        Optional features supported: MEMPOOL IPv6 CLAMUKO AUTOIT_EA06 BZIP2 RAR JIT
778
+
779
+        Database information
780
+        --------------------
781
+        Database directory: /usr/local/share/clamav
782
+        WARNING: freshclam.conf and clamd.conf point to different database directories
783
+        print_dbs: Can't open directory /usr/local/share/clamav
784
+
785
+        Platform information
786
+        --------------------
787
+        uname: Linux 2.6.32-279.el6.x86_64 #1 SMP Fri Jun 22 12:19:21 UTC 2012 x86_64
788
+        OS: linux-gnu, ARCH: x86_64, CPU: x86_64
789
+        Full OS version: ``CentOS release 6.3 (Final)''
790
+        zlib version: 1.2.3 (1.2.3), compile flags: a9
791
+        Triple: x86_64-unknown-linux-gnu
792
+        CPU: amdfam10, Little-endian
793
+        platform id: 0x0a2143430804040607040406
794
+
795
+        Build information
796
+        -----------------
797
+        GNU C: 4.4.6 20120305 (Red Hat 4.4.6-4) (4.4.6)
798
+        GNU C++: 4.4.6 20120305 (Red Hat 4.4.6-4) (4.4.6)
799
+        CPPFLAGS: 
800
+        CFLAGS: -g -O2 -fno-strict-aliasing
801
+        CXXFLAGS: 
802
+        LDFLAGS: 
803
+        Configure: '--enable-check' '--sysconfdir=/etc/clamav'
804
+        --enable-ltdl-convenience
805
+        sizeof(void*) = 8
806
+    \end{verbatim}
807
+    For more detailed help, type 'man clamconf' or 'clamconf --help'.
808
+
707 809
     \subsection{Output format}
708 810
 
709 811
     \subsubsection{clamscan}
... ...
@@ -723,7 +871,7 @@ N * * * *	/usr/local/bin/freshclam --quiet
723 723
     \verb+FOUND+ strings. In case of archives the scanner depends on libclamav
724 724
     and only prints the first virus found within an archive:
725 725
     \begin{verbatim}
726
-	zolw@localhost:/tmp$ clamscan malware.zip 
726
+	$ clamscan malware.zip 
727 727
 	malware.zip: Worm.Mydoom.U FOUND
728 728
     \end{verbatim}
729 729
     When using the --allmatch(-z) flag, clamscan may print multiple virus
... ...
@@ -732,7 +880,7 @@ N * * * *	/usr/local/bin/freshclam --quiet
732 732
     \subsubsection{clamd}
733 733
     The output format of \verb+clamd+ is very similar to \verb+clamscan+.
734 734
     \begin{verbatim}
735
-	zolw@localhost:~$ telnet localhost 3310
735
+	$ telnet localhost 3310
736 736
 	Trying 127.0.0.1...
737 737
 	Connected to localhost.
738 738
 	Escape character is '^]'.
... ...
@@ -823,8 +971,14 @@ N * * * *	/usr/local/bin/freshclam --quiet
823 823
     decoding and normalization is only performed for HTML files.
824 824
 
825 825
     \subsubsection{Data Loss Prevention}
826
-    Libclamav includes a DLP module which can detect credit card and
827
-    social security numbers inside text files.
826
+    Libclamav includes a DLP module which can detect the following
827
+    credit card issuers: AMEX, VISA, MasterCard, Discover, Diner's Club,
828
+    and JCB and U.S. social security numbers inside text files.
829
+    \\\\
830
+    Future versions of Libclamav may include additional features to
831
+    detect other credit cards and other forms of PII (Personally
832
+    Identifiable Information) which may be transmitted without the
833
+    benefit of being encrypted.
828 834
 
829 835
     \subsubsection{Others}
830 836
     Libclamav can handle various obfuscators, encoders, files vulnerable to
... ...
@@ -1115,9 +1269,9 @@ const char *cl_engine_get_str(const struct cl_engine *engine,
1115 1115
     \subsubsection{clamav-config}
1116 1116
     Use \verb+clamav-config+ to check compilation information for libclamav.
1117 1117
     \begin{verbatim}
1118
-	zolw@localhost:~$ clamav-config --libs
1118
+	$ clamav-config --libs
1119 1119
 	-L/usr/local/lib -lz -lbz2 -lgmp -lpthread
1120
-	zolw@localhost:~$ clamav-config --cflags
1120
+	$ clamav-config --cflags
1121 1121
 	-I/usr/local/include -g -O2
1122 1122
     \end{verbatim}
1123 1123
 
... ...
@@ -1139,7 +1293,7 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
1139 1139
     \end{verbatim}
1140 1140
     \verb+sigtool --info+ displays detailed information on CVD files:
1141 1141
     \begin{verbatim}
1142
-zolw@localhost:/usr/local/share/clamav$ sigtool -i daily.cvd 
1142
+$ sigtool -i daily.cvd 
1143 1143
 File: daily.cvd
1144 1144
 Build time: 10 Mar 2008 10:45 +0000
1145 1145
 Version: 6191
... ...
@@ -64,6 +64,9 @@ Initialization</A>
64 64
 	struct cl_engine *cl_engine_new(void);
65 65
 	int cl_engine_free(struct cl_engine *engine);
66 66
 </PRE>
67
+    At this time, <code>cl_init()</code> only supports the <code>CL_INIT_DEFAULT</code> option
68
+    which intializes libclamav with the default settings.
69
+
67 70
     <code>cl_init()</code> and <code>cl_engine_free()</code> return <code>CL_SUCCESS</code>
68 71
     on success or another code on error. <code>cl_engine_new()</code> return
69 72
     a pointer or NULL if there's not enough memory to allocate a new
... ...
@@ -108,7 +108,7 @@ Load bytecode.
108 108
 	    unsigned int sigs = 0;
109 109
 	    int ret;
110 110
 
111
-	if((ret = cl_init()) != CL_SUCCESS) {
111
+	if((ret = cl_init(CL_INIT_DEFAULT)) != CL_SUCCESS) {
112 112
 	    printf("cl_init() error: %s\n", cl_strerror(ret));
113 113
 	    return 1;
114 114
 	}
... ...
@@ -222,8 +222,8 @@ Example
222 222
 #DetectPUA yes
223 223
 
224 224
 # Exclude a specific PUA category. This directive can be used multiple times.
225
-# See http://www.clamav.net/support/pua for the complete list of PUA
226
-# categories.
225
+# See https://github.com/vrtadmin/clamav-faq/blob/master/faq/faq-pua.md for 
226
+# the complete list of PUA categories.
227 227
 # Default: Load all categories (if DetectPUA is activated)
228 228
 #ExcludePUA NetTool
229 229
 #ExcludePUA PWTool
... ...
@@ -386,6 +386,8 @@ libclamav_la_SOURCES = \
386 386
 	builtin_bytecodes.h\
387 387
 	events.c\
388 388
 	events.h \
389
+	adc.c \
390
+	adc.h \
389 391
 	dmg.c \
390 392
 	dmg.h \
391 393
 	xar.c \
... ...
@@ -172,10 +172,10 @@ am_libclamav_la_OBJECTS = libclamav_la-matcher-ac.lo \
172 172
 	libclamav_la-macho.lo libclamav_la-ishield.lo \
173 173
 	libclamav_la-bytecode_api.lo libclamav_la-bytecode_api_decl.lo \
174 174
 	libclamav_la-cache.lo libclamav_la-bytecode_detect.lo \
175
-	libclamav_la-events.lo libclamav_la-dmg.lo libclamav_la-xar.lo \
176
-	libclamav_la-xz_iface.lo libclamav_la-sf_base64decode.lo \
177
-	libclamav_la-hfsplus.lo libclamav_la-swf.lo \
178
-	libclamav_la-jpeg.lo libclamav_la-png.lo \
175
+	libclamav_la-events.lo libclamav_la-adc.lo libclamav_la-dmg.lo \
176
+	libclamav_la-xar.lo libclamav_la-xz_iface.lo \
177
+	libclamav_la-sf_base64decode.lo libclamav_la-hfsplus.lo \
178
+	libclamav_la-swf.lo libclamav_la-jpeg.lo libclamav_la-png.lo \
179 179
 	libclamav_la-iso9660.lo libclamav_la-arc4.lo \
180 180
 	libclamav_la-rijndael.lo libclamav_la-crtmgr.lo \
181 181
 	libclamav_la-asn1.lo libclamav_la-fp_add.lo \
... ...
@@ -697,11 +697,11 @@ libclamav_la_SOURCES = clamav.h matcher-ac.c matcher-ac.h matcher-bm.c \
697 697
 	bcfeatures.h bytecode_api.c bytecode_api_decl.c bytecode_api.h \
698 698
 	bytecode_api_impl.h bytecode_hooks.h cache.c cache.h \
699 699
 	bytecode_detect.c bytecode_detect.h builtin_bytecodes.h \
700
-	events.c events.h dmg.c dmg.h xar.c xar.h xz_iface.c \
701
-	xz_iface.h sf_base64decode.c sf_base64decode.h hfsplus.c \
702
-	hfsplus.h swf.c swf.h jpeg.c jpeg.h png.c png.h iso9660.c \
703
-	iso9660.h arc4.c arc4.h rijndael.c rijndael.h crtmgr.c \
704
-	crtmgr.h asn1.c asn1.h bignum.h bignum_fast.h \
700
+	events.c events.h adc.c adc.h dmg.c dmg.h xar.c xar.h \
701
+	xz_iface.c xz_iface.h sf_base64decode.c sf_base64decode.h \
702
+	hfsplus.c hfsplus.h swf.c swf.h jpeg.c jpeg.h png.c png.h \
703
+	iso9660.c iso9660.h arc4.c arc4.h rijndael.c rijndael.h \
704
+	crtmgr.c crtmgr.h asn1.c asn1.h bignum.h bignum_fast.h \
705 705
 	tomsfastmath/addsub/fp_add.c tomsfastmath/addsub/fp_add_d.c \
706 706
 	tomsfastmath/addsub/fp_addmod.c tomsfastmath/addsub/fp_cmp.c \
707 707
 	tomsfastmath/addsub/fp_cmp_d.c \
... ...
@@ -911,6 +911,7 @@ distclean-compile:
911 911
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-XzCrc64.Plo@am__quote@
912 912
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-XzDec.Plo@am__quote@
913 913
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-XzIn.Plo@am__quote@
914
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-adc.Plo@am__quote@
914 915
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-arc4.Plo@am__quote@
915 916
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-asn1.Plo@am__quote@
916 917
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-aspack.Plo@am__quote@
... ...
@@ -1907,6 +1908,13 @@ libclamav_la-events.lo: events.c
1907 1907
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1908 1908
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-events.lo `test -f 'events.c' || echo '$(srcdir)/'`events.c
1909 1909
 
1910
+libclamav_la-adc.lo: adc.c
1911
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-adc.lo -MD -MP -MF $(DEPDIR)/libclamav_la-adc.Tpo -c -o libclamav_la-adc.lo `test -f 'adc.c' || echo '$(srcdir)/'`adc.c
1912
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-adc.Tpo $(DEPDIR)/libclamav_la-adc.Plo
1913
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='adc.c' object='libclamav_la-adc.lo' libtool=yes @AMDEPBACKSLASH@
1914
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1915
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-adc.lo `test -f 'adc.c' || echo '$(srcdir)/'`adc.c
1916
+
1910 1917
 libclamav_la-dmg.lo: dmg.c
1911 1918
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-dmg.lo -MD -MP -MF $(DEPDIR)/libclamav_la-dmg.Tpo -c -o libclamav_la-dmg.lo `test -f 'dmg.c' || echo '$(srcdir)/'`dmg.c
1912 1919
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-dmg.Tpo $(DEPDIR)/libclamav_la-dmg.Plo
1913 1920
new file mode 100644
... ...
@@ -0,0 +1,291 @@
0
+/*
1
+ *  Copyright (C) 2013 Sourcefire, Inc.
2
+ *
3
+ *  Authors: David Raynor <draynor@sourcefire.com>
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#if HAVE_CONFIG_H
21
+#include "clamav-config.h"
22
+#endif
23
+
24
+#include <stdio.h>
25
+#include <errno.h>
26
+#if HAVE_STRING_H
27
+#include <string.h>
28
+#endif
29
+
30
+#include "cltypes.h"
31
+#include "others.h"
32
+#include "adc.h"
33
+
34
+/* #define DEBUG_ADC */
35
+
36
+#ifdef DEBUG_ADC
37
+#  define adc_dbgmsg(...) cli_dbgmsg( __VA_ARGS__ )
38
+#else
39
+#  define adc_dbgmsg(...) ;
40
+#endif
41
+
42
+/* Initialize values and collect buffer
43
+ * NOTE: buffer size must be larger than largest lookback offset */
44
+int adc_decompressInit(adc_stream *strm)
45
+{
46
+    if (strm == NULL) {
47
+        return ADC_IO_ERROR;
48
+    }
49
+    if (strm->state != ADC_STATE_UNINIT) {
50
+        return ADC_DATA_ERROR;
51
+    }
52
+
53
+    /* Have to buffer maximum backward lookup */
54
+    strm->buffer = (uint8_t *)calloc(ADC_BUFF_SIZE, 1);
55
+    if (strm->buffer == NULL) {
56
+        return ADC_MEM_ERROR;
57
+    }
58
+    strm->buffered = 0;
59
+    strm->state = ADC_STATE_GETTYPE;
60
+    strm->length = 0;
61
+    strm->offset = 0;
62
+    strm->curr = strm->buffer;
63
+
64
+    return ADC_OK;
65
+}
66
+
67
+/* Decompress routine
68
+ * NOTE: Reaching end of input buffer does not mean end of output.
69
+ * It may fill the output buffer but have more to output.
70
+ * It will only return ADC_STREAM_END if output buffer is not full.
71
+ * It will return ADC_DATA_ERROR if it ends in the middle of a phrase
72
+ * (i.e. in the middle of a lookback code or data run)
73
+ */
74
+int adc_decompress(adc_stream *strm)
75
+{
76
+    uint8_t bData;
77
+    uint8_t didNothing = 1;
78
+
79
+    /* first, the error returns based on strm */
80
+    if ((strm == NULL) || (strm->next_in == NULL) || (strm->next_out == NULL)) {
81
+        return ADC_IO_ERROR;
82
+    }
83
+    if (strm->state == ADC_STATE_UNINIT) {
84
+        return ADC_DATA_ERROR;
85
+    }
86
+
87
+    cli_dbgmsg("adc_decompress: avail_in %lu avail_out %lu state %u\n", strm->avail_in, strm->avail_out, strm->state);
88
+
89
+    while (strm->avail_out) {
90
+        /* Exit if needs more in bytes and none available */
91
+        int needsInput;
92
+        switch (strm->state) {
93
+           case ADC_STATE_SHORTLOOK:
94
+           case ADC_STATE_LONGLOOK:
95
+               needsInput = 0;
96
+               break;
97
+           default:
98
+               needsInput = 1;
99
+               break;
100
+        }
101
+        if (needsInput && (strm->avail_in == 0)) {
102
+            break;
103
+        }
104
+        else {
105
+            didNothing = 0;
106
+        }
107
+
108
+        /* Find or execute statecode */
109
+        switch (strm->state) {
110
+            case ADC_STATE_GETTYPE: {
111
+                /* Grab action code */
112
+                bData = *(strm->next_in);
113
+                strm->next_in++;
114
+                strm->avail_in--;
115
+                if (bData & 0x80) {
116
+                    strm->state = ADC_STATE_RAWDATA;
117
+                    strm->offset = 0;
118
+                    strm->length = (bData & 0x7F) + 1;
119
+                }
120
+                else if (bData & 0x40) {
121
+                    strm->state = ADC_STATE_LONGOP2;
122
+                    strm->offset = 0;
123
+                    strm->length = (bData & 0x3F) + 4;
124
+                }
125
+                else {
126
+                    strm->state = ADC_STATE_SHORTOP;
127
+                    strm->offset = (bData & 0x3) * 0x100;
128
+                    strm->length = ((bData & 0x3C) >> 2) + 3;
129
+                }
130
+                adc_dbgmsg("adc_decompress: GETTYPE bData %x state %u offset %u length %u\n",
131
+                           bData, strm->state, strm->offset, strm->length);
132
+                break;
133
+           }
134
+           case ADC_STATE_LONGOP2: {
135
+                /* Grab first offset byte */
136
+                bData = *(strm->next_in);
137
+                strm->next_in++;
138
+                strm->avail_in--;
139
+                strm->offset = bData * 0x100;
140
+                strm->state = ADC_STATE_LONGOP1;
141
+                adc_dbgmsg("adc_decompress: LONGOP2 bData %x state %u offset %u length %u\n",
142
+                           bData, strm->state, strm->offset, strm->length);
143
+                break;
144
+           }
145
+           case ADC_STATE_LONGOP1: {
146
+                /* Grab second offset byte */
147
+                bData = *(strm->next_in);
148
+                strm->next_in++;
149
+                strm->avail_in--;
150
+                strm->offset += bData + 1;
151
+                strm->state = ADC_STATE_LONGLOOK;
152
+                adc_dbgmsg("adc_decompress: LONGOP1 bData %x state %u offset %u length %u\n",
153
+                           bData, strm->state, strm->offset, strm->length);
154
+                break;
155
+           }
156
+           case ADC_STATE_SHORTOP: {
157
+                /* Grab offset byte */
158
+                bData = *(strm->next_in);
159
+                strm->next_in++;
160
+                strm->avail_in--;
161
+                strm->offset += bData + 1;
162
+                strm->state = ADC_STATE_SHORTLOOK;
163
+                adc_dbgmsg("adc_decompress: SHORTOP bData %x state %u offset %u length %u\n",
164
+                           bData, strm->state, strm->offset, strm->length);
165
+                break;
166
+           }
167
+
168
+           case ADC_STATE_RAWDATA: {
169
+                /* Grab data */
170
+                adc_dbgmsg("adc_decompress: RAWDATA offset %u length %u\n", strm->offset, strm->length);
171
+                while ((strm->avail_in > 0) && (strm->avail_out > 0) && (strm->length > 0)) {
172
+                    bData = *(strm->next_in);
173
+                    strm->next_in++;
174
+                    strm->avail_in--;
175
+                    /* store to output */
176
+                    *(strm->next_out) = bData;
177
+                    strm->next_out++;
178
+                    strm->avail_out--;
179
+                    /* store to buffer */
180
+                    if (strm->curr >= (strm->buffer + ADC_BUFF_SIZE)) {
181
+                        strm->curr = strm->buffer;
182
+                    }
183
+                    *(strm->curr) = bData;
184
+                    strm->curr++;
185
+                    if (strm->buffered < ADC_BUFF_SIZE) {
186
+                        strm->buffered++;
187
+                    }
188
+                    strm->length--;
189
+                }
190
+                if (strm->length == 0) {
191
+                    /* adc_dbgmsg("adc_decompress: RAWDATADONE buffered %u avail_in %u avail_out %u \n",
192
+                        strm->buffered, strm->avail_in, strm->avail_out); */
193
+                    strm->state = ADC_STATE_GETTYPE;
194
+                }
195
+                break;
196
+           }
197
+
198
+           case ADC_STATE_SHORTLOOK:
199
+           case ADC_STATE_LONGLOOK: {
200
+                /* Copy data */
201
+                adc_dbgmsg("adc_decompress: LOOKBACK offset %u length %u avail_in %u avail_out %u\n",
202
+                    strm->offset, strm->length, strm->avail_in, strm->avail_out);
203
+                while ((strm->avail_out > 0) && (strm->length > 0)) {
204
+                    /* state validation first */
205
+                    if (strm->offset > 0x10000) {
206
+                        cli_dbgmsg("adc_decompress: bad LOOKBACK offset %u\n", strm->offset);
207
+                        return ADC_DATA_ERROR;
208
+                    }
209
+                    else if ((strm->state == ADC_STATE_SHORTLOOK) && (strm->offset > 0x400)) {
210
+                        cli_dbgmsg("adc_decompress: bad LOOKBACK offset %u\n", strm->offset);
211
+                        return ADC_DATA_ERROR;
212
+                    }
213
+                    if (strm->offset > strm->buffered) {
214
+                        cli_dbgmsg("adc_decompress: too large LOOKBACK offset %u\n", strm->offset);
215
+                        return ADC_DATA_ERROR;
216
+                    }
217
+                    /* retrieve byte */
218
+                    if (strm->curr >= (strm->buffer + ADC_BUFF_SIZE)) {
219
+                        strm->curr = strm->buffer;
220
+                    }
221
+                    if (strm->curr > (strm->buffer + strm->offset)) {
222
+                        bData = *(uint8_t *)(strm->curr - strm->offset);
223
+                    }
224
+                    else {
225
+                        bData = *(uint8_t *)(strm->curr + ADC_BUFF_SIZE - strm->offset);
226
+                    }
227
+                    /* store to output */
228
+                    *(strm->next_out) = bData;
229
+                    strm->next_out++;
230
+                    strm->avail_out--;
231
+                    /* store to buffer */
232
+                    *(strm->curr) = bData;
233
+                    strm->curr++;
234
+                    if (strm->buffered < ADC_BUFF_SIZE) {
235
+                        strm->buffered++;
236
+                    }
237
+                    strm->length--;
238
+                }
239
+                if (strm->length == 0) {
240
+                    strm->state = ADC_STATE_GETTYPE;
241
+                    /* adc_dbgmsg("adc_decompress: LOOKBACKDONE buffered %u avail_in %u avail_out %u \n",
242
+                        strm->buffered, strm->avail_in, strm->avail_out); */
243
+                }
244
+                break;
245
+            }
246
+
247
+            default: {
248
+                /* bad state */
249
+                cli_errmsg("adc_decompress: invalid state %u\n", strm->state);
250
+                return ADC_DATA_ERROR;
251
+            }
252
+        } /* end switch */
253
+    } /* end while */
254
+
255
+    /* There really isn't a terminator, just end of data */
256
+    if (didNothing && strm->avail_out) {
257
+        if (strm->state == ADC_STATE_GETTYPE) {
258
+            /* Nothing left to do */
259
+            return ADC_STREAM_END;
260
+        }
261
+        else {
262
+            /* Ended mid phrase */
263
+            cli_dbgmsg("adc_decompress: stream ended mid-phrase, state %u\n", strm->state);
264
+            return ADC_DATA_ERROR;
265
+        }
266
+    }
267
+    return ADC_OK;
268
+}
269
+
270
+/* Cleanup routine, frees buffer */
271
+int adc_decompressEnd(adc_stream *strm)
272
+{
273
+    if (strm == NULL) {
274
+        return ADC_IO_ERROR;
275
+    }
276
+    if (strm->state == ADC_STATE_UNINIT) {
277
+        return ADC_DATA_ERROR;
278
+    }
279
+
280
+    if (strm->buffer != NULL) {
281
+        free(strm->buffer);
282
+    }
283
+    strm->buffered = 0;
284
+    strm->state = ADC_STATE_UNINIT;
285
+    strm->length = 0;
286
+    strm->offset = 0;
287
+
288
+    return ADC_OK;
289
+}
290
+
0 291
new file mode 100644
... ...
@@ -0,0 +1,55 @@
0
+
1
+
2
+#ifndef CLAM_ADC_H
3
+#define CLAM_ADC_H
4
+
5
+struct adc_stream {
6
+    uint8_t *next_in;
7
+    size_t avail_in;
8
+    size_t total_in;
9
+
10
+    uint8_t *next_out;
11
+    size_t avail_out;
12
+    size_t total_out;
13
+
14
+    /* internals */
15
+    uint8_t *buffer;
16
+    uint8_t *curr;
17
+
18
+    uint32_t buffered;
19
+    uint16_t state;
20
+    uint16_t length;
21
+    uint32_t offset;
22
+};
23
+typedef struct adc_stream adc_stream;
24
+
25
+#define ADC_BUFF_SIZE 65536
26
+
27
+#define    ADC_MEM_ERROR -1
28
+#define    ADC_DATA_ERROR -2
29
+#define    ADC_IO_ERROR -3
30
+#define    ADC_OK 0
31
+#define    ADC_STREAM_END 1
32
+
33
+enum adc_state {
34
+    ADC_STATE_UNINIT = 0,
35
+    ADC_STATE_GETTYPE = 1,
36
+    ADC_STATE_RAWDATA = 2,
37
+    ADC_STATE_SHORTOP = 3,
38
+    ADC_STATE_LONGOP2 = 4,
39
+    ADC_STATE_LONGOP1 = 5,
40
+    ADC_STATE_SHORTLOOK = 6,
41
+    ADC_STATE_LONGLOOK = 7
42
+};
43
+
44
+/* Compression phrases
45
+ * store phrase - 1 byte header + data, first byte 0x80-0xFF, max length 0x80 (7 bits + 1), no offset
46
+ * short phrase - 2 byte header + data, first byte 0x00-0x3F, max length 0x12 (4 bits + 3), max offset 0x3FF (10 bits)
47
+ * long phrase  - 3 byte header + data, first byte 0x40-0x7F, max length 0x43 (6 bits + 4), max offset 0xFFFF (16 bits)
48
+ */
49
+
50
+int adc_decompressInit(adc_stream *strm);
51
+int adc_decompress(adc_stream *strm);
52
+int adc_decompressEnd(adc_stream *strm);
53
+
54
+#endif
... ...
@@ -54,9 +54,10 @@
54 54
 #include "dmg.h"
55 55
 #include "scanners.h"
56 56
 #include "sf_base64decode.h"
57
+#include "adc.h"
57 58
 
58
-// #define DEBUG_DMG_PARSE
59
-// #define DEBUG_DMG_BZIP
59
+/* #define DEBUG_DMG_PARSE */
60
+/* #define DEBUG_DMG_BZIP */
60 61
 
61 62
 #ifdef DEBUG_DMG_PARSE
62 63
 #  define dmg_parsemsg(...) cli_dbgmsg( __VA_ARGS__)
... ...
@@ -710,10 +711,84 @@ static int dmg_stripe_store(cli_ctx *ctx, int fd, uint32_t index, struct dmg_mis
710 710
 /* Stripe handling: ADC block (type 0x80000004) */
711 711
 static int dmg_stripe_adc(cli_ctx *ctx, int fd, uint32_t index, struct dmg_mish_with_stripes *mish_set)
712 712
 {
713
-    /* Temporary stub */
714
-    cli_dbgmsg("dmg_stripe_adc: stripe " STDu32 "\n", index);
715
-    /* Return as format error to prevent scan for now */
716
-    return CL_EFORMAT;
713
+    int ret = CL_CLEAN, adcret;
714
+    adc_stream strm;
715
+    size_t off = mish_set->stripes[index].dataOffset;
716
+    size_t len = mish_set->stripes[index].dataLength;
717
+    uint64_t size_so_far = 0;
718
+    uint64_t expected_len = mish_set->stripes[index].sectorCount * DMG_SECTOR_SIZE;
719
+    uint8_t obuf[BUFSIZ];
720
+
721
+    cli_dbgmsg("dmg_stripe_adc: stripe " STDu32 " initial len " STDu64 " expected len " STDu64 "\n",
722
+            index, len, expected_len);
723
+    if (len == 0)
724
+        return CL_CLEAN;
725
+
726
+    memset(&strm, 0, sizeof(strm));
727
+    strm.next_in = (void*)fmap_need_off_once(*ctx->fmap, off, len);
728
+    if (!strm.next_in) {
729
+        cli_warnmsg("dmg_stripe_adc: fmap need failed on stripe " STDu32 "\n", index);
730
+        return CL_EMAP;
731
+    }
732
+    strm.avail_in = len;
733
+    strm.next_out = obuf;
734
+    strm.avail_out = sizeof(obuf);
735
+
736
+    adcret = adc_decompressInit(&strm);
737
+    if(adcret != ADC_OK) {
738
+        cli_warnmsg("dmg_stripe_adc: adc_decompressInit failed\n");
739
+        return CL_EMEM;
740
+    }
741
+
742
+    while(adcret == ADC_OK) {
743
+        int written;
744
+        if (size_so_far > expected_len) {
745
+            cli_warnmsg("dmg_stripe_adc: expected size exceeded!\n");
746
+            adc_decompressEnd(&strm);
747
+            return CL_EFORMAT;
748
+        }
749
+        adcret = adc_decompress(&strm);
750
+        switch(adcret) {
751
+            case ADC_OK:
752
+                if(strm.avail_out == 0) {
753
+                    if ((written=cli_writen(fd, obuf, sizeof(obuf)))!=sizeof(obuf)) {
754
+                        cli_errmsg("dmg_stripe_adc: failed write to output file\n");
755
+                        adc_decompressEnd(&strm);
756
+                        return CL_EWRITE;
757
+                    }
758
+                    size_so_far += written;
759
+                    strm.next_out = obuf;
760
+                    strm.avail_out = sizeof(obuf);
761
+                }
762
+                continue;
763
+            case ADC_STREAM_END:
764
+            default:
765
+                written = sizeof(obuf) - strm.avail_out;
766
+                if (written) {
767
+                    if ((cli_writen(fd, obuf, written))!=written) {
768
+                        cli_errmsg("dmg_stripe_adc: failed write to output file\n");
769
+                        adc_decompressEnd(&strm);
770
+                        return CL_EWRITE;
771
+                    }
772
+                    size_so_far += written;
773
+                    strm.next_out = obuf;
774
+                    strm.avail_out = sizeof(obuf);
775
+                }
776
+                if (adcret == Z_STREAM_END)
777
+                    break;
778
+                cli_dbgmsg("dmg_stripe_adc: after writing " STDu64 " bytes, "
779
+                           "got error %d decompressing stripe " STDu32 "\n",
780
+                           size_so_far, adcret, index);
781
+                adc_decompressEnd(&strm);
782
+                return CL_EFORMAT;
783
+        }
784
+        break;
785
+    }
786
+
787
+    adc_decompressEnd(&strm);
788
+    cli_dbgmsg("dmg_stripe_adc: stripe " STDu32 " actual len " STDu64 " expected len " STDu64 "\n",
789
+            index, size_so_far, expected_len);
790
+    return CL_CLEAN;
717 791
 }
718 792
 
719 793
 /* Stripe handling: deflate block (type 0x80000005) */
... ...
@@ -651,6 +651,8 @@ static int hfsplus_walk_catalog(cli_ctx *ctx, hfsPlusVolumeHeader *volHeader, hf
651 651
             }
652 652
             memcpy(&fileRec, &(nodeBuf[recordStart+keylen+2]), sizeof(hfsPlusCatalogFile));
653 653
 
654
+            /* Only scan files */
655
+            fileRec.permissions.fileMode = be16_to_host(fileRec.permissions.fileMode);
654 656
             if ((fileRec.permissions.fileMode & HFS_MODE_TYPEMASK) == HFS_MODE_FILE) {
655 657
                 /* Convert forks and scan */
656 658
                 forkdata_to_host(&(fileRec.dataFork));
... ...
@@ -658,36 +660,41 @@ static int hfsplus_walk_catalog(cli_ctx *ctx, hfsPlusVolumeHeader *volHeader, hf
658 658
                 if (fileRec.dataFork.logicalSize) {
659 659
                     ret = hfsplus_scanfile(ctx, volHeader, extHeader, &(fileRec.dataFork), dirname);
660 660
                 }
661
+                /* Check return code */
662
+                if (ret == CL_VIRUS) {
663
+                    has_alerts = 1;
664
+                    if (SCAN_ALL) {
665
+                        /* Continue scanning in SCAN_ALL mode */
666
+                        cli_dbgmsg("hfsplus_walk_catalog: data fork alert, continuing");
667
+                        ret = CL_CLEAN;
668
+                    }
669
+                }
661 670
                 if (ret != CL_CLEAN) {
662 671
                     cli_dbgmsg("hfsplus_walk_catalog: data fork retcode %d", ret);
663
-                    if (ret == CL_VIRUS) {
664
-                        has_alerts = 1;
665
-                        if (SCAN_ALL) {
666
-                            /* Continue scanning in SCAN_ALL mode */
667
-                            ret = CL_CLEAN;
668
-                        }
669
-                    }
670 672
                     break;
671 673
                 }
674
+                /* Scan resource fork */
672 675
                 forkdata_to_host(&(fileRec.resourceFork));
673 676
                 forkdata_print("resource fork:", &(fileRec.resourceFork));
674 677
                 if (fileRec.resourceFork.logicalSize) {
675 678
                     ret = hfsplus_scanfile(ctx, volHeader, extHeader, &(fileRec.resourceFork), dirname);
676 679
                 }
680
+                /* Check return code */
681
+                if (ret == CL_VIRUS) {
682
+                    has_alerts = 1;
683
+                    if (SCAN_ALL) {
684
+                        /* Continue scanning in SCAN_ALL mode */
685
+                        cli_dbgmsg("hfsplus_walk_catalog: resource fork alert, continuing");
686
+                        ret = CL_CLEAN;
687
+                    }
688
+                }
677 689
                 if (ret != CL_CLEAN) {
678 690
                     cli_dbgmsg("hfsplus_walk_catalog: resource fork retcode %d", ret);
679
-                    if (ret == CL_VIRUS) {
680
-                        has_alerts = 1;
681
-                        if (SCAN_ALL) {
682
-                            /* Continue scanning in SCAN_ALL mode */
683
-                            ret = CL_CLEAN;
684
-                        }
685
-                    }
686 691
                     break;
687 692
                 }
688 693
             }
689 694
             else {
690
-                cli_dbgmsg("hfsplus_walk_catalog: record mode is not File\n");
695
+                cli_dbgmsg("hfsplus_walk_catalog: record mode %o is not File\n", fileRec.permissions.fileMode);
691 696
             }
692 697
         }
693 698
         /* if return code, exit loop, message already logged */
... ...
@@ -452,12 +452,6 @@ struct MP *mpool_create() {
452 452
   sz = align_to_pagesize(&mp, MIN_FRAGSIZE);
453 453
   mp.u.mpm.usize = sizeof(struct MPMAP);
454 454
   mp.u.mpm.size = sz - sizeof(mp);
455
-#ifndef _WIN32
456
-  if ((mpool_p = (struct MP *)mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE|ANONYMOUS_MAP, -1, 0)) == MAP_FAILED)
457
-#else
458
-  if(!(mpool_p = (struct MP *)VirtualAlloc(NULL, sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)))
459
-#endif
460
-    return NULL;
461 455
   if (FRAGSBITS > 255) {
462 456
       cli_errmsg("At most 255 frags possible!\n");
463 457
       return NULL;
... ...
@@ -466,6 +460,12 @@ struct MP *mpool_create() {
466 466
       cli_errmsg("fragsz[0] too small!\n");
467 467
       return NULL;
468 468
   }
469
+#ifndef _WIN32
470
+  if ((mpool_p = (struct MP *)mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE|ANONYMOUS_MAP, -1, 0)) == MAP_FAILED)
471
+#else
472
+  if(!(mpool_p = (struct MP *)VirtualAlloc(NULL, sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)))
473
+#endif
474
+    return NULL;
469 475
 #ifdef CL_DEBUG
470 476
   memset(mpool_p, ALLOCPOISON, sz);
471 477
 #endif
... ...
@@ -2909,7 +2909,36 @@ int cl_load(const char *path, struct cl_engine *engine, unsigned int *signo, uns
2909 2909
     }
2910 2910
 
2911 2911
     if(CLAMSTAT(path, &sb) == -1) {
2912
-        cli_errmsg("cl_load(): Can't get status of %s\n", path);
2912
+        switch (errno) {
2913
+#if defined(EACCES)
2914
+            case EACCES:
2915
+                cli_errmsg("cl_load(): Access denied for path: %s\n", path);
2916
+                break;
2917
+#endif
2918
+#if defined(ENOENT)
2919
+            case ENOENT:
2920
+                cli_errmsg("cl_load(): No such file or directory: %s\n", path);
2921
+                break;
2922
+#endif
2923
+#if defined(ELOOP)
2924
+            case ELOOP:
2925
+                cli_errmsg("cl_load(): Too many symbolic links encountered in path: %s\n", path);
2926
+                break;
2927
+#endif
2928
+#if defined(EOVERFLOW)
2929
+            case EOVERFLOW:
2930
+                cli_errmsg("cl_load(): File size is too large to be recognized. Path: %s\n", path);
2931
+                break;
2932
+#endif
2933
+#if defined(EIO)
2934
+            case EIO:
2935
+                cli_errmsg("cl_load(): An I/O error occurred while reading from path: %s\n", path);
2936
+                break;
2937
+#endif
2938
+            default:
2939
+                cli_errmsg("cl_load: Can't get status of: %s\n", path);
2940
+                break;
2941
+        }
2913 2942
         return CL_ESTAT;
2914 2943
     }
2915 2944
 
... ...
@@ -282,6 +282,7 @@
282 282
     <ClCompile Include="..\libclamav\7z\Bra.c" />
283 283
     <ClCompile Include="..\libclamav\7z\Bra86.c" />
284 284
     <ClCompile Include="..\libclamav\7z\LzmaDec.c" />
285
+    <ClCompile Include="..\libclamav\adc.c" />
285 286
     <ClCompile Include="..\libclamav\aspack.c" />
286 287
     <ClCompile Include="..\libclamav\autoit.c" />
287 288
     <ClCompile Include="..\libclamav\binhex.c" />
... ...
@@ -470,4 +471,4 @@
470 470
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
471 471
   <ImportGroup Label="ExtensionTargets">
472 472
   </ImportGroup>
473
-</Project>
474 473
\ No newline at end of file
474
+</Project>
... ...
@@ -51,6 +51,9 @@
51 51
     <ClCompile Include="..\libclamav\bytecode_api_decl.c">
52 52
       <Filter>Source Files</Filter>
53 53
     </ClCompile>
54
+    <ClCompile Include="..\libclamav\adc.c">
55
+      <Filter>Source Files</Filter>
56
+    </ClCompile>
54 57
     <ClCompile Include="..\libclamav\aspack.c">
55 58
       <Filter>Source Files</Filter>
56 59
     </ClCompile>
... ...
@@ -841,4 +844,4 @@
841 841
       <Filter>Source Files\libxml2</Filter>
842 842
     </ClCompile>
843 843
   </ItemGroup>
844
-</Project>
845 844
\ No newline at end of file
845
+</Project>