remotes/push_mirror/0.98.1
Steve Morgan 12 years ago
commit bced84530b
  1. 4
      ChangeLog
  2. 180
      docs/clamdoc.tex
  3. 3
      docs/html/node45.html
  4. 2
      docs/html/node46.html
  5. 4
      etc/clamd.conf.sample
  6. 2
      libclamav/Makefile.am
  7. 26
      libclamav/Makefile.in
  8. 291
      libclamav/adc.c
  9. 55
      libclamav/adc.h
  10. 85
      libclamav/dmg.c
  11. 17
      libclamav/hfsplus.c
  12. 12
      libclamav/mpool.c
  13. 31
      libclamav/readdb.c
  14. 1
      win32/libclamav.vcxproj
  15. 3
      win32/libclamav.vcxproj.filters

@ -1,3 +1,7 @@
Thu Oct 3 10:49:11 2013 EDT 2013 (dar)
------------------------------------
* bb #1570: Support ADC compression in DMG
Wed Oct 2 11:22:40 2013 EDT 2013 (dar)
------------------------------------
* bb #9053: ClamAV 0.98 can't be compiled on FreeBSD 7

@ -316,6 +316,7 @@
\begin{verbatim}
$ ./configure --enable-milter
\end{verbatim}
See section /ref{sec:clamavmilter} for more details on clamav-milter.
\subsection{Running unit tests}\label{unit-testing}
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
\end{verbatim}
\end{itemize}
\subsection{Obtain Latest ClamAV anti-virus signature databases}
Before you can run ClamAV in daemon mode (clamd), 'clamdscan',
or 'clamscan' which is ClamAV's command line virus scanner,
you must have ClamAV Virus Database (.cvd) file(s) installed
in the appropriate location on your system. The default
location for these database files are /usr/local/share/clamav
(in Linux/Unix).
\\\\
Here is a listing of currently available ClamAV Virus Database Files:
\\\\
bytecode.cvd (signatures to detect bytecode in files)
main.cvd (main ClamAV virus database file)
daily.cvd (daily update file for ClamAV virus databases)
safebrowsing.cvd (virus signatures for safe browsing)
\\\\
These files can be downloaded via HTTP from the main ClamAV website
or via the 'freshclam' utility on a periodic basis. Using 'freshclam'
is the preferred method of keeping the ClamAV virus database files
up to date without manual intervention (see section \ref{conf:freshclam} for
information on how to configure 'freshclam' for automatic updating and section
\ref{sec:freshclam} for additional details on freshclam).
\section{Configuration}
\subsubsection{clamconf}
Before proceeding with the steps below, you should
run the 'clamconf' command, which gives important information
about your ClamAV configuration. See section \ref{sec:clamconf}
for more details.
\subsection{clamd}
Before you start using the daemon you have to edit the configuration file
(in other case \verb+clamd+ won't run):
@ -437,14 +466,31 @@ $ CK_FORK=no ./libtool --mode=execute valgrind unit_tests/check-clamav
Now configure Clamuko in \verb+clamd.conf+ and read the \ref{clamuko}
section.
\subsection{clamav-milter}
\subsection{clamav-milter}\label{sec:clamavmilter}
ClamAV $\ge0.95$ includes a new, redesigned clamav-milter. The most notable
difference is that the internal mode has been dropped and now a working
clamd companion is required. The second important difference is that now
the milter has got its own configuration and log files. To compile ClamAV
with the clamav-milter just run \verb+./configure+ \verb+--enable-milter+
and make as usual. Please consult your MTA's manual on how to connect it
with the milter.
the milter has got its own configuration and log files.
To compile ClamAV with the clamav-milter just run \verb+./configure+
\verb+--enable-milter+ and make as usual. In order to use the
'--enable-milter' option with 'configure', your system MUST have the milter
library installed. If you use the '--enable-milter' option without the
library being installed, you will most likely see output like this during
'configure':
\begin{verbatim}
checking for libiconv_open in -liconv... no
checking for iconv... yes
checking whether in_port_t is defined... yes
checking for in_addr_t definition... yes
checking for mi_stop in -lmilter... no
checking for library containing strlcpy... no
checking for mi_stop in -lmilter... no
configure: error: Cannot find libmilter
\end{verbatim}
At which point the 'configure' script will stop processing.
\\\\
Please consult your MTA's manual on how to connect ClamAV with the milter.
\subsection{Testing}
Try to scan recursively the source directory:
@ -462,7 +508,7 @@ $ CK_FORK=no ./libtool --mode=execute valgrind unit_tests/check-clamav
Please note that the scanned files must be accessible by the user running
\verb+clamd+ or you will get an error.
\subsection{Setting up auto-updating}
\subsection{Setting up auto-updating}\label{conf:freshclam}
\verb+freshclam+ is the automatic database update tool for Clam AntiVirus.
It can work in two modes:
\begin{itemize}
@ -704,6 +750,108 @@ N * * * * /usr/local/bin/freshclam --quiet
more better and safe idea is to use the \textbf{samba-vscan} module.
NFS is not supported because Dazuko doesn't intercept NFS access calls.
\subsection{Clamdtop}
\verb+clamdtop+ is a tool to monitor one or multiple instances of clamd. It
has a (color) ncurses interface, that shows the jobs in clamd's queue,
memory usage, and information about the loaded signature database.
You can specify on the command-line to which clamd(s) it should connect
to. By default it will attempt to connect to the local clamd as defined
in clamd.conf.
\\\\
For more detailed help, type 'man clamdtop' or 'clamdtop --help'.
\subsection{Clamscan}
\verb+clamscan+ is ClamAV's command line virus scanner. It can be used to
scan files and/or directories for viruses. In order for clamscan
to work proper, the ClamAV virus database files must be installed on
the system you are using clamscan on.
\\\\
The general usage of clamscan is: clamscan [options] [file/directory/-]
\\\\
For more detailed help, type 'man clamscan' or 'clamscan --help'.
\subsection{ClamBC}
\verb+clambc+ is Clam Anti-Virus' bytecode testing tool. It can be
used to test files which contain bytecode. For more detailed help,
type 'man clambc' or 'clambc --help'.
\subsection{Freshclam}\ref{sec:freshclam}
\verb+freshclam+ is ClamAV's virus database update tool and reads it's
configuration from the file 'freshclam.conf' (this may be
overriden by command line options). Here is a sample usage including cdiffs:
\begin{verbatim}
$ freshclam
ClamAV update process started at Mon Oct 7 08:15:10 2013
main.cld is up to date (version: 55, sigs: 2424225, f-level: 60, builder: neo)
Downloading daily-17945.cdiff [100%]
Downloading daily-17946.cdiff [100%]
Downloading daily-17947.cdiff [100%]
daily.cld updated (version: 17947, sigs: 406951, f-level: 63, builder: neo)
Downloading bytecode-227.cdiff [100%]
Downloading bytecode-228.cdiff [100%]
bytecode.cld updated (version: 228, sigs: 43, f-level: 63, builder: neo)
Database updated (2831219 signatures) from database.clamav.net (IP: 64.6.100.177)
\end{verbatim}
For more detailed help, type 'man clamscan' or 'clamscan --help'.
\subsection{Clamconf}\label{sec:clamconf}
\verb+clamconf+ is the Clam Anti-Virus configuration utility. It is used
for displaying values of configurations options in ClamAV, which
will show the contents of clamd.conf (or tell you if it is not
properly configured), the contents of freshclam.conf, and display
information about software settings, database, platform, and build
information. Here is a sample clamconf output:
\begin{verbatim}
$ clamconf
Checking configuration files in /etc/clamav
Config file: clamd.conf
-----------------------
ERROR: Please edit the example config file /etc/clamav/clamd.conf
Config file: freshclam.conf
---------------------------
ERROR: Please edit the example config file /etc/clamav/freshclam.conf
clamav-milter.conf not found
Software settings
-----------------
Version: 0.97.6
Optional features supported: MEMPOOL IPv6 CLAMUKO AUTOIT_EA06 BZIP2 RAR JIT
Database information
--------------------
Database directory: /usr/local/share/clamav
WARNING: freshclam.conf and clamd.conf point to different database directories
print_dbs: Can't open directory /usr/local/share/clamav
Platform information
--------------------
uname: Linux 2.6.32-279.el6.x86_64 #1 SMP Fri Jun 22 12:19:21 UTC 2012 x86_64
OS: linux-gnu, ARCH: x86_64, CPU: x86_64
Full OS version: ``CentOS release 6.3 (Final)''
zlib version: 1.2.3 (1.2.3), compile flags: a9
Triple: x86_64-unknown-linux-gnu
CPU: amdfam10, Little-endian
platform id: 0x0a2143430804040607040406
Build information
-----------------
GNU C: 4.4.6 20120305 (Red Hat 4.4.6-4) (4.4.6)
GNU C++: 4.4.6 20120305 (Red Hat 4.4.6-4) (4.4.6)
CPPFLAGS:
CFLAGS: -g -O2 -fno-strict-aliasing
CXXFLAGS:
LDFLAGS:
Configure: '--enable-check' '--sysconfdir=/etc/clamav'
--enable-ltdl-convenience
sizeof(void*) = 8
\end{verbatim}
For more detailed help, type 'man clamconf' or 'clamconf --help'.
\subsection{Output format}
\subsubsection{clamscan}
@ -723,7 +871,7 @@ N * * * * /usr/local/bin/freshclam --quiet
\verb+FOUND+ strings. In case of archives the scanner depends on libclamav
and only prints the first virus found within an archive:
\begin{verbatim}
zolw@localhost:/tmp$ clamscan malware.zip
$ clamscan malware.zip
malware.zip: Worm.Mydoom.U FOUND
\end{verbatim}
When using the --allmatch(-z) flag, clamscan may print multiple virus
@ -732,7 +880,7 @@ N * * * * /usr/local/bin/freshclam --quiet
\subsubsection{clamd}
The output format of \verb+clamd+ is very similar to \verb+clamscan+.
\begin{verbatim}
zolw@localhost:~$ telnet localhost 3310
$ telnet localhost 3310
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
@ -823,8 +971,14 @@ N * * * * /usr/local/bin/freshclam --quiet
decoding and normalization is only performed for HTML files.
\subsubsection{Data Loss Prevention}
Libclamav includes a DLP module which can detect credit card and
social security numbers inside text files.
Libclamav includes a DLP module which can detect the following
credit card issuers: AMEX, VISA, MasterCard, Discover, Diner's Club,
and JCB and U.S. social security numbers inside text files.
\\\\
Future versions of Libclamav may include additional features to
detect other credit cards and other forms of PII (Personally
Identifiable Information) which may be transmitted without the
benefit of being encrypted.
\subsubsection{Others}
Libclamav can handle various obfuscators, encoders, files vulnerable to
@ -1115,9 +1269,9 @@ const char *cl_engine_get_str(const struct cl_engine *engine,
\subsubsection{clamav-config}
Use \verb+clamav-config+ to check compilation information for libclamav.
\begin{verbatim}
zolw@localhost:~$ clamav-config --libs
$ clamav-config --libs
-L/usr/local/lib -lz -lbz2 -lgmp -lpthread
zolw@localhost:~$ clamav-config --cflags
$ clamav-config --cflags
-I/usr/local/include -g -O2
\end{verbatim}
@ -1139,7 +1293,7 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
\end{verbatim}
\verb+sigtool --info+ displays detailed information on CVD files:
\begin{verbatim}
zolw@localhost:/usr/local/share/clamav$ sigtool -i daily.cvd
$ sigtool -i daily.cvd
File: daily.cvd
Build time: 10 Mar 2008 10:45 +0000
Version: 6191

@ -64,6 +64,9 @@ Initialization</A>
struct cl_engine *cl_engine_new(void);
int cl_engine_free(struct cl_engine *engine);
</PRE>
At this time, <code>cl_init()</code> only supports the <code>CL_INIT_DEFAULT</code> option
which intializes libclamav with the default settings.
<code>cl_init()</code> and <code>cl_engine_free()</code> return <code>CL_SUCCESS</code>
on success or another code on error. <code>cl_engine_new()</code> return
a pointer or NULL if there's not enough memory to allocate a new

@ -108,7 +108,7 @@ Load bytecode.
unsigned int sigs = 0;
int ret;
if((ret = cl_init()) != CL_SUCCESS) {
if((ret = cl_init(CL_INIT_DEFAULT)) != CL_SUCCESS) {
printf("cl_init() error: %s\n", cl_strerror(ret));
return 1;
}

@ -222,8 +222,8 @@ Example
#DetectPUA yes
# Exclude a specific PUA category. This directive can be used multiple times.
# See http://www.clamav.net/support/pua for the complete list of PUA
# categories.
# See https://github.com/vrtadmin/clamav-faq/blob/master/faq/faq-pua.md for
# the complete list of PUA categories.
# Default: Load all categories (if DetectPUA is activated)
#ExcludePUA NetTool
#ExcludePUA PWTool

@ -386,6 +386,8 @@ libclamav_la_SOURCES = \
builtin_bytecodes.h\
events.c\
events.h \
adc.c \
adc.h \
dmg.c \
dmg.h \
xar.c \

@ -172,10 +172,10 @@ am_libclamav_la_OBJECTS = libclamav_la-matcher-ac.lo \
libclamav_la-macho.lo libclamav_la-ishield.lo \
libclamav_la-bytecode_api.lo libclamav_la-bytecode_api_decl.lo \
libclamav_la-cache.lo libclamav_la-bytecode_detect.lo \
libclamav_la-events.lo libclamav_la-dmg.lo libclamav_la-xar.lo \
libclamav_la-xz_iface.lo libclamav_la-sf_base64decode.lo \
libclamav_la-hfsplus.lo libclamav_la-swf.lo \
libclamav_la-jpeg.lo libclamav_la-png.lo \
libclamav_la-events.lo libclamav_la-adc.lo libclamav_la-dmg.lo \
libclamav_la-xar.lo libclamav_la-xz_iface.lo \
libclamav_la-sf_base64decode.lo libclamav_la-hfsplus.lo \
libclamav_la-swf.lo libclamav_la-jpeg.lo libclamav_la-png.lo \
libclamav_la-iso9660.lo libclamav_la-arc4.lo \
libclamav_la-rijndael.lo libclamav_la-crtmgr.lo \
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 \
bcfeatures.h bytecode_api.c bytecode_api_decl.c bytecode_api.h \
bytecode_api_impl.h bytecode_hooks.h cache.c cache.h \
bytecode_detect.c bytecode_detect.h builtin_bytecodes.h \
events.c events.h dmg.c dmg.h xar.c xar.h xz_iface.c \
xz_iface.h sf_base64decode.c sf_base64decode.h hfsplus.c \
hfsplus.h swf.c swf.h jpeg.c jpeg.h png.c png.h iso9660.c \
iso9660.h arc4.c arc4.h rijndael.c rijndael.h crtmgr.c \
crtmgr.h asn1.c asn1.h bignum.h bignum_fast.h \
events.c events.h adc.c adc.h dmg.c dmg.h xar.c xar.h \
xz_iface.c xz_iface.h sf_base64decode.c sf_base64decode.h \
hfsplus.c hfsplus.h swf.c swf.h jpeg.c jpeg.h png.c png.h \
iso9660.c iso9660.h arc4.c arc4.h rijndael.c rijndael.h \
crtmgr.c crtmgr.h asn1.c asn1.h bignum.h bignum_fast.h \
tomsfastmath/addsub/fp_add.c tomsfastmath/addsub/fp_add_d.c \
tomsfastmath/addsub/fp_addmod.c tomsfastmath/addsub/fp_cmp.c \
tomsfastmath/addsub/fp_cmp_d.c \
@ -911,6 +911,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-XzCrc64.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-XzDec.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-XzIn.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-adc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-arc4.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-asn1.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-aspack.Plo@am__quote@
@ -1907,6 +1908,13 @@ libclamav_la-events.lo: events.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@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
libclamav_la-adc.lo: adc.c
@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
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-adc.Tpo $(DEPDIR)/libclamav_la-adc.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adc.c' object='libclamav_la-adc.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@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
libclamav_la-dmg.lo: dmg.c
@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
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-dmg.Tpo $(DEPDIR)/libclamav_la-dmg.Plo

@ -0,0 +1,291 @@
/*
* Copyright (C) 2013 Sourcefire, Inc.
*
* Authors: David Raynor <draynor@sourcefire.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include <stdio.h>
#include <errno.h>
#if HAVE_STRING_H
#include <string.h>
#endif
#include "cltypes.h"
#include "others.h"
#include "adc.h"
/* #define DEBUG_ADC */
#ifdef DEBUG_ADC
# define adc_dbgmsg(...) cli_dbgmsg( __VA_ARGS__ )
#else
# define adc_dbgmsg(...) ;
#endif
/* Initialize values and collect buffer
* NOTE: buffer size must be larger than largest lookback offset */
int adc_decompressInit(adc_stream *strm)
{
if (strm == NULL) {
return ADC_IO_ERROR;
}
if (strm->state != ADC_STATE_UNINIT) {
return ADC_DATA_ERROR;
}
/* Have to buffer maximum backward lookup */
strm->buffer = (uint8_t *)calloc(ADC_BUFF_SIZE, 1);
if (strm->buffer == NULL) {
return ADC_MEM_ERROR;
}
strm->buffered = 0;
strm->state = ADC_STATE_GETTYPE;
strm->length = 0;
strm->offset = 0;
strm->curr = strm->buffer;
return ADC_OK;
}
/* Decompress routine
* NOTE: Reaching end of input buffer does not mean end of output.
* It may fill the output buffer but have more to output.
* It will only return ADC_STREAM_END if output buffer is not full.
* It will return ADC_DATA_ERROR if it ends in the middle of a phrase
* (i.e. in the middle of a lookback code or data run)
*/
int adc_decompress(adc_stream *strm)
{
uint8_t bData;
uint8_t didNothing = 1;
/* first, the error returns based on strm */
if ((strm == NULL) || (strm->next_in == NULL) || (strm->next_out == NULL)) {
return ADC_IO_ERROR;
}
if (strm->state == ADC_STATE_UNINIT) {
return ADC_DATA_ERROR;
}
cli_dbgmsg("adc_decompress: avail_in %lu avail_out %lu state %u\n", strm->avail_in, strm->avail_out, strm->state);
while (strm->avail_out) {
/* Exit if needs more in bytes and none available */
int needsInput;
switch (strm->state) {
case ADC_STATE_SHORTLOOK:
case ADC_STATE_LONGLOOK:
needsInput = 0;
break;
default:
needsInput = 1;
break;
}
if (needsInput && (strm->avail_in == 0)) {
break;
}
else {
didNothing = 0;
}
/* Find or execute statecode */
switch (strm->state) {
case ADC_STATE_GETTYPE: {
/* Grab action code */
bData = *(strm->next_in);
strm->next_in++;
strm->avail_in--;
if (bData & 0x80) {
strm->state = ADC_STATE_RAWDATA;
strm->offset = 0;
strm->length = (bData & 0x7F) + 1;
}
else if (bData & 0x40) {
strm->state = ADC_STATE_LONGOP2;
strm->offset = 0;
strm->length = (bData & 0x3F) + 4;
}
else {
strm->state = ADC_STATE_SHORTOP;
strm->offset = (bData & 0x3) * 0x100;
strm->length = ((bData & 0x3C) >> 2) + 3;
}
adc_dbgmsg("adc_decompress: GETTYPE bData %x state %u offset %u length %u\n",
bData, strm->state, strm->offset, strm->length);
break;
}
case ADC_STATE_LONGOP2: {
/* Grab first offset byte */
bData = *(strm->next_in);
strm->next_in++;
strm->avail_in--;
strm->offset = bData * 0x100;
strm->state = ADC_STATE_LONGOP1;
adc_dbgmsg("adc_decompress: LONGOP2 bData %x state %u offset %u length %u\n",
bData, strm->state, strm->offset, strm->length);
break;
}
case ADC_STATE_LONGOP1: {
/* Grab second offset byte */
bData = *(strm->next_in);
strm->next_in++;
strm->avail_in--;
strm->offset += bData + 1;
strm->state = ADC_STATE_LONGLOOK;
adc_dbgmsg("adc_decompress: LONGOP1 bData %x state %u offset %u length %u\n",
bData, strm->state, strm->offset, strm->length);
break;
}
case ADC_STATE_SHORTOP: {
/* Grab offset byte */
bData = *(strm->next_in);
strm->next_in++;
strm->avail_in--;
strm->offset += bData + 1;
strm->state = ADC_STATE_SHORTLOOK;
adc_dbgmsg("adc_decompress: SHORTOP bData %x state %u offset %u length %u\n",
bData, strm->state, strm->offset, strm->length);
break;
}
case ADC_STATE_RAWDATA: {
/* Grab data */
adc_dbgmsg("adc_decompress: RAWDATA offset %u length %u\n", strm->offset, strm->length);
while ((strm->avail_in > 0) && (strm->avail_out > 0) && (strm->length > 0)) {
bData = *(strm->next_in);
strm->next_in++;
strm->avail_in--;
/* store to output */
*(strm->next_out) = bData;
strm->next_out++;
strm->avail_out--;
/* store to buffer */
if (strm->curr >= (strm->buffer + ADC_BUFF_SIZE)) {
strm->curr = strm->buffer;
}
*(strm->curr) = bData;
strm->curr++;
if (strm->buffered < ADC_BUFF_SIZE) {
strm->buffered++;
}
strm->length--;
}
if (strm->length == 0) {
/* adc_dbgmsg("adc_decompress: RAWDATADONE buffered %u avail_in %u avail_out %u \n",
strm->buffered, strm->avail_in, strm->avail_out); */
strm->state = ADC_STATE_GETTYPE;
}
break;
}
case ADC_STATE_SHORTLOOK:
case ADC_STATE_LONGLOOK: {
/* Copy data */
adc_dbgmsg("adc_decompress: LOOKBACK offset %u length %u avail_in %u avail_out %u\n",
strm->offset, strm->length, strm->avail_in, strm->avail_out);
while ((strm->avail_out > 0) && (strm->length > 0)) {
/* state validation first */
if (strm->offset > 0x10000) {
cli_dbgmsg("adc_decompress: bad LOOKBACK offset %u\n", strm->offset);
return ADC_DATA_ERROR;
}
else if ((strm->state == ADC_STATE_SHORTLOOK) && (strm->offset > 0x400)) {
cli_dbgmsg("adc_decompress: bad LOOKBACK offset %u\n", strm->offset);
return ADC_DATA_ERROR;
}
if (strm->offset > strm->buffered) {
cli_dbgmsg("adc_decompress: too large LOOKBACK offset %u\n", strm->offset);
return ADC_DATA_ERROR;
}
/* retrieve byte */
if (strm->curr >= (strm->buffer + ADC_BUFF_SIZE)) {
strm->curr = strm->buffer;
}
if (strm->curr > (strm->buffer + strm->offset)) {
bData = *(uint8_t *)(strm->curr - strm->offset);
}
else {
bData = *(uint8_t *)(strm->curr + ADC_BUFF_SIZE - strm->offset);
}
/* store to output */
*(strm->next_out) = bData;
strm->next_out++;
strm->avail_out--;
/* store to buffer */
*(strm->curr) = bData;
strm->curr++;
if (strm->buffered < ADC_BUFF_SIZE) {
strm->buffered++;
}
strm->length--;
}
if (strm->length == 0) {
strm->state = ADC_STATE_GETTYPE;
/* adc_dbgmsg("adc_decompress: LOOKBACKDONE buffered %u avail_in %u avail_out %u \n",
strm->buffered, strm->avail_in, strm->avail_out); */
}
break;
}
default: {
/* bad state */
cli_errmsg("adc_decompress: invalid state %u\n", strm->state);
return ADC_DATA_ERROR;
}
} /* end switch */
} /* end while */
/* There really isn't a terminator, just end of data */
if (didNothing && strm->avail_out) {
if (strm->state == ADC_STATE_GETTYPE) {
/* Nothing left to do */
return ADC_STREAM_END;
}
else {
/* Ended mid phrase */
cli_dbgmsg("adc_decompress: stream ended mid-phrase, state %u\n", strm->state);
return ADC_DATA_ERROR;
}
}
return ADC_OK;
}
/* Cleanup routine, frees buffer */
int adc_decompressEnd(adc_stream *strm)
{
if (strm == NULL) {
return ADC_IO_ERROR;
}
if (strm->state == ADC_STATE_UNINIT) {
return ADC_DATA_ERROR;
}
if (strm->buffer != NULL) {
free(strm->buffer);
}
strm->buffered = 0;
strm->state = ADC_STATE_UNINIT;
strm->length = 0;
strm->offset = 0;
return ADC_OK;
}

@ -0,0 +1,55 @@
#ifndef CLAM_ADC_H
#define CLAM_ADC_H
struct adc_stream {
uint8_t *next_in;
size_t avail_in;
size_t total_in;
uint8_t *next_out;
size_t avail_out;
size_t total_out;
/* internals */
uint8_t *buffer;
uint8_t *curr;
uint32_t buffered;
uint16_t state;
uint16_t length;
uint32_t offset;
};
typedef struct adc_stream adc_stream;
#define ADC_BUFF_SIZE 65536
#define ADC_MEM_ERROR -1
#define ADC_DATA_ERROR -2
#define ADC_IO_ERROR -3
#define ADC_OK 0
#define ADC_STREAM_END 1
enum adc_state {
ADC_STATE_UNINIT = 0,
ADC_STATE_GETTYPE = 1,
ADC_STATE_RAWDATA = 2,
ADC_STATE_SHORTOP = 3,
ADC_STATE_LONGOP2 = 4,
ADC_STATE_LONGOP1 = 5,
ADC_STATE_SHORTLOOK = 6,
ADC_STATE_LONGLOOK = 7
};
/* Compression phrases
* store phrase - 1 byte header + data, first byte 0x80-0xFF, max length 0x80 (7 bits + 1), no offset
* short phrase - 2 byte header + data, first byte 0x00-0x3F, max length 0x12 (4 bits + 3), max offset 0x3FF (10 bits)
* long phrase - 3 byte header + data, first byte 0x40-0x7F, max length 0x43 (6 bits + 4), max offset 0xFFFF (16 bits)
*/
int adc_decompressInit(adc_stream *strm);
int adc_decompress(adc_stream *strm);
int adc_decompressEnd(adc_stream *strm);
#endif

@ -54,9 +54,10 @@
#include "dmg.h"
#include "scanners.h"
#include "sf_base64decode.h"
#include "adc.h"
// #define DEBUG_DMG_PARSE
// #define DEBUG_DMG_BZIP
/* #define DEBUG_DMG_PARSE */
/* #define DEBUG_DMG_BZIP */
#ifdef DEBUG_DMG_PARSE
# define dmg_parsemsg(...) cli_dbgmsg( __VA_ARGS__)
@ -710,11 +711,85 @@ static int dmg_stripe_store(cli_ctx *ctx, int fd, uint32_t index, struct dmg_mis
/* Stripe handling: ADC block (type 0x80000004) */
static int dmg_stripe_adc(cli_ctx *ctx, int fd, uint32_t index, struct dmg_mish_with_stripes *mish_set)
{
/* Temporary stub */
cli_dbgmsg("dmg_stripe_adc: stripe " STDu32 "\n", index);
/* Return as format error to prevent scan for now */
int ret = CL_CLEAN, adcret;
adc_stream strm;
size_t off = mish_set->stripes[index].dataOffset;
size_t len = mish_set->stripes[index].dataLength;
uint64_t size_so_far = 0;
uint64_t expected_len = mish_set->stripes[index].sectorCount * DMG_SECTOR_SIZE;
uint8_t obuf[BUFSIZ];
cli_dbgmsg("dmg_stripe_adc: stripe " STDu32 " initial len " STDu64 " expected len " STDu64 "\n",
index, len, expected_len);
if (len == 0)
return CL_CLEAN;
memset(&strm, 0, sizeof(strm));
strm.next_in = (void*)fmap_need_off_once(*ctx->fmap, off, len);
if (!strm.next_in) {
cli_warnmsg("dmg_stripe_adc: fmap need failed on stripe " STDu32 "\n", index);
return CL_EMAP;
}
strm.avail_in = len;
strm.next_out = obuf;
strm.avail_out = sizeof(obuf);
adcret = adc_decompressInit(&strm);
if(adcret != ADC_OK) {
cli_warnmsg("dmg_stripe_adc: adc_decompressInit failed\n");
return CL_EMEM;
}
while(adcret == ADC_OK) {
int written;
if (size_so_far > expected_len) {
cli_warnmsg("dmg_stripe_adc: expected size exceeded!\n");
adc_decompressEnd(&strm);
return CL_EFORMAT;
}
adcret = adc_decompress(&strm);
switch(adcret) {
case ADC_OK:
if(strm.avail_out == 0) {
if ((written=cli_writen(fd, obuf, sizeof(obuf)))!=sizeof(obuf)) {
cli_errmsg("dmg_stripe_adc: failed write to output file\n");
adc_decompressEnd(&strm);
return CL_EWRITE;
}
size_so_far += written;
strm.next_out = obuf;
strm.avail_out = sizeof(obuf);
}
continue;
case ADC_STREAM_END:
default:
written = sizeof(obuf) - strm.avail_out;
if (written) {
if ((cli_writen(fd, obuf, written))!=written) {
cli_errmsg("dmg_stripe_adc: failed write to output file\n");
adc_decompressEnd(&strm);
return CL_EWRITE;
}
size_so_far += written;
strm.next_out = obuf;
strm.avail_out = sizeof(obuf);
}
if (adcret == Z_STREAM_END)
break;
cli_dbgmsg("dmg_stripe_adc: after writing " STDu64 " bytes, "
"got error %d decompressing stripe " STDu32 "\n",
size_so_far, adcret, index);
adc_decompressEnd(&strm);
return CL_EFORMAT;
}
break;
}
adc_decompressEnd(&strm);
cli_dbgmsg("dmg_stripe_adc: stripe " STDu32 " actual len " STDu64 " expected len " STDu64 "\n",
index, size_so_far, expected_len);
return CL_CLEAN;
}
/* Stripe handling: deflate block (type 0x80000005) */
static int dmg_stripe_inflate(cli_ctx *ctx, int fd, uint32_t index, struct dmg_mish_with_stripes *mish_set)

@ -651,6 +651,8 @@ static int hfsplus_walk_catalog(cli_ctx *ctx, hfsPlusVolumeHeader *volHeader, hf
}
memcpy(&fileRec, &(nodeBuf[recordStart+keylen+2]), sizeof(hfsPlusCatalogFile));
/* Only scan files */
fileRec.permissions.fileMode = be16_to_host(fileRec.permissions.fileMode);
if ((fileRec.permissions.fileMode & HFS_MODE_TYPEMASK) == HFS_MODE_FILE) {
/* Convert forks and scan */
forkdata_to_host(&(fileRec.dataFork));
@ -658,36 +660,41 @@ static int hfsplus_walk_catalog(cli_ctx *ctx, hfsPlusVolumeHeader *volHeader, hf
if (fileRec.dataFork.logicalSize) {
ret = hfsplus_scanfile(ctx, volHeader, extHeader, &(fileRec.dataFork), dirname);
}
if (ret != CL_CLEAN) {
cli_dbgmsg("hfsplus_walk_catalog: data fork retcode %d", ret);
/* Check return code */
if (ret == CL_VIRUS) {
has_alerts = 1;
if (SCAN_ALL) {
/* Continue scanning in SCAN_ALL mode */
cli_dbgmsg("hfsplus_walk_catalog: data fork alert, continuing");
ret = CL_CLEAN;
}
}
if (ret != CL_CLEAN) {
cli_dbgmsg("hfsplus_walk_catalog: data fork retcode %d", ret);
break;
}
/* Scan resource fork */
forkdata_to_host(&(fileRec.resourceFork));
forkdata_print("resource fork:", &(fileRec.resourceFork));
if (fileRec.resourceFork.logicalSize) {
ret = hfsplus_scanfile(ctx, volHeader, extHeader, &(fileRec.resourceFork), dirname);
}
if (ret != CL_CLEAN) {
cli_dbgmsg("hfsplus_walk_catalog: resource fork retcode %d", ret);
/* Check return code */
if (ret == CL_VIRUS) {
has_alerts = 1;
if (SCAN_ALL) {
/* Continue scanning in SCAN_ALL mode */
cli_dbgmsg("hfsplus_walk_catalog: resource fork alert, continuing");
ret = CL_CLEAN;
}
}
if (ret != CL_CLEAN) {
cli_dbgmsg("hfsplus_walk_catalog: resource fork retcode %d", ret);
break;
}
}
else {
cli_dbgmsg("hfsplus_walk_catalog: record mode is not File\n");
cli_dbgmsg("hfsplus_walk_catalog: record mode %o is not File\n", fileRec.permissions.fileMode);
}
}
/* if return code, exit loop, message already logged */

@ -452,12 +452,6 @@ struct MP *mpool_create() {
sz = align_to_pagesize(&mp, MIN_FRAGSIZE);
mp.u.mpm.usize = sizeof(struct MPMAP);
mp.u.mpm.size = sz - sizeof(mp);
#ifndef _WIN32
if ((mpool_p = (struct MP *)mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE|ANONYMOUS_MAP, -1, 0)) == MAP_FAILED)
#else
if(!(mpool_p = (struct MP *)VirtualAlloc(NULL, sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)))
#endif
return NULL;
if (FRAGSBITS > 255) {
cli_errmsg("At most 255 frags possible!\n");
return NULL;
@ -466,6 +460,12 @@ struct MP *mpool_create() {
cli_errmsg("fragsz[0] too small!\n");
return NULL;
}
#ifndef _WIN32
if ((mpool_p = (struct MP *)mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE|ANONYMOUS_MAP, -1, 0)) == MAP_FAILED)
#else
if(!(mpool_p = (struct MP *)VirtualAlloc(NULL, sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)))
#endif
return NULL;
#ifdef CL_DEBUG
memset(mpool_p, ALLOCPOISON, sz);
#endif

@ -2909,7 +2909,36 @@ int cl_load(const char *path, struct cl_engine *engine, unsigned int *signo, uns
}
if(CLAMSTAT(path, &sb) == -1) {
cli_errmsg("cl_load(): Can't get status of %s\n", path);
switch (errno) {
#if defined(EACCES)
case EACCES:
cli_errmsg("cl_load(): Access denied for path: %s\n", path);
break;
#endif
#if defined(ENOENT)
case ENOENT:
cli_errmsg("cl_load(): No such file or directory: %s\n", path);
break;
#endif
#if defined(ELOOP)
case ELOOP:
cli_errmsg("cl_load(): Too many symbolic links encountered in path: %s\n", path);
break;
#endif
#if defined(EOVERFLOW)
case EOVERFLOW:
cli_errmsg("cl_load(): File size is too large to be recognized. Path: %s\n", path);
break;
#endif
#if defined(EIO)
case EIO:
cli_errmsg("cl_load(): An I/O error occurred while reading from path: %s\n", path);
break;
#endif
default:
cli_errmsg("cl_load: Can't get status of: %s\n", path);
break;
}
return CL_ESTAT;
}

@ -282,6 +282,7 @@
<ClCompile Include="..\libclamav\7z\Bra.c" />
<ClCompile Include="..\libclamav\7z\Bra86.c" />
<ClCompile Include="..\libclamav\7z\LzmaDec.c" />
<ClCompile Include="..\libclamav\adc.c" />
<ClCompile Include="..\libclamav\aspack.c" />
<ClCompile Include="..\libclamav\autoit.c" />
<ClCompile Include="..\libclamav\binhex.c" />

@ -51,6 +51,9 @@
<ClCompile Include="..\libclamav\bytecode_api_decl.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libclamav\adc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\libclamav\aspack.c">
<Filter>Source Files</Filter>
</ClCompile>

Loading…
Cancel
Save