Browse code

merge backport fixes for 0.88.1

git-svn-id: file:///var/lib/svn/clamav-devel/branches/0.88-stable@2795 77e5149b-7576-45b1-b177-96237e5ba77b

Sven Strickroth authored on 2007/02/18 23:41:27
Showing 37 changed files
... ...
@@ -1,3 +1,30 @@
1
+Tue Apr  4 12:04:07 CEST 2006
2
+-----------------------------
3
+  V 0.88.1
4
+  * Bugfixes:
5
+    - libclamav/matcher.c: properly handle partial reads in cli_scandesc()
6
+    - libclamav/mbox.c: sync with CVS, fixes detection of Worm.Bagle.CT
7
+    - freshclam: fix support for LocalIPAddress
8
+      Patch by Anton Yuzhaninov <citrin*citrin.ru>
9
+    - docs/man: multiple manpage typo fixes
10
+      Patch by A. Costa <agcosta*gis.net>)
11
+    - shared/output.c: properly handle return value of vsnprintf
12
+      Thanks to Anton Yuzhaninov <citrin*rambler-co.ru>
13
+    - libclamav/htmlnorm.c: fix typo spotted by Gianluigi Tiesi
14
+      <sherpya*netfarm.it>
15
+    - sigtool/sigtool.c: fix possible crash in build(), thanks to Sven
16
+    - clamd/session.c: remove static timeout (5s) for SESSION
17
+      Pointed out by Joseph Benden <joe*thrallingpenguin.com>
18
+    - libclamav/pe.c: fix possible integer overflow reported by Damian Put
19
+      Note: only exploitable if file size limit (ArchiveMaxFileSize) disabled
20
+    - libclamav/scanners.c: properly report archive unpacking errors
21
+      Problem spotted by David F. Skoll <dfs*roaringpenguin.com>
22
+    - libclamav/others.c: fix possible crash in cli_bitset_test()
23
+      Reported by David Luyer <david_luyer*pacific.net.au>
24
+    - libclamav/zziplib: fix possible crash on FreeBSD
25
+      Reported by Robert Rebbun <robert*desertsurf.com>
26
+    - clamav-milter: fall back if sendfile() fails
27
+
1 28
 Mon Jan  9 18:26:21 CET 2006
2 29
 ----------------------------
3 30
   V 0.88
... ...
@@ -1,9 +1,8 @@
1
-0.88
1
+0.88.1
2
+------
2 3
 
3
-A possible heap overflow in the UPX code has been fixed. General improvements
4
-include better zip and mail processing, and support for a self-protection mode.
5
-The security of the UPX, FSG and Petite modules has been improved, too.
4
+This version fixes a number of minor bugs and provides code updates
5
+to improve virus detection.
6 6
 
7 7
 --
8 8
 The ClamAV team (http://www.clamav.net/team.html)
... ...
@@ -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.88.1
6
+------
7
+
8
+This version fixes a number of minor bugs and provides code updates
9
+to improve virus detection.
10
+
11
+--
12
+The ClamAV team (http://www.clamav.net/team.html)
13
+
14
+
5 15
 0.88
6 16
 ----
7 17
 
... ...
@@ -198,6 +198,9 @@
198 198
 /* Define to 1 if you have the `snprintf' function. */
199 199
 #undef HAVE_SNPRINTF
200 200
 
201
+/* Define to 1 if you have the 'socklen_t' type. */
202
+#undef HAVE_SOCKLEN_T
203
+
201 204
 /* Define to 1 if you have the <stdint.h> header file. */
202 205
 #undef HAVE_STDINT_H
203 206
 
... ...
@@ -23,12 +23,12 @@
23 23
  * For installation instructions see the file INSTALL that came with this file
24 24
  */
25 25
 
26
-#define	CM_VERSION	"0.87"
27
-
28 26
 #if HAVE_CONFIG_H
29 27
 #include "clamav-config.h"
30 28
 #endif
31 29
 
30
+#define	CM_VERSION	VERSION
31
+
32 32
 #include "defaults.h"
33 33
 #include "cfgparser.h"
34 34
 #include "target.h"
... ...
@@ -4173,8 +4173,9 @@ move(const char *oldfile, const char *newfile)
4173 4173
 	int ret;
4174 4174
 #ifdef	C_LINUX
4175 4175
 	struct stat statb;
4176
-	int fin, fout;
4176
+	int fin, fout, c;
4177 4177
 	off_t offset;
4178
+	FILE *fsin, *fsout;
4178 4179
 #else
4179 4180
 	FILE *fin, *fout;
4180 4181
 	int c;
... ...
@@ -4211,12 +4212,27 @@ move(const char *oldfile, const char *newfile)
4211 4211
 	ret = sendfile(fout, fin, &offset, statb.st_size);
4212 4212
 	close(fin);
4213 4213
 	if(ret < 0) {
4214
+		/* fall back if sendfile fails, which shouldn't happen */
4214 4215
 		perror(newfile);
4215 4216
 		close(fout);
4216 4217
 		unlink(newfile);
4217
-		return -1;
4218
-	}
4219
-	close(fout);
4218
+
4219
+		fsin = fopen(oldfile, "r");
4220
+		if(fsin == NULL)
4221
+			return -1;
4222
+
4223
+		fsout = fopen(newfile, "w");
4224
+		if(fsout == NULL) {
4225
+			fclose(fsin);
4226
+			return -1;
4227
+		}
4228
+		while((c = getc(fsin)) != EOF)
4229
+			putc(c, fsout);
4230
+
4231
+		fclose(fsin);
4232
+		fclose(fsout);
4233
+	} else
4234
+		close(fout);
4220 4235
 #else
4221 4236
 	fin = fopen(oldfile, "r");
4222 4237
 	if(fin == NULL)
... ...
@@ -205,19 +205,18 @@ int scan(const char *filename, unsigned long int *scanned, const struct cl_node
205 205
 	const char *virname;
206 206
 
207 207
 
208
-    /* check permissions  */
209
-    if(access(filename, R_OK)) {
210
-	mdprintf(odesc, "%s: Access denied. ERROR\n", filename);
211
-	return -1;
212
-    }
213
-
214 208
     /* stat file */
215
-
216 209
     if(lstat(filename, &sb) == -1) {
217 210
 	mdprintf(odesc, "%s: lstat() failed. ERROR\n", filename);
218 211
 	return -1;
219 212
     }
220 213
 
214
+    /* check permissions  */
215
+    if(access(filename, R_OK)) {
216
+	mdprintf(odesc, "%s: Access denied. ERROR\n", filename);
217
+	return -1;
218
+    }
219
+
221 220
     switch(sb.st_mode & S_IFMT) {
222 221
 	case S_IFLNK:
223 222
 	    if(!cfgopt(copt, "FollowFileSymlinks"))
... ...
@@ -105,7 +105,6 @@ void scanner_thread(void *arg)
105 105
 
106 106
 	    case COMMAND_SESSION:
107 107
 		session = TRUE;
108
-		timeout = 5;
109 108
 		break;
110 109
 
111 110
 	    case COMMAND_END:
... ...
@@ -192,7 +192,11 @@ int dsstream(int sockd, const struct optstruct *opt)
192 192
 	int wsockd, loopw = 60, bread, port, infected = 0;
193 193
 	struct sockaddr_in server;
194 194
 	struct sockaddr_in peer;
195
+#ifdef HAVE_SOCKLEN_T
195 196
 	socklen_t peer_size;
197
+#else
198
+	int peer_size;
199
+#endif
196 200
 	char buff[4096], *pt;
197 201
 
198 202
 
... ...
@@ -2073,7 +2073,7 @@ fi
2073 2073
 
2074 2074
 # Define the identity of the package.
2075 2075
  PACKAGE=clamav
2076
- VERSION="0.88"
2076
+ VERSION="0.88.1"
2077 2077
 
2078 2078
 
2079 2079
 cat >>confdefs.h <<_ACEOF
... ...
@@ -14390,6 +14390,76 @@ cat >>confdefs.h <<_ACEOF
14390 14390
 _ACEOF
14391 14391
 
14392 14392
 
14393
+echo "$as_me:$LINENO: checking for socklen_t" >&5
14394
+echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6
14395
+if test "${have_socklen_t+set}" = set; then
14396
+  echo $ECHO_N "(cached) $ECHO_C" >&6
14397
+else
14398
+
14399
+	cat >conftest.$ac_ext <<_ACEOF
14400
+/* confdefs.h.  */
14401
+_ACEOF
14402
+cat confdefs.h >>conftest.$ac_ext
14403
+cat >>conftest.$ac_ext <<_ACEOF
14404
+/* end confdefs.h.  */
14405
+
14406
+		#include <sys/types.h>
14407
+		#include <sys/socket.h>
14408
+
14409
+int
14410
+main ()
14411
+{
14412
+
14413
+		socklen_t len;
14414
+		getpeername(0, 0, &len);
14415
+
14416
+  ;
14417
+  return 0;
14418
+}
14419
+_ACEOF
14420
+rm -f conftest.$ac_objext
14421
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
14422
+  (eval $ac_compile) 2>conftest.er1
14423
+  ac_status=$?
14424
+  grep -v '^ *+' conftest.er1 >conftest.err
14425
+  rm -f conftest.er1
14426
+  cat conftest.err >&5
14427
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
14428
+  (exit $ac_status); } &&
14429
+	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
14430
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
14431
+  (eval $ac_try) 2>&5
14432
+  ac_status=$?
14433
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
14434
+  (exit $ac_status); }; } &&
14435
+	 { ac_try='test -s conftest.$ac_objext'
14436
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
14437
+  (eval $ac_try) 2>&5
14438
+  ac_status=$?
14439
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
14440
+  (exit $ac_status); }; }; then
14441
+  have_socklen_t=yes
14442
+else
14443
+  echo "$as_me: failed program was:" >&5
14444
+sed 's/^/| /' conftest.$ac_ext >&5
14445
+
14446
+have_socklen_t=no
14447
+fi
14448
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
14449
+
14450
+fi
14451
+
14452
+echo "$as_me:$LINENO: result: $have_socklen_t" >&5
14453
+echo "${ECHO_T}$have_socklen_t" >&6
14454
+
14455
+if test "$have_socklen_t" = "yes"; then
14456
+
14457
+cat >>confdefs.h <<\_ACEOF
14458
+#define HAVE_SOCKLEN_T 1
14459
+_ACEOF
14460
+
14461
+fi
14462
+
14393 14463
                                                                                                                                                                           ac_config_files="$ac_config_files libclamav/Makefile clamscan/Makefile database/Makefile docs/Makefile clamd/Makefile clamdscan/Makefile clamav-milter/Makefile freshclam/Makefile sigtool/Makefile etc/Makefile Makefile clamav-config libclamav.pc docs/man/clamd.8 docs/man/clamd.conf.5 docs/man/freshclam.1 docs/man/freshclam.conf.5"
14394 14464
 cat >confcache <<\_ACEOF
14395 14465
 # This file is a shell script that caches the results of configure
... ...
@@ -18,7 +18,7 @@ dnl   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 18
 
19 19
 AC_INIT(clamscan/clamscan.c)
20 20
 AC_CREATE_TARGET_H(target.h)
21
-AM_INIT_AUTOMAKE(clamav, "0.88")
21
+AM_INIT_AUTOMAKE(clamav, "0.88.1")
22 22
 AM_CONFIG_HEADER(clamav-config.h)
23 23
 
24 24
 LC_CURRENT=1
... ...
@@ -977,6 +977,25 @@ DEFAULT_FD_SETSIZE=256)
977 977
 AC_MSG_RESULT($DEFAULT_FD_SETSIZE)
978 978
 AC_DEFINE_UNQUOTED(DEFAULT_FD_SETSIZE, $DEFAULT_FD_SETSIZE, "default FD_SETSIZE value")
979 979
 
980
+dnl check for socklen_t
981
+AC_MSG_CHECKING([for socklen_t])
982
+AC_CACHE_VAL(have_socklen_t,[
983
+	AC_TRY_COMPILE([
984
+		#include <sys/types.h>
985
+		#include <sys/socket.h>
986
+		],[
987
+		socklen_t len;
988
+		getpeername(0, 0, &len);
989
+		],
990
+		[have_socklen_t=yes],
991
+		[have_socklen_t=no])
992
+	])
993
+AC_MSG_RESULT($have_socklen_t)
994
+
995
+if test "$have_socklen_t" = "yes"; then
996
+    AC_DEFINE(HAVE_SOCKLEN_T, 1, [Define to 1 if you have the 'socklen_t' type.])
997
+fi
998
+
980 999
 AC_OUTPUT([
981 1000
 libclamav/Makefile
982 1001
 clamscan/Makefile
983 1002
Binary files a/docs/clamav-mirror-howto.pdf and b/docs/clamav-mirror-howto.pdf differ
984 1003
Binary files a/docs/clamdoc.pdf and b/docs/clamdoc.pdf differ
... ...
@@ -69,7 +69,7 @@
69 69
     \vspace{3cm}
70 70
     \begin{flushright}
71 71
 	\rule[-1ex]{8cm}{3pt}\\
72
-	\huge Clam AntiVirus 0.88\\
72
+	\huge Clam AntiVirus 0.88.1\\
73 73
 	\huge \emph{User Manual}\\
74 74
     \end{flushright}
75 75
 
... ...
@@ -2012,7 +2012,7 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2012 2012
 	\url{clamav.ialfa.net} & 210.22.201.152 & People's Republic & Alfa Shen\\
2013 2013
 			       &		& of China	    & \email{<alfa*ialfa.net>}\\ \hline
2014 2014
 
2015
-	\url{clamavdb.ikk.sztaki.hu} & 193.225.86.3 & Hungary & Gabor Kiss\\
2015
+	\url{clamavdb.ikk.sztaki.hu} & 193.225.12.21 & Hungary & Gabor Kiss\\
2016 2016
 				     &		    &	      & \email{<kissg*debella.ikk.sztaki.hu>}\\ \hline
2017 2017
 
2018 2018
 	\url{clamav.mirrors.nks.net} & 24.73.112.74 & Florida, USA & James Neal\\
... ...
@@ -2142,8 +2142,6 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2142 2142
 			      &		       &       & \email{<ito*begi.net>}\\ \hline
2143 2143
 	\url{clamav.meiwing.com} & 210.245.226.117 & Hong Kong & Thomas Koo\\
2144 2144
 				 &		  &	      & \email{<thomas*meiwing.com>}\\ \hline
2145
-	\url{clamav.mtcnet.jp} & 221.246.94.244 & Japan & Masahiro Kawai\\
2146
-			       &		&	& \email{<kawai*mtcnet.co.jp>}\\ \hline
2147 2145
 	\url{clamav.unix.su} & 62.181.41.8 & Russian Federation & Konstantin A. Mikhailov\\
2148 2146
 			     &		   &			& \email{<kam*unix.su>}\\ \hline
2149 2147
     \end{tabular}}
... ...
@@ -2169,8 +2167,6 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2169 2169
 				  &		  &	& \email{<pavalos*theshell.com>}\\ \hline
2170 2170
 	\url{clamav.inode.at} & 81.223.20.171 & Austria & Michael Renner\\
2171 2171
 			      &		      &		& \email{<mirror*inode.at>}\\ \hline
2172
-	\url{clamav.informatik.fh-furtwangen.de} & 141.28.73.8 & Germany & Sebastian Siewior\\
2173
-						 &	       &	 & \email{<bigeasy*foo.fh-furtwangen.de>}\\ \hline
2174 2172
 	\url{clamav.cpss.edu.hk} & 218.189.210.14 & Hong Kong & Wan Pui Wa\\
2175 2173
 				 &		  &	      & \email{<puiwa*cpss.edu.hk>}\\ \hline
2176 2174
 	\url{clamav.irontec.com} & 66.111.55.10 & Tampa, & Iker Sagasti Markina\\
... ...
@@ -2197,13 +2193,13 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2197 2197
 				 &		  &	  & \email{<master*hanbiro.com>}\\ \hline
2198 2198
 	\url{clamav.vtu.lt} & 193.219.149.170 & Lithuania & Eugenijus J.\\
2199 2199
 			    &		      &		  & \email{<ejs*ar.vtu.lt>}\\ \hline
2200
-	\url{clamav.ftpproxy.org} & 217.110.63.228 & Germany & Andreas Schoenberg\\
2200
+	\url{clamav.ftpproxy.org} & 195.246.234.199 & Germany & Andreas Schoenberg\\
2201 2201
 				  &		   &	     & \email{<asg*ftpproxy.org>}\\ \hline
2202 2202
 	\url{clamav.iasi.roedu.net} & 192.129.4.120 & Romania & Subredu Manuel\\
2203 2203
 				    &		    &	      & \email{<ftpadmin*iasi.roedu.net>}\\ \hline
2204 2204
 	\url{clamav.infonet.ee} & 212.7.0.71 & Estonia & Konstantin Barinov\\
2205 2205
 				&	     &	       & \email{<sbr*infonet.ee>}\\ \hline
2206
-	\url{clamav.savework.de} & 81.169.151.96 & Germany & Kai-H. Weutzing\\
2206
+	\url{clamav.savework.de} & 85.214.44.186 & Germany & Kai-H. Weutzing\\
2207 2207
 				 &		 &	   & \email{<clamavdb*savework.de>}\\ \hline
2208 2208
     \end{tabular}}
2209 2209
     \end{center}
... ...
@@ -2216,8 +2212,6 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2216 2216
 
2217 2217
 	\url{clamav.citrin.ru} & 213.248.60.121 & Russia & Anton Yuzhaninov\\
2218 2218
 			       &		&	 & \email{<citrin*citrin.ru>}\\ \hline
2219
-	\url{clamav.keystreams.com} & 207.158.28.8 & USA & Roman Volf\\
2220
-				    &		   &	 & \email{<volfman*keystreams.com>}\\ \hline
2221 2219
 	\url{clamav.paralax.org} & 83.148.101.196 & Bulgaria & Svetoslav Vesselkoff\\
2222 2220
 				 &		  &	     & \email{<soho*paralax.org>}\\ \hline
2223 2221
 	\url{clamav.linux.pt} & 194.65.79.153 & Portugal & Jose Celestino\\
... ...
@@ -2262,6 +2256,16 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2262 2262
 					&		  &	    & \email{<fabian*lug-norderstedt.de>}\\ \hline
2263 2263
 	\url{clamav.df.lth.se} & 194.47.250.218 & Sweden & Rune Anderson\\
2264 2264
 			       &		&	 & \email{<rpa*df.lth.se>}\\ \hline
2265
+	\url{clamav.gueth.net} & 217.160.141.39 & Germany & Volker Gueth\\
2266
+			       &		&	  & \email{<volker*gueth.net>}\\ \hline
2267
+	\url{b.clamav.mirror.fizzelpark.com} & 217.115.136.170 & Germany & Thilo Bangert\\
2268
+					     &		       &	 & \email{<bangert*fizzelpark.com>}\\ \hline
2269
+	\url{clamav.dg.net.ua} & 213.186.196.225 & Ukraine & Oleksandr V. Typlynskyi\\
2270
+			       &		 &	   & \email{<clamavdb*dg.net.ua>}\\ \hline
2271
+	\url{clamav.i24horas.com.br} & 200.242.49.19 & Brazil & Renato Lins\\
2272
+				     &		     &	      & \email{<renato-clamav*autoservico.com>}\\ \hline
2273
+	\url{clamav.gva.es} & 82.159.137.16 & Spain & Jose Antonio Amador\\
2274
+			    &		    &	    & \email{<jamador*gva.es>}\\ \hline
2265 2275
     \end{tabular}}
2266 2276
     \end{center}
2267 2277
 
... ...
@@ -2269,23 +2273,27 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2269 2269
     The following people contributed to our project in some way (providing
2270 2270
     patches, bug reports, technical support, documentation, good ideas...):
2271 2271
     \begin{itemize}
2272
+	\item Clint Adams \email{<schizo*debian.org>}
2272 2273
 	\item Sergey Y. Afonin \email{<asy*kraft-s.ru>}
2273 2274
 	\item Robert Allerstorfer \email{<roal*anet.at>}
2274 2275
 	\item Claudio Alonso \email{<cfalonso*yahoo.com>}
2275 2276
 	\item Kevin Amorin \email{<kamorin*ccs.neu.edu>}
2276 2277
 	\item Kamil Andrusz \email{<wizz*mniam.net>}
2278
+	\item Tayfun Asker \email{<tasker*metu.edu.tr>}
2277 2279
 	\item Jean-Edouard Babin \email{<Jeb*jeb.com.fr>}
2278 2280
 	\item Marc Baudoin \email{<babafou*babafou.eu.org>}
2279 2281
 	\item Scott Beck \email{<sbeck*gossamer-threads.com>}
2280 2282
 	\item Rolf Eike Beer \email{<eike*mail.math.uni-mannheim.de>}
2281 2283
 	\item Rene Bellora \email{<rbellora*tecnoaccion.com.ar>}
2282 2284
 	\item Carlo Marcelo Arenas Belon \email{<carenas*sajinet.com.pe>}
2285
+	\item Joseph Benden \email{<joe*thrallingpenguin.com>}
2283 2286
 	\item Hilko Bengen \email{<bengen*vdst-ka.inka.de>}
2284 2287
 	\item Hank Beatty \email{<hbeatty*starband.net>}
2285 2288
 	\item Alexandre Biancalana \email{<ale*seudns.net>}
2286 2289
 	\item Patrick Bihan-Faou \email{<patrick*mindstep.com>}
2287 2290
 	\item Martin Blapp \email{<mb*imp.ch>}
2288 2291
 	\item Dale Blount \email{<dale*velocity.net>}
2292
+	\item Serge van den Boom \email{<svdb*stack.nl>}
2289 2293
 	\item Oliver Brandmueller \email{<ob*e-Gitt.NET>}
2290 2294
 	\item Boguslaw Brandys \email{<brandys*o2.pl>}
2291 2295
 	\item Igor Brezac \email{<igor*ipass.net>}
... ...
@@ -2320,6 +2328,7 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2320 2320
 	\item Fred van Engen \email{<fred*wooha.org>}
2321 2321
 	\item Jason Englander \email{<jason*englanders.cc>}
2322 2322
 	\item Oden Eriksson \email{<oeriksson*mandrakesoft.com>}
2323
+	\item Daniel Fahlgren \email{<fahlgren*ardendo.se>}
2323 2324
 	\item Andy Fiddaman \email{<af*jeamland.org>}
2324 2325
 	\item Edison Figueira Junior \email{<edison*brc.com.br>}
2325 2326
 	\item David Ford \email{<david+cert*blue-labs.org>}
... ...
@@ -2363,6 +2372,7 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2363 2363
 	\item Per Jessen \email{<per*computer.org>}
2364 2364
 	\item Dave Jones \email{<dave*kalkbay.co.za>}
2365 2365
 	\item Jesper Juhl \email{<juhl*dif.dk>}
2366
+	\item Kamil Kaczkowski \email{<kamil*kamil.eisp.pl>}
2366 2367
 	\item Alex Kah \email{<alex*narfonix.com>}
2367 2368
 	\item Stefan Kaltenbrunner \email{<stefan*kaltenbrunner.cc>}
2368 2369
 	\item Lloyd Kamara \email{<l.kamara*imperial.ac.uk>}
... ...
@@ -2380,6 +2390,7 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2380 2380
 	\item Mark Kushinsky \email{<mark*mdspc.com>}
2381 2381
 	\item Mike Lambert \email{<lambert*jeol.com>}
2382 2382
 	\item Thomas Lamy \email{<Thomas.Lamy*in-online.net>}
2383
+	\item Stephane Leclerc \email{<sleclerc*aliastec.net>}
2383 2384
 	\item Marty Lee \email{<marty*maui.co.uk>}
2384 2385
 	\item Dennis Leeuw \email{<dleeuw*made-it.com>}
2385 2386
 	\item Martin Lesser \email{<admin-debian*bettercom.de>}
... ...
@@ -2389,6 +2400,7 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2389 2389
 	\item Jerome Limozin \email{<jerome*limozin.net>}
2390 2390
 	\item Mike Loewen \email{<mloewen*sturgeon.cac.psu.edu>}
2391 2391
 	\item Roger Lucas \email{<roger*planbit.co.uk>}
2392
+	\item David Luyer \email{<david\_luyer*pacific.net.au>}
2392 2393
 	\item Richard Lyons \email{<frob-clamav*webcentral.com.au>}
2393 2394
 	\item David S. Madole \email{<david*madole.net>}
2394 2395
 	\item Thomas Madsen \email{<tm*softcom.dk>}
... ...
@@ -2396,6 +2408,7 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2396 2396
 	\item Joe Maimon \email{<jmaimon*ttec.com>}
2397 2397
 	\item David Majorel \email{<dm*lagoon.nc>}
2398 2398
 	\item Andrey V. Malyshev \email{<amal*krasn.ru>}
2399
+	\item Fukuda Manabu \email{<fukuda*cri-mw.co.jp>}
2399 2400
 	\item Stefan Martig \email{<sm*officeco.ch>}
2400 2401
 	\item Alexander Marx \email{<mad-ml*madness.at>}
2401 2402
 	\item Andreas Marx (\url{http://www.av-test.org/})
... ...
@@ -2452,6 +2465,7 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2452 2452
 	\item Sergei Pronin \email{<sp*finndesign.fi>}
2453 2453
 	\item Thomas Quinot \email{<thomas*cuivre.fr.eu.org>}
2454 2454
 	\item Ed Ravin \email{<eravin*panix.com>}
2455
+	\item Robert Rebbun \email{<robert*desertsurf.com>}
2455 2456
 	\item Brian A. Reiter \email{<breiter*wolfereiter.com>}
2456 2457
 	\item Didi Rieder \email{<adrieder*sbox.tugraz.at>}
2457 2458
 	\item Pavel V. Rochnyack \email{<rpv*fsf.tsu.ru>}
... ...
@@ -2469,9 +2483,11 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2469 2469
 	\item Omer Faruk Sen \email{<ofsen*enderunix.org>}
2470 2470
 	\item Sergey \email{<a\_s\_y*sama.ru>}
2471 2471
 	\item Tuomas Silen \email{<tuomas.silen*nodeta.fi>}
2472
+	\item David F. Skoll \email{<dfs*roaringpenguin.com>}
2472 2473
 	\item Al Smith \email{<ajs+clamav*aeschi.ch.eu.org>}
2473 2474
 	\item Sergey Smitienko \email{<hunter*comsys.com.ua>}
2474 2475
 	\item Solar Designer \email{<solar*openwall.com>}
2476
+	\item Joerg Sonnenberger \email{<joerg*britannica.bec.de>}
2475 2477
 	\item Kevin Spicer \email{<kevin*kevinspicer.co.uk>}
2476 2478
 	\item GertJan Spoelman \email{<cav*gjs.cc>}
2477 2479
 	\item Ole Stanstrup \email{<ole*stanstrup.dk>}
... ...
@@ -2486,6 +2502,7 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2486 2486
 	\item Masahiro Teramoto \email{<markun*onohara.to>}
2487 2487
 	\item Daniel Theodoro \email{<dtheodoro*ig.com.br>}
2488 2488
 	\item Ryan Thompson \email{<clamav*sasknow.com>}
2489
+	\item Gianluigi Tiesi \email{<sherpya*netfarm.it>}
2489 2490
 	\item Yar Tikhiy \email{<yar*comp.chem.msu.su>}
2490 2491
 	\item Andrew Toller \email{<atoller*connectfree.co.uk>}
2491 2492
 	\item Michael L. Torrie \email{<torriem*chem.byu.edu>}
... ...
@@ -2506,6 +2523,7 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2506 2506
 	\item David Wu \email{<dyw*iohk.com>}
2507 2507
 	\item Takumi Yamane \email{<yamtak*b-session.com>}
2508 2508
 	\item Youza Youzovic \email{<youza*post.cz>}
2509
+	\item Anton Yuzhaninov \email{<citrin*rambler-co.ru>}
2509 2510
 	\item Leonid Zeitlin \email{<lz*europe.com>}
2510 2511
 	\item ZMan Z. \email{<x86zman*go-a-way.dyndns.org>}
2511 2512
 	\item Andoni Zubimendi \email{<andoni*lpsat.net>}
... ...
@@ -2518,6 +2536,7 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2518 2518
 	\item Advance Healthcare Group (\url{http://www.ahgl.com.au/})
2519 2519
 	\item American Computer \& Electronic Services Corp. (\url{http://www.acesnw.com/})
2520 2520
 	\item Anonymous donor from Colorado, US
2521
+	\item Peter Ashman
2521 2522
 	\item Atlas College (\url{http://www.atlascollege.nl/})
2522 2523
 	\item AWD Online (\url{http://www.awdonline.com/})
2523 2524
 	\item BackupAssist Backup Software (\url{http://www.backupassist.com/})
... ...
@@ -2553,6 +2572,7 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2553 2553
 	\item The Free Shopping Cart people (\url{http://www.precisionweb.net/})
2554 2554
 	\item Paul Freeman
2555 2555
 	\item Jack Fung
2556
+	\item Stephen Gageby
2556 2557
 	\item Paolo Galeazzi
2557 2558
 	\item GANDI (\url{http://www.gandi.net/})
2558 2559
 	\item Jeremy Garcia (\url{http://www.linuxquestions.org/})
... ...
@@ -2567,6 +2587,7 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2567 2567
 	\item Hosting Metro LLC (\url{http://www.hostingmetro.com/})
2568 2568
 	\item IDEAL Software GmbH (\url{http://www.IdealSoftware.com/})
2569 2569
 	\item Industry Standard Computers (\url{http://www.ISCnetwork.com/})
2570
+	\item Interact2Day (\url{http://www.interact2day.com/})
2570 2571
 	\item Invisik Corporation (\url{http://www.invisik.com/})
2571 2572
 	\item itXcel Internet - Domain Registration (\url{http://www.itxcel.com})
2572 2573
 	\item Craig Jackson
... ...
@@ -2616,6 +2637,7 @@ level required:MD5 checksum:digital signature:builder name:build time (sec)
2616 2616
 	\item SearchMain (\url{http://www.searchmain.com/})
2617 2617
 	\item Olivier Silber
2618 2618
 	\item Fernando Augusto Medeiros Silva (\url{http://www.linuxplace.com.br/})
2619
+	\item Sollentuna Fria Gymnasium, Sweden (\url{http://www.sfg.se/})
2619 2620
 	\item StarBand (\url{http://www.starband.com/})
2620 2621
 	\item Stroke of Color, Inc.
2621 2622
 	\item Synchro Sistemas de Informacao (\url{http://synchro.com.br/})
... ...
@@ -146,7 +146,7 @@ Execute the COMMAND when virus is found. In the command string %v will be replac
146 146
 Default: disabled
147 147
 .TP 
148 148
 \fBExitOnOOM\fR
149
-Stop deamon when libclamav reports out of memory condition.
149
+Stop daemon when libclamav reports out of memory condition.
150 150
 .br 
151 151
 Default: disabled
152 152
 .TP 
... ...
@@ -290,7 +290,7 @@ Scan files on execute.
290 290
 Default: disabled
291 291
 .TP 
292 292
 \fBClamukoIncludePath STRING\fR
293
-Set the include paths (all files and directories in them will be scanned). You can have multiple ClamukoIncludePath directives but each directory must be added in a seperate line).
293
+Set the include paths (all files and directories in them will be scanned). You can have multiple ClamukoIncludePath directives but each directory must be added in a separate line).
294 294
 .br 
295 295
 Default: disabled
296 296
 .TP 
... ...
@@ -38,7 +38,7 @@ Load virus database from FILE or load all virus database files from DIR.
38 38
 Save scan report to FILE.
39 39
 .TP 
40 40
 \fB\-\-tempdir=DIRECTORY\fR
41
-Create temporary files in DIRECTORY. Directory must be writeable for the 'clamav' user or unprivileged user running clamscan.
41
+Create temporary files in DIRECTORY. Directory must be writable for the 'clamav' user or unprivileged user running clamscan.
42 42
 .TP 
43 43
 \fB\-\-leave\-temps\fR
44 44
 Do not remove temporary files.
... ...
@@ -65,7 +65,7 @@ Only print infected files.
65 65
 Remove infected files. \fBBe careful.\fR
66 66
 .TP 
67 67
 \fB\-\-move=DIRECTORY\fR
68
-Move infected files into DIRECTORY. Directory must be writeable for the 'clamav' user or unprivileged user running clamscan.
68
+Move infected files into DIRECTORY. Directory must be writable for the 'clamav' user or unprivileged user running clamscan.
69 69
 .TP 
70 70
 \fB\-\-no\-mail\fR
71 71
 Disable scanning of mail files.
... ...
@@ -106,7 +106,7 @@ Set archive recursion level limit. This option protects your system against DoS
106 106
 \fB\-\-max\-ratio=#n\fR
107 107
 Set maximum archive compression ratio limit. This option protects your system against DoS attacks (default: 250).
108 108
 .TP 
109
-\fB\-\-max\-dir\-recurion=#n\fR
109
+\fB\-\-max\-dir\-recursion=#n\fR
110 110
 Maximum depth directories are scanned at (default: 15).
111 111
 .TP 
112 112
 \fB\-\-unzip[=FULLPATH]\fR
... ...
@@ -185,7 +185,7 @@ Note: some return codes may only appear in a one file mode (clamscan is started
185 185
 .TP 
186 186
 57: Can't get absolute path name of current working directory.
187 187
 .TP 
188
-58: I/O error, please check your filesystem.
188
+58: I/O error, please check your file system.
189 189
 .TP 
190 190
 59: Can't get information about current user from /etc/passwd.
191 191
 .TP 
... ...
@@ -32,7 +32,7 @@ Write all messages to the standard output (stdout), instead of the standard erro
32 32
 Save download report in FILE.
33 33
 .TP 
34 34
 \fB\-\-datadir=DIRECTORY\fR
35
-Install new database in DIRECTORY. The directory must be writeable for the 'clamav' user or unprivileged user running freshclam.
35
+Install new database in DIRECTORY. The directory must be writable for the 'clamav' user or unprivileged user running freshclam.
36 36
 .TP 
37 37
 \fB\-u USER, \-\-user USER\fR
38 38
 Run as USER. By default (when started by root) freshclam drops privileges and works as the 'clamav' user.
... ...
@@ -55,10 +55,10 @@ Notify the daemon about the new database. By default it reads a hardcoded config
55 55
 Use (local) IP for HTTP downloads. Useful for multi\-homed systems. If binding fails for whatever reason, a warning is issued and freshclam behaves like without this flag.
56 56
 .TP 
57 57
 \fB\-\-on\-error\-execute=COMMAND\fR
58
-Execute COMMAND if error occured. Remeber, that virus database freshness is the most important thing in anti\-virus system. With this option freshclam can alert you (eg. send SMS) when something is going wrong.
58
+Execute COMMAND if error occurred. Remember, that virus database freshness is the most important thing in anti\-virus system. With this option freshclam can alert you (eg. send SMS) when something is going wrong.
59 59
 .TP 
60 60
 \fB\-\-on\-update\-execute=COMMAND\fR
61
-Execute COMMAND after succesful update.
61
+Execute COMMAND after successful update.
62 62
 .TP 
63 63
 \fB\-\-on\-outdated\-execute=COMMAND\fR
64 64
 Execute COMMAND when freshclam reports outdated version. In the command string %v will be replaced by the new version number.
... ...
@@ -77,7 +77,7 @@ Execute COMMAND when freshclam reports outdated version. In the command string %
77 77
 
78 78
 \fBfreshclam \-d \-c 2\fR
79 79
 .SH "RETURN CODES"
80
-0 : Database succesfully updated.
80
+0 : Database successfully updated.
81 81
 .TP 
82 82
 1 : Database is up\-to\-date.
83 83
 .TP 
... ...
@@ -107,7 +107,7 @@ Execute COMMAND when freshclam reports outdated version. In the command string %
107 107
 .TP 
108 108
 61: Can't drop privileges.
109 109
 .TP 
110
-62: Can't initialze logger.
110
+62: Can't initialize logger.
111 111
 .SH "FILES"
112 112
 .LP 
113 113
 @CFGDIR@/freshclam.conf
... ...
@@ -98,7 +98,7 @@ Use \fBIP\fR as client address for downloading databases. Useful for multi homed
98 98
 Default: Use OS\'es default outgoing IP address.
99 99
 .TP 
100 100
 \fBNotifyClamd \[STRING\]\fR
101
-Notify a running clamd(8) to reload it\'s database after a download has occured. Optionally a clamd.conf(5) file location may be given to tell freshclam(1) how to communicate with clamd(8).
101
+Notify a running clamd(8) to reload its database after a download has occurred. Optionally a clamd.conf(5) file location may be given to tell freshclam(1) how to communicate with clamd(8).
102 102
 .br .
103 103
 Default: The default is to not notify clamd. See clamd.conf(5)\'s option SelfCheck for how clamd(8) handles database updates in this case.
104 104
 .TP 
... ...
@@ -14,9 +14,9 @@ Example
14 14
 #LogFile /tmp/clamd.log
15 15
 
16 16
 # By default the log file is locked for writing - the lock protects against
17
-# running clamd multiple times (if want to run another clamd, please
18
-# copy the configuration file, change the LogFile variable, and run
19
-# the daemon with --config-file option).
17
+# running clamd multiple times (if you want to run another clamd instance,
18
+# please # copy the configuration file, change the LogFile variable, and run
19
+# the daemon with the --config-file option).
20 20
 # This option disables log file locking.
21 21
 # Default: disabled
22 22
 #LogFileUnlock
... ...
@@ -148,8 +148,8 @@ int downloadmanager(const struct cfgstruct *copt, const struct optstruct *opt, c
148 148
     }
149 149
 #endif /* HAVE_RESOLV_H */
150 150
 
151
-    if(optl(opt, "localip")) {
152
-        localip = getargl(opt, "localip");
151
+    if(optl(opt, "local-address")) {
152
+        localip = getargl(opt, "local-address");
153 153
     } else if((cpt = cfgopt(copt, "LocalIPAddress"))) {
154 154
 	localip = cpt->strarg;
155 155
     }
... ...
@@ -497,6 +497,17 @@ int wwwconnect(const char *server, const char *proxy, int pport, char *ip, char
497 497
 
498 498
     name.sin_family = AF_INET;
499 499
 
500
+#ifdef PF_INET
501
+    socketfd = socket(PF_INET, SOCK_STREAM, 0);
502
+#else
503
+    socketfd = socket(AF_INET, SOCK_STREAM, 0);
504
+#endif
505
+
506
+    if(socketfd < 0) {
507
+	mprintf("@Can't create new socket\n");
508
+	return -1;
509
+    }
510
+
500 511
     if (localip) {
501 512
 	if ((he = gethostbyname(localip)) == NULL) {
502 513
 	    char *herr;
... ...
@@ -585,6 +596,7 @@ int wwwconnect(const char *server, const char *proxy, int pport, char *ip, char
585 585
 		break;
586 586
 	}
587 587
         mprintf("@Can't get information about %s: %s\n", hostpt, herr);
588
+	close(socketfd);
588 589
 	return -1;
589 590
     }
590 591
 
... ...
@@ -602,21 +614,15 @@ int wwwconnect(const char *server, const char *proxy, int pport, char *ip, char
602 602
 	name.sin_addr = *((struct in_addr *) host->h_addr_list[i]);
603 603
 	name.sin_port = htons(port);
604 604
 
605
-#ifdef PF_INET
606
-	socketfd = socket(PF_INET, SOCK_STREAM, 0);
607
-#else
608
-	socketfd = socket(AF_INET, SOCK_STREAM, 0);
609
-#endif
610
-
611 605
 	if(connect(socketfd, (struct sockaddr *) &name, sizeof(struct sockaddr_in)) == -1) {
612 606
 	    mprintf("Can't connect to port %d of host %s (IP: %s)\n", port, hostpt, ipaddr);
613
-	    close(socketfd);
614 607
 	    continue;
608
+	} else {
609
+	    return socketfd;
615 610
 	}
616
-
617
-	return socketfd;
618 611
     }
619 612
 
613
+    close(socketfd);
620 614
     return -2;
621 615
 }
622 616
 
... ...
@@ -61,7 +61,7 @@ int main(int argc, char **argv)
61 61
 	    {"no-dns", 0, 0, 0},
62 62
 	    {"checks", 1, 0, 'c'},
63 63
 	    {"http-proxy", 1, 0, 0},
64
-	    {"client-address", 1, 0, 'a'},
64
+	    {"local-address", 1, 0, 'a'},
65 65
 	    {"proxy-user", 1, 0, 0},
66 66
 	    {"daemon-notify", 2, 0, 0},
67 67
 	    {"on-update-execute", 1, 0, 0},
... ...
@@ -124,6 +124,8 @@ libclamav_la_SOURCES = \
124 124
 	is_tar.c \
125 125
 	is_tar.h \
126 126
 	tnef.c \
127
-	tnef.h
127
+	tnef.h \
128
+	uuencode.c \
129
+	uuencode.h
128 130
 
129 131
 lib_LTLIBRARIES = libclamav.la
... ...
@@ -84,7 +84,7 @@ am_libclamav_la_OBJECTS = matcher-ac.lo matcher-bm.lo matcher.lo \
84 84
 	text.lo ole2_extract.lo vba_extract.lo msexpand.lo pe.lo \
85 85
 	cabd.lo lzxd.lo mszipd.lo qtmd.lo system.lo upx.lo htmlnorm.lo \
86 86
 	chmunpack.lo rebuildpe.lo petite.lo fsg.lo line.lo untar.lo \
87
-	special.lo binhex.lo is_tar.lo tnef.lo
87
+	special.lo binhex.lo is_tar.lo tnef.lo uuencode.lo
88 88
 libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
89 89
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
90 90
 depcomp = $(SHELL) $(top_srcdir)/depcomp
... ...
@@ -316,7 +316,9 @@ libclamav_la_SOURCES = \
316 316
 	is_tar.c \
317 317
 	is_tar.h \
318 318
 	tnef.c \
319
-	tnef.h
319
+	tnef.h \
320
+	uuencode.c \
321
+	uuencode.h
320 322
 
321 323
 lib_LTLIBRARIES = libclamav.la
322 324
 all: all-am
... ...
@@ -428,6 +430,7 @@ distclean-compile:
428 428
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unrarlib.Plo@am__quote@
429 429
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/untar.Plo@am__quote@
430 430
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upx.Plo@am__quote@
431
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uuencode.Plo@am__quote@
431 432
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vba_extract.Plo@am__quote@
432 433
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzip-dir.Plo@am__quote@
433 434
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzip-err.Plo@am__quote@
... ...
@@ -1092,7 +1092,7 @@ static int cli_html_normalise(int fd, m_area_t *m_area, const char *dirname, tag
1092 1092
 						ptr++;
1093 1093
 					}
1094 1094
 				} else if (*ptr == '\"') {
1095
-					if (!escape && (quoted=DOUBLE_QUOTED)) {
1095
+					if (!escape && (quoted==DOUBLE_QUOTED)) {
1096 1096
 						state = HTML_RFC2397_FINISH;
1097 1097
 						ptr++;
1098 1098
 					} else {
... ...
@@ -245,7 +245,8 @@ int cli_validatesig(unsigned short target, unsigned short ftype, const char *off
245 245
 int cli_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_node *root, short otfrec, unsigned short ftype)
246 246
 {
247 247
  	char *buffer, *buff, *endbl, *pt;
248
-	int bytes, buffsize, length, ret, *partcnt, type = CL_CLEAN;
248
+	int bytes, ret, *partcnt, type = CL_CLEAN;
249
+	unsigned int buffersize, length, shift = 0;
249 250
 	unsigned long int *partoff, offset = 0;
250 251
 	MD5_CTX ctx;
251 252
 	unsigned char digest[16];
... ...
@@ -258,9 +259,9 @@ int cli_scandesc(int desc, const char **virname, unsigned long int *scanned, con
258 258
     }
259 259
 
260 260
     /* prepare the buffer */
261
-    buffsize = root->maxpatlen + SCANBUFF;
262
-    if(!(buffer = (char *) cli_calloc(buffsize, sizeof(char)))) {
263
-	cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%d)\n", buffsize);
261
+    buffersize = root->maxpatlen + SCANBUFF;
262
+    if(!(buffer = (char *) cli_calloc(buffersize, sizeof(char)))) {
263
+	cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%d)\n", buffersize);
264 264
 	return CL_EMEM;
265 265
     }
266 266
 
... ...
@@ -288,14 +289,15 @@ int cli_scandesc(int desc, const char **virname, unsigned long int *scanned, con
288 288
 						*/
289 289
 
290 290
     pt = buff;
291
-    length = SCANBUFF;
292
-    while((bytes = cli_readn(desc, buff, SCANBUFF)) > 0) {
291
+    while((bytes = cli_readn(desc, buff + shift, SCANBUFF - shift)) > 0) {
293 292
 
294 293
 	if(scanned)
295 294
 	    *scanned += bytes / CL_COUNT_PRECISION;
296 295
 
297
-	if(bytes < SCANBUFF)
298
-	    length -= SCANBUFF - bytes;
296
+	length = shift + bytes;
297
+	if(pt == buffer)
298
+	    length += root->maxpatlen;
299
+
299 300
 
300 301
 	if(cli_bm_scanbuff(pt, length, virname, root, offset, ftype, desc) == CL_VIRUS ||
301 302
 	   (ret = cli_ac_scanbuff(pt, length, virname, root, partcnt, otfrec, offset, partoff, ftype, desc)) == CL_VIRUS) {
... ...
@@ -314,20 +316,22 @@ int cli_scandesc(int desc, const char **virname, unsigned long int *scanned, con
314 314
 		type = ret;
315 315
 	}
316 316
 
317
-	if(bytes == SCANBUFF) {
317
+	if(root->md5_hlist)
318
+	    MD5_Update(&ctx, buff + shift, bytes);
319
+
320
+	if(bytes + shift == SCANBUFF) {
318 321
 	    memmove(buffer, endbl, root->maxpatlen);
322
+	    offset += SCANBUFF;
319 323
 
320
-	    if(pt == buffer) {
321
-		offset += SCANBUFF;
322
-	    } else {
323
-		offset += SCANBUFF - root->maxpatlen;
324
+	    if(pt == buff) {
324 325
 		pt = buffer;
325
-		length = buffsize;
326
+		offset -= root->maxpatlen;
326 327
 	    }
327
-	}
328 328
 
329
-	if(root->md5_hlist)
330
-	    MD5_Update(&ctx, buff, bytes);
329
+	    shift = 0;
330
+	} else {
331
+	    shift += bytes;
332
+	}
331 333
     }
332 334
 
333 335
     free(buffer);
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 Nigel Horne <njh@bandsman.co.uk>
2
+ *  Copyright (C) 2002-2006 Nigel Horne <njh@bandsman.co.uk>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -15,7 +15,7 @@
15 15
  *  along with this program; if not, write to the Free Software
16 16
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 17
  */
18
-static	char	const	rcsid[] = "$Id: mbox.c,v 1.238+fixes 2005/04/19 09:20:55 nigelhorne Exp $";
18
+static	char	const	rcsid[] = "$Id: mbox.c,v 1.279 2006/02/06 02:36:39 nigelhorne Exp $";
19 19
 
20 20
 #if HAVE_CONFIG_H
21 21
 #include "clamav-config.h"
... ...
@@ -39,10 +39,7 @@ static	char	const	rcsid[] = "$Id: mbox.c,v 1.238+fixes 2005/04/19 09:20:55 nigel
39 39
 #include <strings.h>
40 40
 #include <ctype.h>
41 41
 #include <time.h>
42
-#include <unistd.h>
43 42
 #include <fcntl.h>
44
-#include <sys/stat.h>
45
-#include <sys/types.h>
46 43
 #include <sys/param.h>
47 44
 #include <clamav.h>
48 45
 #include <dirent.h>
... ...
@@ -66,6 +63,7 @@ static	char	const	rcsid[] = "$Id: mbox.c,v 1.238+fixes 2005/04/19 09:20:55 nigel
66 66
 #include "defaults.h"
67 67
 #include "str.h"
68 68
 #include "filetypes.h"
69
+#include "uuencode.h"
69 70
 
70 71
 #ifdef	CL_DEBUG
71 72
 #if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 1
... ...
@@ -98,6 +96,10 @@ static	void	print_trace(int use_syslog);
98 98
 
99 99
 typedef enum	{ FALSE = 0, TRUE = 1 } bool;
100 100
 
101
+#ifndef isblank
102
+#define isblank(c)	(((c) == ' ') || ((c) == '\t'))
103
+#endif
104
+
101 105
 #define	SAVE_TO_DISC	/* multipart/message are saved in a temporary file */
102 106
 
103 107
 /*
... ...
@@ -121,7 +123,7 @@ typedef enum	{ FALSE = 0, TRUE = 1 } bool;
121 121
 #ifdef	WITH_CURL
122 122
 #define	FOLLOWURLS	5	/*
123 123
 				 * Maximum number of URLs scanned in a message
124
-				 * part. Helps to find Dialier.gen-45. If
124
+				 * part. Helps to find Dialer.gen-45. If
125 125
 				 * not defined, don't check any URLs
126 126
 				 */
127 127
 #endif
... ...
@@ -138,14 +140,11 @@ typedef enum	{ FALSE = 0, TRUE = 1 } bool;
138 138
 #include <curl/curl.h>
139 139
 
140 140
 /*
141
- * Needs curl >= 7.11 (I've heard that 7.9 can cause crashes and 7.10 is
141
+ * Needs curl >= 7.11 (I've heard that 7.9 can cause crashes and I have seen
142
+ *	7.10 segfault, later versions can be flakey as well)
142 143
  * untested)
143 144
  */
144
-#if	(LIBCURL_VERSION_MAJOR < 7)
145
-#undef	WITH_CURL	/* also undef FOLLOWURLS? */
146
-#endif
147
-
148
-#if	(LIBCURL_VERSION_MAJOR == 7) && (LIBCURL_VERSION_MINOR < 10)
145
+#if     (LIBCURL_VERSION_NUM < 0x070B00)
149 146
 #undef	WITH_CURL	/* also undef FOLLOWURLS? */
150 147
 #endif
151 148
 
... ...
@@ -187,11 +186,7 @@ static	char	*rfc822comments(const char *in, char *out);
187 187
 static	int	rfc1341(message *m, const char *dir);
188 188
 #endif
189 189
 static	bool	usefulHeader(int commandNumber, const char *cmd);
190
-static        int     uufasttrack(message *m, const char *firstline, const char *dir, FILE *fin);
191 190
 static	char	*getline_from_mbox(char *buffer, size_t len, FILE *fin);
192
-#ifdef	NEW_WORLD
193
-static	const	char	*cli_pmemstr(const char *haystack, size_t hs, const char *needle, size_t ns);
194
-#endif
195 191
 
196 192
 static	void	checkURLs(message *m, const char *dir);
197 193
 #ifdef	WITH_CURL
... ...
@@ -208,7 +203,7 @@ static	void	*getURL(struct arg *arg);
208 208
 #endif
209 209
 
210 210
 /* Maximum line length according to RFC821 */
211
-#define	LINE_LENGTH	1000
211
+#define	RFC2821LENGTH	1000
212 212
 
213 213
 /* Hashcodes for our hash tables */
214 214
 #define	CONTENT_TYPE			1
... ...
@@ -299,21 +294,48 @@ static	pthread_mutex_t	tables_mutex = PTHREAD_MUTEX_INITIALIZER;
299 299
 
300 300
 #ifdef	NEW_WORLD
301 301
 
302
+#undef	PARTIAL_DIR
303
+
302 304
 #if HAVE_MMAP
303 305
 #if HAVE_SYS_MMAN_H
304 306
 #include <sys/mman.h>
305 307
 #else /* HAVE_SYS_MMAN_H */
306 308
 #undef HAVE_MMAP
307 309
 #endif
310
+#else	/*HAVE_MMAP*/
311
+#undef	NEW_WORLD
312
+#endif
308 313
 #endif
309 314
 
315
+#ifdef	NEW_WORLD
316
+/*
317
+ * Files larger than this are scanned with the old method, should be
318
+ *	StreamMaxLength, I guess
319
+ * If NW_MAX_FILE_SIZE is not defined, all files go through the
320
+ *	new method. This definition is for machines very tight on RAM, or
321
+ *	with large StreamMaxLength values
322
+ */
323
+#define	MAX_ALLOCATION	134217728	/* see libclamav/others.c */
324
+#define	NW_MAX_FILE_SIZE	MAX_ALLOCATION
325
+
310 326
 struct scanlist {
311
-	char *start;
312
-	size_t size;
313
-	encoding_type decoder;	/* only BASE64 and QUOTEDPRINTABLE for now */
314
-	struct scanlist *next;
327
+	const	char	*start;
328
+	size_t	size;
329
+	encoding_type	decoder;	/* only BASE64 and QUOTEDPRINTABLE for now */
330
+	struct	scanlist *next;
315 331
 };
316 332
 
333
+static struct map {
334
+	const	char	*offset;	/* sorted */
335
+	const	char	*word;
336
+	struct	map	*next;
337
+} *map, *tail;
338
+
339
+static	void	create_map(const char *begin, const char *end);
340
+static	void	add_to_map(const char *offset, const char *word);
341
+static	const	char	*find_in_map(const char *offset, const char *word);
342
+static	void	free_map(void);
343
+
317 344
 /*
318 345
  * This could be the future. Instead of parsing and decoding it just decodes.
319 346
  *
... ...
@@ -331,16 +353,21 @@ struct scanlist {
331 331
  * because the scan can proceed to the end of the file rather than the end
332 332
  * of the attachment which can mean than later emails are scanned many times
333 333
  *
334
- * TODO: Also all those pmemstr()s are slow, so we need to reduce the number
335
- *	and size of data scanned each time, and we fall through to
336
- *	cli_parse_mbox() too often
334
+ * FIXME: quoted printable doesn't know when to stop, so size related virus
335
+ *	matching breaks
336
+ *
337
+ * TODO: Fall through to cli_parse_mbox() too often
338
+ *
339
+ * TODO: Add support for systems without mmap()
340
+ *
341
+ * TODO: partial_dir fall through
337 342
  */
338 343
 int
339 344
 cli_mbox(const char *dir, int desc, unsigned int options)
340 345
 {
341
-	char *start, *ptr, *line, *p, *q;
342
-	const char *last;
343
-	size_t size, s;
346
+	char *start, *ptr, *line;
347
+	const char *last, *p, *q;
348
+	size_t size;
344 349
 	struct stat statb;
345 350
 	message *m;
346 351
 	fileblob *fb;
... ...
@@ -360,10 +387,15 @@ cli_mbox(const char *dir, int desc, unsigned int options)
360 360
 	if(size == 0)
361 361
 		return CL_CLEAN;
362 362
 
363
-	if(size > 10*1024*1024)
364
-		return cli_parse_mbox(dir, desc, options);	/* should be StreamMaxLength, I guess */
363
+#ifdef	NW_MAX_FILE_SIZE
364
+	if(size > NW_MAX_FILE_SIZE)
365
+		return cli_parse_mbox(dir, desc, options);
366
+#endif
365 367
 
366
-	cli_warnmsg("NEW_WORLD is new code - use at your own risk.\n");
368
+	/*cli_warnmsg("NEW_WORLD is new code - use at your own risk.\n");*/
369
+#ifdef	PARTIAL_DIR
370
+	cli_warnmsg("PARTIAL_DIR doesn't work in the NEW_WORLD yet\n");
371
+#endif
367 372
 
368 373
 	start = mmap(NULL, size, PROT_READ, MAP_PRIVATE, desc, 0);
369 374
 	if(start == MAP_FAILED)
... ...
@@ -371,26 +403,27 @@ cli_mbox(const char *dir, int desc, unsigned int options)
371 371
 
372 372
 	cli_dbgmsg("mmap'ed mbox\n");
373 373
 
374
-	/* last points to the last *valid* address in the array */
375
-	last = &start[size - 1];
376
-
377 374
 	ptr = cli_malloc(size);
378 375
 	if(ptr) {
379
-		wasAlloced = 1;
380 376
 		memcpy(ptr, start, size);
381 377
 		munmap(start, size);
382 378
 		start = ptr;
383
-		last = &start[size - 1];
379
+		wasAlloced = 1;
384 380
 	} else
385 381
 		wasAlloced = 0;
386 382
 
387
-	/*
388
-	 * Would be nice to have a case insensitive cli_memstr()
389
-	 */
383
+	/* last points to the last *valid* address in the array */
384
+	last = &start[size - 1];
385
+
386
+	create_map(start, last);
387
+
390 388
 	scanelem = scanlist = NULL;
391 389
 	q = start;
392
-	s = size;
393
-	while((p = (char *)cli_pmemstr(q, s, "base64", 6)) != NULL) {
390
+	/*
391
+	 * FIXME: mismatch of const char * and char * here and in later calls
392
+	 *	to find_in_map()
393
+	 */
394
+	while((p = find_in_map(q, "base64")) != NULL) {
394 395
 		cli_dbgmsg("Found base64\n");
395 396
 		if(scanelem) {
396 397
 			scanelem->next = cli_malloc(sizeof(struct scanlist));
... ...
@@ -399,25 +432,22 @@ cli_mbox(const char *dir, int desc, unsigned int options)
399 399
 			scanlist = scanelem = cli_malloc(sizeof(struct scanlist));
400 400
 		scanelem->next = NULL;
401 401
 		scanelem->decoder = BASE64;
402
-		s -= (p - q) + 6;
403 402
 		q = scanelem->start = &p[6];
404
-		if(((p = (char *)cli_pmemstr(q, s, "\nFrom ", 6)) != NULL) ||
405
-		   ((p = (char *)cli_pmemstr(q, s, "base64", 6)) != NULL) ||
406
-		   ((p = (char *)cli_pmemstr(q, s, "quoted-printable", 16)) != NULL)) {
403
+		if(((p = find_in_map(q, "\nFrom ")) != NULL) ||
404
+		   ((p = find_in_map(q, "base64")) != NULL) ||
405
+		   ((p = find_in_map(q, "quoted-printable")) != NULL)) {
407 406
 			scanelem->size = (size_t)(p - q);
408 407
 			q = p;
409
-			s -= scanelem->size;
410 408
 		} else {
411 409
 			scanelem->size = (size_t)(last - scanelem->start) + 1;
412 410
 			break;
413 411
 		}
414
-		cli_dbgmsg("base64: last %u q %u s %u\n", (unsigned int)last, (unsigned int)q, s);
412
+		cli_dbgmsg("base64: last %u q %u\n", (unsigned int)last, (unsigned int)q);
415 413
 		assert(scanelem->size <= size);
416
-		assert(&q[s - 1] <= last);
417 414
 	}
415
+
418 416
 	q = start;
419
-	s = size;
420
-	while((p = (char *)cli_pmemstr(q, s, "quoted-printable", 16)) != NULL) {
417
+	while((p = find_in_map(q, "quoted-printable")) != NULL) {
421 418
 		if(p != q)
422 419
 			switch(p[-1]) {
423 420
 				case ' ':
... ...
@@ -425,14 +455,17 @@ cli_mbox(const char *dir, int desc, unsigned int options)
425 425
 				case '=':	/* wrong but allow it */
426 426
 					break;
427 427
 				default:
428
-					s -= (p - q) + 16;
429 428
 					q = &p[16];
430 429
 					cli_dbgmsg("Ignore quoted-printable false positive\n");
431
-					cli_dbgmsg("s = %u\n", s);
432 430
 					continue;	/* false positive */
433 431
 			}
434 432
 
435 433
 		cli_dbgmsg("Found quoted-printable\n");
434
+#ifdef	notdef
435
+		/*
436
+		 * The problem with quoted printable is recognising when to stop
437
+		 * parsing
438
+		 */
436 439
 		if(scanelem) {
437 440
 			scanelem->next = cli_malloc(sizeof(struct scanlist));
438 441
 			scanelem = scanelem->next;
... ...
@@ -440,40 +473,55 @@ cli_mbox(const char *dir, int desc, unsigned int options)
440 440
 			scanlist = scanelem = cli_malloc(sizeof(struct scanlist));
441 441
 		scanelem->next = NULL;
442 442
 		scanelem->decoder = QUOTEDPRINTABLE;
443
-		s -= (p - q) + 16;
444 443
 		q = scanelem->start = &p[16];
445
-		cli_dbgmsg("qp: last %u q %u s %u\n", (unsigned int)last, (unsigned int)q, s);
446
-		if(((p = (char *)cli_pmemstr(q, s, "\nFrom ", 6)) != NULL) ||
447
-		   ((p = (char *)cli_pmemstr(q, s, "quoted-printable", 16)) != NULL) ||
448
-		   ((p = (char *)cli_pmemstr(q, s, "base64", 6)) != NULL)) {
444
+		cli_dbgmsg("qp: last %u q %u\n", (unsigned int)last, (unsigned int)q);
445
+		if(((p = find_in_map(q, "\nFrom ")) != NULL) ||
446
+		   ((p = find_in_map(q, "quoted-printable")) != NULL) ||
447
+		   ((p = find_in_map(q, "base64")) != NULL)) {
449 448
 			scanelem->size = (size_t)(p - q);
450 449
 			q = p;
451
-			s -= scanelem->size;
452 450
 			cli_dbgmsg("qp: scanelem->size = %u\n", scanelem->size);
453 451
 		} else {
454 452
 			scanelem->size = (size_t)(last - scanelem->start) + 1;
455 453
 			break;
456 454
 		}
457 455
 		assert(scanelem->size <= size);
458
-		assert(&q[s - 1] <= last);
456
+#else
457
+		if(wasAlloced)
458
+			free(start);
459
+		else
460
+			munmap(start, size);
461
+
462
+		free_map();
463
+		return cli_parse_mbox(dir, desc, options);
464
+#endif
459 465
 	}
460 466
 
461 467
 	if(scanlist == NULL) {
462 468
 		const struct tableinit *tableinit;
463 469
 		bool anyHeadersFound = FALSE;
464 470
 		bool hasuuencode = FALSE;
471
+		cli_file_t type;
465 472
 
466 473
 		/* FIXME: message: There could of course be no decoder needed... */
467 474
 		for(tableinit = rfc821headers; tableinit->key; tableinit++)
468
-			if(cli_pmemstr(start, size, tableinit->key, strlen(tableinit->key))) {
475
+			if(find_in_map(start, tableinit->key)) {
469 476
 				anyHeadersFound = TRUE;
470 477
 				break;
471 478
 			}
472 479
 
473
-		if((!anyHeadersFound) && cli_pmemstr(start, size, "\nbegin ", 7))
480
+		if((!anyHeadersFound) && find_in_map(start, "\nbegin "))
474 481
 			/* uuencoded part */
475 482
 			hasuuencode = TRUE;
476 483
 
484
+		free_map();
485
+
486
+		type = cli_filetype(start, size);
487
+
488
+		if((type == CL_TYPE_UNKNOWN_TEXT) &&
489
+		   (strncmp(start, "Microsoft Mail Internet Headers", 31) == 0))
490
+			type = CL_TYPE_MAIL;
491
+
477 492
 		if(wasAlloced)
478 493
 			free(start);
479 494
 		else
... ...
@@ -481,21 +529,47 @@ cli_mbox(const char *dir, int desc, unsigned int options)
481 481
 
482 482
 		if(anyHeadersFound || hasuuencode) {
483 483
 			/* TODO: reduce the number of falls through here */
484
-			cli_warnmsg("cli_mbox: uuencode or unknown encoder\n");
485
-			return cli_parse_mbox(dir, desc, options);
484
+			if(hasuuencode)
485
+				cli_dbgmsg("New world - fall back to old uudecoder, type %d\n", type);
486
+			else
487
+				cli_dbgmsg("cli_mbox: unknown encoder, type %d\n", type);
488
+			if(type == CL_TYPE_MAIL)
489
+				return cli_parse_mbox(dir, desc, options);
490
+			cli_dbgmsg("Unknown filetype %d, return CLEAN\n", type);
491
+			return CL_CLEAN;
486 492
 		}
487 493
 
488
-		cli_warnmsg("cli_mbox: I believe it's plain text which must be clean\n");
494
+		/* The message could be a plain text phish */
495
+		if((type == CL_TYPE_MAIL) && (!(options&CL_DB_NOPHISHING)))
496
+			return cli_parse_mbox(dir, desc, options);
497
+		cli_dbgmsg("cli_mbox: I believe it's plain text which must be clean\n");
489 498
 		return CL_CLEAN;
490 499
 	}
500
+	free_map();
501
+
502
+#if	0
503
+	if(wasAlloced) {
504
+		const char *max = NULL;
505
+
506
+		for(scanelem = scanlist; scanelem; scanelem = scanelem->next) {
507
+			const char *end = &scanelem->start[scanelem->size];
508
+
509
+			if(end > max)
510
+				max = end;
511
+		}
512
+
513
+		if(max < last)
514
+			printf("could free %d bytes\n", (int)(last - max));
515
+	}
516
+#endif
491 517
 
492 518
 	for(scanelem = scanlist; scanelem; scanelem = scanelem->next) {
493 519
 		if(scanelem->decoder == BASE64) {
494
-			char *b64start = scanelem->start;
495
-			long b64size = scanelem->size;
520
+			const char *b64start = scanelem->start;
521
+			size_t b64size = scanelem->size;
496 522
 
497 523
 			cli_dbgmsg("b64size = %lu\n", b64size);
498
-			while(*b64start != '\n') {
524
+			while((*b64start != '\n') && (*b64start != '\r')) {
499 525
 				b64start++;
500 526
 				b64size--;
501 527
 			}
... ...
@@ -506,14 +580,33 @@ cli_mbox(const char *dir, int desc, unsigned int options)
506 506
 				if(*b64start == ';') {
507 507
 					b64start++;
508 508
 					b64size--;
509
-				} else if(*b64start == '\n') {
510
-					b64start++;
511
-					b64size--;
512
-					if((*b64start == '\n') || (*b64start == '\r')) {
513
-						b64start++;
514
-						b64size--;
515
-						break;
516
-					}
509
+				} else if((memcmp(b64start, "\n\n", 2) == 0) ||
510
+					  (memcmp(b64start, "\r\r", 2) == 0)) {
511
+					b64start += 2;
512
+					b64size -= 2;
513
+					break;
514
+				} else if(memcmp(b64start, "\r\n\r\n", 4) == 0) {
515
+					b64start += 4;
516
+					b64size -= 4;
517
+					break;
518
+				} else if(memcmp(b64start, "\n \n", 3) == 0) {
519
+					/*
520
+					 * Some viruses are broken and have
521
+					 * one space character at the end of
522
+					 * the headers
523
+					 */
524
+					b64start += 3;
525
+					b64size -= 3;
526
+					break;
527
+				} else if(memcmp(b64start, "\r\n \r\n", 5) == 0) {
528
+					/*
529
+					 * Some viruses are broken and have
530
+					 * one space character at the end of
531
+					 * the headers
532
+					 */
533
+					b64start += 5;
534
+					b64size -= 5;
535
+					break;
517 536
 				}
518 537
 				b64start++;
519 538
 				b64size--;
... ...
@@ -527,17 +620,27 @@ cli_mbox(const char *dir, int desc, unsigned int options)
527 527
 				}
528 528
 
529 529
 			if(b64size > 0L) {
530
+				int lastline;
530 531
 				cli_dbgmsg("cli_mbox: decoding %ld base64 bytes\n", b64size);
531 532
 
532 533
 				line = NULL;
533 534
 
534 535
 				m = messageCreate();
535
-				if(m == NULL)
536
+				if(m == NULL) {
537
+					if(wasAlloced)
538
+						free(start);
539
+					else
540
+						munmap(start, size);
541
+
536 542
 					return CL_EMEM;
543
+				}
537 544
 				messageSetEncoding(m, "base64");
538 545
 
546
+				lastline = 0;
547
+
539 548
 				do {
540 549
 					int length = 0;
550
+					char *newline, *equal;
541 551
 
542 552
 					/*printf("%ld: ", b64size); fflush(stdout);*/
543 553
 
... ...
@@ -548,23 +651,33 @@ cli_mbox(const char *dir, int desc, unsigned int options)
548 548
 
549 549
 					/*printf("%d: ", length); fflush(stdout);*/
550 550
 
551
-					line = cli_realloc(line, length + 1);
551
+					newline = cli_realloc(line, length + 1);
552
+					if(newline == NULL)
553
+						break;
554
+					line = newline;
552 555
 
553 556
 					memcpy(line, b64start, length);
554 557
 					line[length] = '\0';
555 558
 
559
+					equal = strchr(line, '=');
560
+					if(equal) {
561
+						lastline++;
562
+						*equal = '\0';
563
+					}
556 564
 					/*puts(line);*/
557 565
 
558 566
 					if(messageAddStr(m, line) < 0)
559 567
 						break;
560 568
 
561 569
 					if((b64size > 0) && (*ptr == '\r')) {
562
-						ptr++;
570
+						b64start = ++ptr;
571
+						--b64size;
572
+					}
573
+					if((b64size > 0) && (*ptr == '\n')) {
574
+						b64start = ++ptr;
563 575
 						--b64size;
564 576
 					}
565
-					b64start = ++ptr;
566
-					--b64size;
567
-					if(strchr(line, '='))
577
+					if(lastline)
568 578
 						break;
569 579
 				} while(b64size > 0L);
570 580
 
... ...
@@ -578,8 +691,8 @@ cli_mbox(const char *dir, int desc, unsigned int options)
578 578
 					ret = -1;
579 579
 			}
580 580
 		} else if(scanelem->decoder == QUOTEDPRINTABLE) {
581
-			char *quotedstart = scanelem->start;
582
-			long quotedsize = scanelem->size;
581
+			const char *quotedstart = scanelem->start;
582
+			size_t quotedsize = scanelem->size;
583 583
 
584 584
 			cli_dbgmsg("quotedsize = %lu\n", quotedsize);
585 585
 			while(*quotedstart != '\n') {
... ...
@@ -593,7 +706,7 @@ cli_mbox(const char *dir, int desc, unsigned int options)
593 593
 				if(*quotedstart == ';') {
594 594
 					quotedstart++;
595 595
 					quotedsize--;
596
-				} else if(*quotedstart == '\n') {
596
+				} else if((*quotedstart == '\n') || (*quotedstart == '\r')) {
597 597
 					quotedstart++;
598 598
 					quotedsize--;
599 599
 					if((*quotedstart == '\n') || (*quotedstart == '\r')) {
... ...
@@ -615,14 +728,21 @@ cli_mbox(const char *dir, int desc, unsigned int options)
615 615
 				cli_dbgmsg("cli_mbox: decoding %ld quoted-printable bytes\n", quotedsize);
616 616
 
617 617
 				m = messageCreate();
618
-				if(m == NULL)
618
+				if(m == NULL) {
619
+					if(wasAlloced)
620
+						free(start);
621
+					else
622
+						munmap(start, size);
623
+
619 624
 					return CL_EMEM;
625
+				}
620 626
 				messageSetEncoding(m, "quoted-printable");
621 627
 
622 628
 				line = NULL;
623 629
 
624 630
 				do {
625 631
 					int length = 0;
632
+					char *newline;
626 633
 
627 634
 					/*printf("%ld: ", quotedsize); fflush(stdout);*/
628 635
 
... ...
@@ -633,7 +753,10 @@ cli_mbox(const char *dir, int desc, unsigned int options)
633 633
 
634 634
 					/*printf("%d: ", length); fflush(stdout);*/
635 635
 
636
-					line = cli_realloc(line, length + 1);
636
+					newline = cli_realloc(line, length + 1);
637
+					if(newline == NULL)
638
+						break;
639
+					line = newline;
637 640
 
638 641
 					memcpy(line, quotedstart, length);
639 642
 					line[length] = '\0';
... ...
@@ -644,11 +767,13 @@ cli_mbox(const char *dir, int desc, unsigned int options)
644 644
 						break;
645 645
 
646 646
 					if((quotedsize > 0) && (*ptr == '\r')) {
647
-						ptr++;
647
+						quotedstart = ++ptr;
648
+						--quotedsize;
649
+					}
650
+					if((quotedsize > 0) && (*ptr == '\n')) {
651
+						quotedstart = ++ptr;
648 652
 						--quotedsize;
649 653
 					}
650
-					quotedstart = ++ptr;
651
-					--quotedsize;
652 654
 				} while(quotedsize > 0L);
653 655
 
654 656
 				free(line);
... ...
@@ -682,11 +807,86 @@ cli_mbox(const char *dir, int desc, unsigned int options)
682 682
 	if(ret == 0)
683 683
 		return CL_CLEAN;	/* a lie - but it gets things going */
684 684
 
685
+	cli_dbgmsg("New world - don't know what to do - fall back to old world\n");
685 686
 	/* Fall back for now */
686 687
 	lseek(desc, 0L, SEEK_SET);
687 688
 	return cli_parse_mbox(dir, desc, options);
688 689
 }
689
-#else
690
+
691
+static void
692
+create_map(const char *begin, const char *end)
693
+{
694
+	const struct wordlist {
695
+		const char *word;
696
+		int len;
697
+	} wordlist[] = {
698
+		{	"base64",		6	},
699
+		{	"quoted-printable",	16	},
700
+		{	"\nbegin ",		7	},
701
+		{	"\nFrom ",		7	},
702
+		{	NULL,			0	}
703
+	};
704
+
705
+	if(map) {
706
+		cli_warnmsg("create_map called without free_map\n");
707
+		free_map();
708
+	}
709
+	while(begin < end) {
710
+		const struct wordlist *word;
711
+
712
+		for(word = wordlist; word->word; word++) {
713
+			if((end - begin) < word->len)
714
+				continue;
715
+			if(strncasecmp(begin, word->word, word->len) == 0) {
716
+				add_to_map(begin, word->word);
717
+				break;
718
+			}
719
+		}
720
+		begin++;
721
+	}
722
+}
723
+
724
+/* To sort map, assume 'offset' is presented in sorted order */
725
+static void
726
+add_to_map(const char *offset, const char *word)
727
+{
728
+	if(map) {
729
+		tail->next = cli_malloc(sizeof(struct map));	/* FIXME: verify */
730
+		tail = tail->next;
731
+	} else
732
+		map = tail = cli_malloc(sizeof(struct map));	/* FIXME: verify */
733
+
734
+	tail->offset = offset;
735
+	tail->word = word;
736
+	tail->next = NULL;
737
+}
738
+
739
+static const char *
740
+find_in_map(const char *offset, const char *word)
741
+{
742
+	const struct map *item;
743
+
744
+	for(item = map; item; item = item->next)
745
+		if(item->offset >= offset)
746
+			if(strcasecmp(word, item->word) == 0)
747
+				return item->offset;
748
+
749
+	return NULL;
750
+}
751
+
752
+static void
753
+free_map(void)
754
+{
755
+	while(map) {
756
+		struct map *next = map->next;
757
+
758
+		free(map);
759
+		map = next;
760
+	}
761
+	map = NULL;
762
+}
763
+
764
+#else	/*!NEW_WORLD*/
690 765
 int
691 766
 cli_mbox(const char *dir, int desc, unsigned int options)
692 767
 {
... ...
@@ -711,6 +911,8 @@ cli_mbox(const char *dir, int desc, unsigned int options)
711 711
  * TODO: ensure parseEmailHeaders is always called before parseEmailBody
712 712
  * TODO: create parseEmail which calls parseEmailHeaders then parseEmailBody
713 713
  * TODO: Look into TNEF. Is there anything that needs to be done here?
714
+ * TODO: Handle unepected NUL bytes in header lines which stop strcmp()s:
715
+ *	e.g. \0Content-Type: application/binary;
714 716
  */
715 717
 static int
716 718
 cli_parse_mbox(const char *dir, int desc, unsigned int options)
... ...
@@ -718,7 +920,7 @@ cli_parse_mbox(const char *dir, int desc, unsigned int options)
718 718
 	int retcode, i;
719 719
 	message *body;
720 720
 	FILE *fd;
721
-	char buffer[LINE_LENGTH + 1];
721
+	char buffer[RFC2821LENGTH + 1];
722 722
 #ifdef HAVE_BACKTRACE
723 723
 	void (*segv)(int);
724 724
 #endif
... ...
@@ -728,7 +930,11 @@ cli_parse_mbox(const char *dir, int desc, unsigned int options)
728 728
 	int tmpfd;
729 729
 #endif
730 730
 
731
+#ifdef	NEW_WORLD
732
+	cli_dbgmsg("fall back to old world\n");
733
+#else
731 734
 	cli_dbgmsg("in mbox()\n");
735
+#endif
732 736
 
733 737
 	i = dup(desc);
734 738
 	if((fd = fdopen(i, "rb")) == NULL) {
... ...
@@ -806,7 +1012,7 @@ cli_parse_mbox(const char *dir, int desc, unsigned int options)
806 806
 	 * message is stopped, and giving a better indication of which message
807 807
 	 * within the mailbox is infected
808 808
 	 */
809
-	if(strncmp(buffer, "From ", 5) == 0) {
809
+	if((strncmp(buffer, "From ", 5) == 0) && isalnum(buffer[5])) {
810 810
 		/*
811 811
 		 * Have been asked to check a UNIX style mbox file, which
812 812
 		 * may contain more than one e-mail message to decode
... ...
@@ -845,7 +1051,7 @@ cli_parse_mbox(const char *dir, int desc, unsigned int options)
845 845
 
846 846
 		do {
847 847
 			cli_chomp(buffer);
848
-			if(lastLineWasEmpty && (strncmp(buffer, "From ", 5) == 0)) {
848
+			if(lastLineWasEmpty && (strncmp(buffer, "From ", 5) == 0) && isalnum(buffer[5])) {
849 849
 				cli_dbgmsg("Deal with email number %d\n", messagenumber++);
850 850
 				/*
851 851
 				 * End of a message in the mail box
... ...
@@ -882,9 +1088,9 @@ cli_parse_mbox(const char *dir, int desc, unsigned int options)
882 882
 				 * Fast track visa to uudecode.
883 883
 				 * TODO: binhex, yenc
884 884
 				 */
885
-				if(uufasttrack(m, buffer, dir, fd) < 0)
885
+				if(uudecodeFile(m, buffer, dir, fd) < 0)
886 886
 					if(messageAddStr(m, buffer) < 0)
887
-					    break;
887
+						break;
888 888
 			} else
889 889
 				if(messageAddStr(m, buffer) < 0)
890 890
 					break;
... ...
@@ -970,7 +1176,7 @@ parseEmailFile(FILE *fin, const table_t *rfc821, const char *firstLine, const ch
970 970
 	int commandNumber = -1;
971 971
 	char *fullline = NULL, *boundary = NULL;
972 972
 	size_t fulllinelength = 0;
973
-	char buffer[LINE_LENGTH+1];
973
+	char buffer[RFC2821LENGTH + 1];
974 974
 
975 975
 	cli_dbgmsg("parseEmailFile\n");
976 976
 
... ...
@@ -1005,7 +1211,7 @@ parseEmailFile(FILE *fin, const table_t *rfc821, const char *firstLine, const ch
1005 1005
 			boundary = NULL;
1006 1006
 		}
1007 1007
 		if(inHeader) {
1008
-			cli_dbgmsg("parseEmailFile: check '%s' contMarker %d fullline 0x%p\n",
1008
+			cli_dbgmsg("parseEmailFile: check '%s' contMarker %d fullline %p\n",
1009 1009
 				buffer ? buffer : "", (int)contMarker, fullline);
1010 1010
 			if(line && isspace(line[0])) {
1011 1011
 				char copy[sizeof(buffer)];
... ...
@@ -1060,12 +1266,12 @@ parseEmailFile(FILE *fin, const table_t *rfc821, const char *firstLine, const ch
1060 1060
 				int lookahead;
1061 1061
 
1062 1062
 				if(fullline == NULL) {
1063
-					char cmd[LINE_LENGTH + 1], out[LINE_LENGTH + 1];
1063
+					char cmd[RFC2821LENGTH + 1], out[RFC2821LENGTH + 1];
1064 1064
 
1065 1065
 					/*
1066 1066
 					 * Continuation of line we're ignoring?
1067 1067
 					 */
1068
-					if((line[0] == '\t') || (line[0] == ' ') || contMarker) {
1068
+					if(isblank(line[0])) {
1069 1069
 						contMarker = continuationMarker(line);
1070 1070
 						continue;
1071 1071
 					}
... ...
@@ -1098,7 +1304,10 @@ parseEmailFile(FILE *fin, const table_t *rfc821, const char *firstLine, const ch
1098 1098
 					fulllinelength = strlen(line) + 1;
1099 1099
 				} else if(line != NULL) {
1100 1100
 					fulllinelength += strlen(line);
1101
-					fullline = cli_realloc(fullline, fulllinelength);
1101
+					ptr = cli_realloc(fullline, fulllinelength);
1102
+					if(ptr == NULL)
1103
+						continue;
1104
+					fullline = ptr;
1102 1105
 					strcat(fullline, line);
1103 1106
 				}
1104 1107
 
... ...
@@ -1123,7 +1332,7 @@ parseEmailFile(FILE *fin, const table_t *rfc821, const char *firstLine, const ch
1123 1123
 					 *
1124 1124
 					 * Add all the arguments on the line
1125 1125
 					 */
1126
-					if((lookahead == '\t') || (lookahead == ' '))
1126
+					if(isblank(lookahead))
1127 1127
 						continue;
1128 1128
 				}
1129 1129
 
... ...
@@ -1154,7 +1363,7 @@ parseEmailFile(FILE *fin, const table_t *rfc821, const char *firstLine, const ch
1154 1154
 			 * Fast track visa to uudecode.
1155 1155
 			 * TODO: binhex, yenc
1156 1156
 			 */
1157
-			if(uufasttrack(ret, line, dir, fin) < 0)
1157
+			if(uudecodeFile(ret, line, dir, fin) < 0)
1158 1158
 				if(messageAddStr(ret, line) < 0)
1159 1159
 					break;
1160 1160
 		} else
... ...
@@ -1246,12 +1455,12 @@ parseEmailHeaders(const message *m, const table_t *rfc821)
1246 1246
 				int quotes;
1247 1247
 
1248 1248
 				if(fullline == NULL) {
1249
-					char cmd[LINE_LENGTH + 1];
1249
+					char cmd[RFC2821LENGTH + 1];
1250 1250
 
1251 1251
 					/*
1252 1252
 					 * Continuation of line we're ignoring?
1253 1253
 					 */
1254
-					if((buffer[0] == '\t') || (buffer[0] == ' '))
1254
+					if(isblank(buffer[0]))
1255 1255
 						continue;
1256 1256
 
1257 1257
 					/*
... ...
@@ -1284,7 +1493,10 @@ parseEmailHeaders(const message *m, const table_t *rfc821)
1284 1284
 					fulllinelength = strlen(buffer) + 1;
1285 1285
 				} else if(buffer) {
1286 1286
 					fulllinelength += strlen(buffer);
1287
-					fullline = cli_realloc(fullline, fulllinelength);
1287
+					ptr = cli_realloc(fullline, fulllinelength);
1288
+					if(ptr == NULL)
1289
+						continue;
1290
+					fullline = ptr;
1288 1291
 					strcat(fullline, buffer);
1289 1292
 				}
1290 1293
 
... ...
@@ -1298,11 +1510,8 @@ parseEmailHeaders(const message *m, const table_t *rfc821)
1298 1298
 					 *
1299 1299
 					 * Add all the arguments on the line
1300 1300
 					 */
1301
-					switch(lineGetData(t->t_next->t_line)[0]) {
1302
-						case ' ':
1303
-						case '\t':
1304
-							continue;
1305
-					}
1301
+					if(isblank(lineGetData(t->t_next->t_line)[0]))
1302
+						continue;
1306 1303
 
1307 1304
 				quotes = 0;
1308 1305
 				for(qptr = fullline; *qptr; qptr++)
... ...
@@ -1541,19 +1750,11 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t
1541 1541
 					if(boundaryStart(lineGetData(t_line->t_line), boundary))
1542 1542
 						break;
1543 1543
 					/*
1544
-					 * Found a uuencoded/binhex file before
1544
+					 * Found a binhex file before
1545 1545
 					 *	the first multipart
1546 1546
 					 * TODO: check yEnc
1547 1547
 					 */
1548
-					if(uuencodeBegin(mainMessage) == t_line) {
1549
-						if(messageGetEncoding(mainMessage) == NOENCODING) {
1550
-							messageSetEncoding(mainMessage, "x-uuencode");
1551
-							fb = messageToFileblob(mainMessage, dir);
1552
-
1553
-							if(fb)
1554
-								fileblobDestroy(fb);
1555
-						}
1556
-					} else if(binhexBegin(mainMessage) == t_line) {
1548
+					if(binhexBegin(mainMessage) == t_line) {
1557 1549
 						if(messageGetEncoding(mainMessage) == NOENCODING) {
1558 1550
 							messageSetEncoding(mainMessage, "x-binhex");
1559 1551
 							fb = messageToFileblob(mainMessage, dir);
... ...
@@ -1588,7 +1789,7 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t
1588 1588
 				mimeType = NOMIME;
1589 1589
 				/*
1590 1590
 				 * The break means that we will still
1591
-				 * check if the file contains a uuencoded file
1591
+				 * check if the file contains a yEnc/binhex file
1592 1592
 				 */
1593 1593
 				break;
1594 1594
 			}
... ...
@@ -1639,12 +1840,12 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t
1639 1639
 					cli_dbgmsg("Empty part\n");
1640 1640
 					/*
1641 1641
 					 * Remove this part unless there's
1642
-					 * a uuencoded portion somewhere in
1642
+					 * a binhex portion somewhere in
1643 1643
 					 * the complete message that we may
1644 1644
 					 * throw away by mistake if the MIME
1645 1645
 					 * encoding information is incorrect
1646 1646
 					 */
1647
-					if(uuencodeBegin(mainMessage) == NULL) {
1647
+					if(binhexBegin(mainMessage) == NULL) {
1648 1648
 						messageDestroy(aMessage);
1649 1649
 						--multiparts;
1650 1650
 					}
... ...
@@ -1654,8 +1855,8 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t
1654 1654
 				do {
1655 1655
 					const char *line = lineGetData(t_line->t_line);
1656 1656
 
1657
-					/*cli_dbgmsg("inMimeHead %d inhead %d boundary '%s' line '%s' next '%s'\n",
1658
-						inMimeHead, inhead, boundary, line,
1657
+					/*cli_dbgmsg("multipart %d: inMimeHead %d inhead %d boundary '%s' line '%s' next '%s'\n",
1658
+						multiparts, inMimeHead, inhead, boundary, line,
1659 1659
 						t_line->t_next && t_line->t_next->t_line ? lineGetData(t_line->t_next->t_line) : "(null)");*/
1660 1660
 
1661 1661
 					if(inMimeHead) {	/* continuation line */
... ...
@@ -1778,7 +1979,7 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t
1778 1778
 
1779 1779
 						inMimeHead = FALSE;
1780 1780
 
1781
-						assert(strlen(line) <= LINE_LENGTH);
1781
+						assert(strlen(line) <= RFC2821LENGTH);
1782 1782
 
1783 1783
 						fullline = rfc822comments(line, NULL);
1784 1784
 						if(fullline == NULL)
... ...
@@ -2045,9 +2246,9 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t
2045 2045
 					case NOMIME:
2046 2046
 						cli_dbgmsg("No mime headers found in multipart part %d\n", i);
2047 2047
 						if(mainMessage) {
2048
-							if(uuencodeBegin(aMessage)) {
2049
-								cli_dbgmsg("Found uuencoded message in multipart/mixed mainMessage\n");
2050
-								messageSetEncoding(mainMessage, "x-uuencode");
2048
+							if(binhexBegin(aMessage)) {
2049
+								cli_dbgmsg("Found binhex message in multipart/mixed mainMessage\n");
2050
+								messageSetEncoding(mainMessage, "x-bunhex");
2051 2051
 								fb = messageToFileblob(mainMessage, dir);
2052 2052
 
2053 2053
 								if(fb)
... ...
@@ -2057,16 +2258,7 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t
2057 2057
 								messageDestroy(mainMessage);
2058 2058
 							mainMessage = NULL;
2059 2059
 						} else if(aMessage) {
2060
-							if(uuencodeBegin(aMessage)) {
2061
-								cli_dbgmsg("Found uuencoded message in multipart/mixed non mime part\n");
2062
-								messageSetEncoding(aMessage, "x-uuencode");
2063
-								fb = messageToFileblob(aMessage, dir);
2064
-
2065
-								if(fb)
2066
-									fileblobDestroy(fb);
2067
-								assert(aMessage == messages[i]);
2068
-								messageReset(messages[i]);
2069
-							} else if(binhexBegin(aMessage)) {
2060
+							if(binhexBegin(aMessage)) {
2070 2061
 								cli_dbgmsg("Found binhex message in multipart/mixed non mime part\n");
2071 2062
 								messageSetEncoding(aMessage, "x-binhex");
2072 2063
 								fb = messageToFileblob(aMessage, dir);
... ...
@@ -2082,8 +2274,7 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t
2082 2082
 							/*
2083 2083
 							 * No plain text version
2084 2084
 							 */
2085
-							messageAddStr(aMessage, "No plain text alternative");
2086
-						assert(messageGetBody(aMessage) != NULL);
2085
+							cli_dbgmsg("No plain text alternative");
2087 2086
 						break;
2088 2087
 					case TEXT:
2089 2088
 						dtype = messageGetDispositionType(aMessage);
... ...
@@ -2097,10 +2288,7 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t
2097 2097
 							mainMessage = NULL;
2098 2098
 							cptr = messageGetMimeSubtype(aMessage);
2099 2099
 							cli_dbgmsg("Mime subtype \"%s\"\n", cptr);
2100
-							if(uuencodeBegin(aMessage)) {
2101
-								cli_dbgmsg("Found uuencoded message in multipart/mixed text portion\n");
2102
-								messageSetEncoding(aMessage, "x-uuencode");
2103
-							} else if((tableFind(subtypeTable, cptr) == PLAIN) &&
2100
+							if((tableFind(subtypeTable, cptr) == PLAIN) &&
2104 2101
 								  (messageGetEncoding(aMessage) == NOENCODING)) {
2105 2102
 								char *filename;
2106 2103
 								/*
... ...
@@ -2265,7 +2453,7 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t
2265 2265
 						cli_warnmsg("PGP encoded attachment not scanned\n");
2266 2266
 						rc = 2;
2267 2267
 					} else
2268
-						cli_warnmsg("Unknown encryption protocol '%s' - if you believe this file contains a virus, report it to bugs@clamav.net\n");
2268
+						cli_warnmsg("Unknown encryption protocol '%s' - if you believe this file contains a virus, submit it to www.clamav.net\n", protocol);
2269 2269
 					free(protocol);
2270 2270
 				} else
2271 2271
 					cli_dbgmsg("Encryption method missing protocol name\n");
... ...
@@ -2347,7 +2535,7 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t
2347 2347
 				/* TODO */
2348 2348
 				cli_warnmsg("Attempt to send Content-type message/external-body trapped");
2349 2349
 			else
2350
-				cli_warnmsg("Unsupported message format `%s' - if you believe this file contains a virus, report it to bugs@clamav.net\n", mimeSubtype);
2350
+				cli_warnmsg("Unsupported message format `%s' - if you believe this file contains a virus, submit it to www.clamav.net\n", mimeSubtype);
2351 2351
 
2352 2352
 
2353 2353
 			if(mainMessage && (mainMessage != messageIn))
... ...
@@ -2534,21 +2722,7 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t
2534 2534
 		 */
2535 2535
 		const text *t_line;
2536 2536
 
2537
-		if((t_line = uuencodeBegin(mainMessage)) != NULL) {
2538
-			cli_dbgmsg("Found uuencoded file\n");
2539
-
2540
-			/*
2541
-			 * Main part contains uuencoded section
2542
-			 */
2543
-			messageSetEncoding(mainMessage, "x-uuencode");
2544
-
2545
-			if((fb = messageToFileblob(mainMessage, dir)) != NULL) {
2546
-				if((cptr = fileblobGetFilename(fb)) != NULL)
2547
-					cli_dbgmsg("Saving uuencoded message %s\n", cptr);
2548
-				fileblobDestroy(fb);
2549
-			}
2550
-			rc = 1;
2551
-		} else if((encodingLine(mainMessage) != NULL) &&
2537
+		if((encodingLine(mainMessage) != NULL) &&
2552 2538
 			  ((t_line = bounceBegin(mainMessage)) != NULL)) {
2553 2539
 			const text *t, *start;
2554 2540
 			/*
... ...
@@ -2571,7 +2745,7 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t
2571 2571
 			 * won't be scanned
2572 2572
 			 */
2573 2573
 			for(t = start = t_line; t; t = t->t_next) {
2574
-				char cmd[LINE_LENGTH + 1];
2574
+				char cmd[RFC2821LENGTH + 1];
2575 2575
 				const char *txt = lineGetData(t->t_line);
2576 2576
 
2577 2577
 				if(txt == NULL)
... ...
@@ -2613,8 +2787,6 @@ parseEmailBody(message *messageIn, text *textIn, const char *dir, const table_t
2613 2613
 		} else {
2614 2614
 			bool saveIt;
2615 2615
 
2616
-			cli_dbgmsg("Not found uuencoded file\n");
2617
-
2618 2616
 			if(messageGetMimeType(mainMessage) == MESSAGE)
2619 2617
 				/*
2620 2618
 				 * Quick peek, if the encapsulated
... ...
@@ -2692,7 +2864,7 @@ boundaryStart(const char *line, const char *boundary)
2692 2692
 {
2693 2693
 	char *ptr, *out;
2694 2694
 	int rc;
2695
-	char buf[LINE_LENGTH + 1];
2695
+	char buf[RFC2821LENGTH + 1];
2696 2696
 
2697 2697
 	if(line == NULL)
2698 2698
 		return 0;	/* empty line */
... ...
@@ -3268,7 +3440,7 @@ rfc2047(const char *in)
3268 3268
 		encoding = tolower(encoding);
3269 3269
 
3270 3270
 		if((encoding != 'q') && (encoding != 'b')) {
3271
-			cli_warnmsg("Unsupported RFC2047 encoding type '%c' - if you believe this file contains a virus that was missed, report it to bugs@clamav.net\n", encoding);
3271
+			cli_warnmsg("Unsupported RFC2047 encoding type '%c' - if you believe this file contains a virus, submit it to www.clamav.net\n", encoding);
3272 3272
 			free(out);
3273 3273
 			out = NULL;
3274 3274
 			break;
... ...
@@ -3390,9 +3562,11 @@ rfc1341(message *m, const char *dir)
3390 3390
 		oldfilename = (char *)messageFindArgument(m, "name");
3391 3391
 
3392 3392
 	arg = cli_malloc(10 + strlen(id) + strlen(number));
3393
-	sprintf(arg, "filename=%s%s", id, number);
3394
-	messageAddArgument(m, arg);
3395
-	free(arg);
3393
+	if(arg) {
3394
+		sprintf(arg, "filename=%s%s", id, number);
3395
+		messageAddArgument(m, arg);
3396
+		free(arg);
3397
+	}
3396 3398
 
3397 3399
 	if(oldfilename) {
3398 3400
 		cli_warnmsg("Must reset to %s\n", oldfilename);
... ...
@@ -3422,6 +3596,7 @@ rfc1341(message *m, const char *dir)
3422 3422
 		if((n == t) && ((dd = opendir(pdir)) != NULL)) {
3423 3423
 			FILE *fout;
3424 3424
 			char outname[NAME_MAX + 1];
3425
+			time_t now;
3425 3426
 
3426 3427
 			snprintf(outname, sizeof(outname) - 1, "%s/%s", dir, id);
3427 3428
 
... ...
@@ -3436,6 +3611,7 @@ rfc1341(message *m, const char *dir)
3436 3436
 				return -1;
3437 3437
 			}
3438 3438
 
3439
+			time(&now);
3439 3440
 			for(n = 1; n <= t; n++) {
3440 3441
 				char filename[NAME_MAX + 1];
3441 3442
 				const struct dirent *dent;
... ...
@@ -3456,20 +3632,31 @@ rfc1341(message *m, const char *dir)
3456 3456
 				while((dent = readdir(dd))) {
3457 3457
 #endif
3458 3458
 					FILE *fin;
3459
-					char buffer[BUFSIZ];
3459
+					char buffer[BUFSIZ], fullname[NAME_MAX + 1];
3460 3460
 					int nblanks;
3461 3461
 					extern short cli_leavetemps_flag;
3462
+					struct stat statb;
3462 3463
 
3463 3464
 					if(dent->d_ino == 0)
3464 3465
 						continue;
3465 3466
 
3466
-					if(strncmp(filename, dent->d_name, strlen(filename)) != 0)
3467
+					snprintf(fullname, sizeof(fullname) - 1,
3468
+						"%s/%s", pdir, dent->d_name);
3469
+
3470
+					if(strncmp(filename, dent->d_name, strlen(filename)) != 0) {
3471
+						if(!cli_leavetemps_flag)
3472
+							continue;
3473
+						if(stat(fullname, &statb) < 0)
3474
+							continue;
3475
+						if(now - statb.st_mtime > (time_t)(7 * 24 * 3600))
3476
+							if(unlink(fullname) >= 0)
3477
+								cli_warnmsg("removed old RFC1341 file %s\n", fullname);
3467 3478
 						continue;
3479
+					}
3468 3480
 
3469
-					sprintf(filename, "%s/%s", pdir, dent->d_name);
3470
-					fin = fopen(filename, "rb");
3481
+					fin = fopen(fullname, "rb");
3471 3482
 					if(fin == NULL) {
3472
-						cli_errmsg("Can't open '%s' for reading", filename);
3483
+						cli_errmsg("Can't open '%s' for reading", fullname);
3473 3484
 						fclose(fout);
3474 3485
 						unlink(outname);
3475 3486
 						free(id);
... ...
@@ -3496,7 +3683,7 @@ rfc1341(message *m, const char *dir)
3496 3496
 
3497 3497
 					/* don't unlink if leave temps */
3498 3498
 					if(!cli_leavetemps_flag)
3499
-						unlink(filename);
3499
+						unlink(fullname);
3500 3500
 					break;
3501 3501
 				}
3502 3502
 				rewinddir(dd);
... ...
@@ -3568,6 +3755,11 @@ checkURLs(message *m, const char *dir)
3568 3568
 	for(i = 0; i < hrefs.count; i++) {
3569 3569
 		const char *url = (const char *)hrefs.value[i];
3570 3570
 
3571
+		/*
3572
+		 * TODO: If it's an image source, it'd be nice to note beacons
3573
+		 *	where width="0" height="0", which needs support from
3574
+		 *	the HTML normalise code
3575
+		 */
3571 3576
 		if(strncasecmp("http://", url, 7) == 0) {
3572 3577
 			char *ptr;
3573 3578
 #ifdef	WITH_CURL
... ...
@@ -3588,10 +3780,21 @@ checkURLs(message *m, const char *dir)
3588 3588
 				cli_dbgmsg("URL %s already downloaded\n", url);
3589 3589
 				continue;
3590 3590
 			}
3591
+			/*
3592
+			 * What about foreign character spoofing?
3593
+			 * It would be useful be able to check if url
3594
+			 *	is the same as the text displayed, e.g.
3595
+			 *	<a href="http://dodgy.biz">www.paypal.com</a>
3596
+			 *	but that needs support from HTML normalise
3597
+			 */
3598
+			if(strchr(url, '%') && strchr(url, '@'))
3599
+				cli_warnmsg("Possible URL spoofing attempt noticed, but not yet handled (%s)\n", url);
3600
+
3591 3601
 			if(n == FOLLOWURLS) {
3592
-				cli_warnmsg("Not all URLs will be scanned\n");
3602
+				cli_warnmsg("URL %s will not be scanned\n", url);
3593 3603
 				break;
3594 3604
 			}
3605
+
3595 3606
 			(void)tableInsert(t, url, 1);
3596 3607
 			cli_dbgmsg("Downloading URL %s to be scanned\n", url);
3597 3608
 			strncpy(name, url, sizeof(name) - 1);
... ...
@@ -3619,18 +3822,12 @@ checkURLs(message *m, const char *dir)
3619 3619
 			 */
3620 3620
 			len = sizeof(cmd) - 26 - strlen(dir) - strlen(name);
3621 3621
 #ifdef	CL_DEBUG
3622
-			snprintf(cmd, sizeof(cmd) - 1, "GET -t10 %.*s >%s/%s", len, url, dir, name);
3622
+			snprintf(cmd, sizeof(cmd) - 1, "GET -t10 \"%.*s\" >%s/%s", len, url, dir, name);
3623 3623
 #else
3624
-			snprintf(cmd, sizeof(cmd) - 1, "GET -t10 %.*s >%s/%s 2>/dev/null", len, url, dir, name);
3624
+			snprintf(cmd, sizeof(cmd) - 1, "GET -t10 \"%.*s\" >%s/%s 2>/dev/null", len, url, dir, name);
3625 3625
 #endif
3626 3626
 			cmd[sizeof(cmd) - 1] = '\0';
3627 3627
 
3628
-#ifndef	WITH_CURL
3629
-			for(ptr = cmd; *ptr; ptr++)
3630
-				if(strchr(";&", *ptr))
3631
-					*ptr = '_';
3632
-#endif
3633
-
3634 3628
 			cli_dbgmsg("%s\n", cmd);
3635 3629
 #ifdef	CL_THREAD_SAFE
3636 3630
 			pthread_mutex_lock(&system_mutex);
... ...
@@ -3666,6 +3863,16 @@ checkURLs(message *m, const char *dir)
3666 3666
 	html_tag_arg_free(&hrefs);
3667 3667
 }
3668 3668
 
3669
+/*
3670
+ * Includes some Win32 patches by Gianluigi Tiesi <sherpya@netfarm.it>
3671
+ *
3672
+ * FIXME: Often WMF exploits work by sending people an email directing them
3673
+ *	to a page which displays a picture containing the exploit. This is not
3674
+ *	currently found, since only the HTML on the referred page is downloaded.
3675
+ *	It would be useful to scan the HTML for references to pictures and
3676
+ *	download them for scanning. But that will hit performance so there is
3677
+ *	an issue here.
3678
+ */
3669 3679
 #ifdef	WITH_CURL
3670 3680
 static void *
3671 3681
 #ifdef	CL_THREAD_SAFE
... ...
@@ -3687,17 +3894,20 @@ getURL(struct arg *arg)
3687 3687
 	const char *filename = arg->filename;
3688 3688
 	char fout[NAME_MAX + 1];
3689 3689
 #ifdef	CURLOPT_ERRORBUFFER
3690
-	char errorbuffer[128];
3690
+	char errorbuffer[CURL_ERROR_SIZE];
3691
+#elif	(LIBCURL_VERSION_NUM >= 0x070C00)
3692
+	CURLcode res = CURLE_OK;
3691 3693
 #endif
3692 3694
 
3693 3695
 #ifdef	CL_THREAD_SAFE
3694 3696
 	pthread_mutex_lock(&init_mutex);
3695 3697
 #endif
3696 3698
 	if(!initialised) {
3697
-		if(curl_global_init(CURL_GLOBAL_NOTHING) != 0) {
3699
+		if(curl_global_init(CURL_GLOBAL_ALL) != 0) {
3698 3700
 #ifdef	CL_THREAD_SAFE
3699 3701
 			pthread_mutex_unlock(&init_mutex);
3700 3702
 #endif
3703
+			cli_errmsg("curl_global_init failed");
3701 3704
 			return NULL;
3702 3705
 		}
3703 3706
 		initialised = 1;
... ...
@@ -3708,17 +3918,22 @@ getURL(struct arg *arg)
3708 3708
 
3709 3709
 	/* easy isn't the word I'd use... */
3710 3710
 	curl = curl_easy_init();
3711
-	if(curl == NULL)
3711
+	if(curl == NULL) {
3712
+		cli_errmsg("curl_easy_init failed");
3712 3713
 		return NULL;
3714
+	}
3713 3715
 
3714 3716
 	(void)curl_easy_setopt(curl, CURLOPT_USERAGENT, "www.clamav.net");
3715 3717
 
3716
-	if(curl_easy_setopt(curl, CURLOPT_URL, url) != 0)
3718
+	if(curl_easy_setopt(curl, CURLOPT_URL, url) != 0) {
3719
+		cli_errmsg("%s: curl_easy_setopt failed", url);
3720
+		curl_easy_cleanup(curl);
3717 3721
 		return NULL;
3722
+	}
3718 3723
 
3719 3724
 	snprintf(fout, NAME_MAX, "%s/%s", dir, filename);
3720 3725
 
3721
-	fp = fopen(fout, "w");
3726
+	fp = fopen(fout, "wb");
3722 3727
 
3723 3728
 	if(fp == NULL) {
3724 3729
 		cli_errmsg("Can't open '%s' for writing", fout);
... ...
@@ -3765,10 +3980,6 @@ getURL(struct arg *arg)
3765 3765
 	 */
3766 3766
 	curl_easy_setopt(curl, CURLOPT_USERPWD, "username:password");
3767 3767
 
3768
-#ifdef	CURLOPT_ERRORBUFFER
3769
-	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
3770
-#endif
3771
-
3772 3768
 	/*
3773 3769
 	 * FIXME: valgrind reports "pthread_mutex_unlock: mutex is not locked"
3774 3770
 	 * from gethostbyaddr_r within this. It may be a bug in libcurl
... ...
@@ -3777,24 +3988,31 @@ getURL(struct arg *arg)
3777 3777
 	 * Conditional jump or move depends on uninitialised value(s) and
3778 3778
 	 * quit. But the program seems to work OK without valgrind...
3779 3779
 	 * Perhaps Curl_resolv() isn't thread safe?
3780
+	 *
3781
+	 * I have seen segfaults in version 7.12.3. Version 7.14 seems OK.
3780 3782
 	 */
3781 3783
 	/*
3782 3784
 	 * On some C libraries (notably with FC3, glibc-2.3.3-74) you get a
3783
-	 * memory leak * here in getaddrinfo(), see
3785
+	 * memory leak here in getaddrinfo(), see
3784 3786
 	 *	https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=139559
3785 3787
 	 */
3786
-
3787
-	if(curl_easy_perform(curl) != CURLE_OK) {
3788 3788
 #ifdef	CURLOPT_ERRORBUFFER
3789
+	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
3790
+
3791
+	if(curl_easy_perform(curl) != CURLE_OK)
3789 3792
 		cli_warnmsg("URL %s failed to download: %s\n", url, errorbuffer);
3793
+#elif	(LIBCURL_VERSION_NUM >= 0x070C00)
3794
+	if((res = curl_easy_perform(curl)) != CURLE_OK)
3795
+		cli_warnmsg("URL %s failed to download: %s\n", url,
3796
+			curl_easy_strerror(res));
3790 3797
 #else
3798
+	if(curl_easy_perform(curl) != CURLE_OK)
3791 3799
 		cli_warnmsg("URL %s failed to download\n", url);
3792 3800
 #endif
3793
-	}
3794 3801
 
3795 3802
 	fclose(fp);
3796
-	curl_slist_free_all(headers);
3797 3803
 	curl_easy_cleanup(curl);
3804
+	curl_slist_free_all(headers);
3798 3805
 
3799 3806
 	return NULL;
3800 3807
 }
... ...
@@ -3866,52 +4084,6 @@ usefulHeader(int commandNumber, const char *cmd)
3866 3866
 }
3867 3867
 
3868 3868
 /*
3869
- * Save the uuencoded part of the file as it is read in since there's no need
3870
- * to include it in the parse tree. Saves memory and parse time.
3871
- * Return < 0 for failure
3872
- */
3873
-static int
3874
-uufasttrack(message *m, const char *firstline, const char *dir, FILE *fin)
3875
-{
3876
-	fileblob *fb = fileblobCreate();
3877
-	char buffer[LINE_LENGTH + 1];
3878
-	char *filename = cli_strtok(firstline, 2, " ");
3879
-
3880
-	if(filename == NULL)
3881
-		return -1;
3882
-
3883
-	fileblobSetFilename(fb, dir, filename);
3884
-	cli_dbgmsg("Fast track uudecode %s\n", filename);
3885
-	free(filename);
3886
-
3887
-	while(fgets(buffer, sizeof(buffer) - 1, fin) != NULL) {
3888
-		unsigned char data[1024];
3889
-		const unsigned char *uptr;
3890
-		size_t len;
3891
-
3892
-		cli_chomp(buffer);
3893
-		if(strcasecmp(buffer, "end") == 0)
3894
-			break;
3895
-		if(buffer[0] == '\0')
3896
-			break;
3897
-
3898
-		uptr = decodeLine(m, UUENCODE, buffer, data, sizeof(data));
3899
-		if(uptr == NULL)
3900
-			break;
3901
-
3902
-		len = (size_t)(uptr - data);
3903
-		if((len > 62) || (len == 0))
3904
-			break;
3905
-
3906
-		if(fileblobAddData(fb, data, len) < 0)
3907
-			break;
3908
-	}
3909
-
3910
-	fileblobDestroy(fb);
3911
-	return 1;
3912
-}
3913
-
3914
-/*
3915 3869
  * Like fgets but cope with end of line by "\n", "\r\n", "\n\r", "\r"
3916 3870
  */
3917 3871
 static char *
... ...
@@ -3943,7 +4115,7 @@ getline_from_mbox(char *buffer, size_t len, FILE *fin)
3943 3943
 					ungetc(c, fin);
3944 3944
 				break;
3945 3945
 			default:
3946
-				*buffer++ = c;
3946
+				*buffer++ = (char)c;
3947 3947
 				continue;
3948 3948
 			case EOF:
3949 3949
 				break;
... ...
@@ -3955,56 +4127,17 @@ getline_from_mbox(char *buffer, size_t len, FILE *fin)
3955 3955
 				break;
3956 3956
 		}
3957 3957
 		break;
3958
-	} while(--len > 0);
3958
+	} while(--len > 1);
3959 3959
 
3960 3960
 	if(len == 0) {
3961
-		/* probably, the email breaks RFC821 */
3962
-		cli_dbgmsg("getline_from_mbox: buffer overflow stopped\n");
3961
+		/* the email probably breaks RFC821 */
3962
+		cli_warnmsg("getline_from_mbox: buffer overflow stopped - line lost\n");
3963 3963
 		return NULL;
3964 3964
 	}
3965
+	if(len == 1)
3966
+		/* over flows will have appear on separate lines */
3967
+		cli_dbgmsg("getline_from_mbox: buffer overflow stopped - line recovered\n");
3965 3968
 	*buffer = '\0';
3966 3969
 
3967 3970
 	return ret;
3968 3971
 }
3969
-
3970
-#ifdef	NEW_WORLD
3971
-/*
3972
- * like cli_memstr - but returns the location of the match
3973
- * FIXME: need a case insensitive version
3974
- */
3975
-static const char *
3976
-cli_pmemstr(const char *haystack, size_t hs, const char *needle, size_t ns)
3977
-{
3978
-	const char *pt, *hay;
3979
-	size_t n;
3980
-
3981
-	if(haystack == needle)
3982
-		return haystack;
3983
-
3984
-	if(hs < ns)
3985
-		return NULL;
3986
-
3987
-	if(memcmp(haystack, needle, ns) == 0)
3988
-		return haystack;
3989
-
3990
-	pt = hay = haystack;
3991
-	n = hs;
3992
-
3993
-	while((pt = memchr(hay, needle[0], n)) != NULL) {
3994
-		n -= (int) pt - (int) hay;
3995
-		if(n < ns)
3996
-			break;
3997
-
3998
-		if(memcmp(pt, needle, ns) == 0)
3999
-			return pt;
4000
-
4001
-		if(hay == pt) {
4002
-			n--;
4003
-			hay++;
4004
-		} else
4005
-			hay = pt;
4006
-	}
4007
-
4008
-	return NULL;
4009
-}
4010
-#endif
... ...
@@ -74,8 +74,6 @@ pthread_mutex_t cli_gentemp_mutex = PTHREAD_MUTEX_INITIALIZER;
74 74
 
75 75
 #define CL_FLEVEL 7 /* don't touch it */
76 76
 
77
-#define MAX_ALLOCATION 134217728
78
-
79 77
 short cli_debug_flag = 0, cli_leavetemps_flag = 0;
80 78
 
81 79
 static unsigned char oldmd5buff[16] = { 16, 38, 97, 12, 8, 4, 72, 196, 217, 144, 33, 124, 18, 11, 17, 253 };
... ...
@@ -306,15 +304,15 @@ void *cli_malloc(size_t size)
306 306
 	void *alloc;
307 307
 
308 308
 
309
-    if(!size || size > MAX_ALLOCATION) {
310
-	cli_errmsg("Attempt to allocate %d bytes. Please report to bugs@clamav.net\n", size);
309
+    if(!size || size > CLI_MAX_ALLOCATION) {
310
+	cli_errmsg("Attempt to allocate %u bytes. Please report to bugs@clamav.net\n", size);
311 311
 	return NULL;
312 312
     }
313 313
 
314 314
     alloc = malloc(size);
315 315
 
316 316
     if(!alloc) {
317
-	cli_errmsg("cli_malloc(): Can't allocate memory (%d bytes).\n", size);
317
+	cli_errmsg("cli_malloc(): Can't allocate memory (%u bytes).\n", size);
318 318
 	perror("malloc_problem");
319 319
 	/* _exit(1); */
320 320
 	return NULL;
... ...
@@ -326,15 +324,15 @@ void *cli_calloc(size_t nmemb, size_t size)
326 326
 	void *alloc;
327 327
 
328 328
 
329
-    if(!size || size > MAX_ALLOCATION) {
330
-	cli_errmsg("Attempt to allocate %d bytes. Please report to bugs@clamav.net\n", size);
329
+    if(!size || size > CLI_MAX_ALLOCATION) {
330
+	cli_errmsg("Attempt to allocate %u bytes. Please report to bugs@clamav.net\n", size);
331 331
 	return NULL;
332 332
     }
333 333
 
334 334
     alloc = calloc(nmemb, size);
335 335
 
336 336
     if(!alloc) {
337
-	cli_errmsg("cli_calloc(): Can't allocate memory (%d bytes).\n", nmemb * size);
337
+	cli_errmsg("cli_calloc(): Can't allocate memory (%u bytes).\n", nmemb * size);
338 338
 	perror("calloc_problem");
339 339
 	/* _exit(1); */
340 340
 	return NULL;
... ...
@@ -346,15 +344,15 @@ void *cli_realloc(void *ptr, size_t size)
346 346
 	void *alloc;
347 347
 
348 348
 
349
-    if(!size || size > MAX_ALLOCATION) {
350
-	cli_errmsg("Attempt to allocate %d bytes. Please report to bugs@clamav.net\n", size);
349
+    if(!size || size > CLI_MAX_ALLOCATION) {
350
+	cli_errmsg("Attempt to allocate %u bytes. Please report to bugs@clamav.net\n", size);
351 351
 	return NULL;
352 352
     }
353 353
 
354 354
     alloc = realloc(ptr, size);
355 355
 
356 356
     if(!alloc) {
357
-	cli_errmsg("cli_realloc(): Can't re-allocate memory to %d byte.\n", size);
357
+	cli_errmsg("cli_realloc(): Can't re-allocate memory to %u byte.\n", size);
358 358
 	perror("realloc_problem");
359 359
 	return NULL;
360 360
     } else return alloc;
... ...
@@ -700,6 +698,10 @@ int cli_bitset_test(bitset_t *bs, unsigned long bit_offset)
700 700
 	
701 701
 	char_offset = bit_offset / BITS_PER_CHAR;
702 702
 	bit_offset = bit_offset % BITS_PER_CHAR;
703
-	
703
+
704
+	if (char_offset >= bs->length) {
705
+		return FALSE;
706
+	}
707
+
704 708
 	return (bs->bitset[char_offset] & ((unsigned char)1 << bit_offset));
705 709
 }
... ...
@@ -27,6 +27,12 @@
27 27
     (bb_size > 0 && sb_size > 0 && sb_size <= bb_size	\
28 28
      && sb >= bb && sb + sb_size <= bb + bb_size && sb + sb_size > bb)
29 29
 
30
+#define CLI_ISCONTAINED2(bb, bb_size, sb, sb_size)	\
31
+    (bb_size > 0 && sb_size >= 0 && sb_size <= bb_size	\
32
+     && sb >= bb && sb + sb_size <= bb + bb_size && sb + sb_size >= bb)
33
+
34
+#define CLI_MAX_ALLOCATION 134217728
35
+
30 36
 typedef struct bitset_tag {
31 37
     unsigned char *bitset;
32 38
     unsigned long length;
... ...
@@ -315,16 +315,18 @@ int cli_scanpe(int desc, const char **virname, unsigned long int *scanned, const
315 315
     }
316 316
 
317 317
     nsections = EC16(file_hdr.NumberOfSections);
318
-    if(nsections < 1) {
318
+    if(nsections < 1 || nsections > 99) {
319 319
 	if(DETECT_BROKEN) {
320 320
 	    if(virname)
321 321
 		*virname = "Broken.Executable";
322 322
 	    return CL_VIRUS;
323 323
 	}
324
-	cli_warnmsg("PE file contains no sections\n");
324
+	if(nsections)
325
+	    cli_warnmsg("PE file contains %d sections\n", nsections);
326
+	else
327
+	    cli_warnmsg("PE file contains no sections\n");
325 328
 	return CL_CLEAN;
326 329
     }
327
-
328 330
     cli_dbgmsg("NumberOfSections: %d\n", nsections);
329 331
 
330 332
     timestamp = (time_t) EC32(file_hdr.TimeDateStamp);
... ...
@@ -591,7 +593,7 @@ int cli_scanpe(int desc, const char **virname, unsigned long int *scanned, const
591 591
 		    uint32_t newesi, newedi, newebx, newedx;
592 592
 
593 593
 		if(limits && limits->maxfilesize && (ssize > limits->maxfilesize || dsize > limits->maxfilesize)) {
594
-		    cli_dbgmsg("FSG: Sizes exceeded (ssize: %d, dsize: %d, max: %lu)\n", ssize, dsize , limits->maxfilesize);
594
+		    cli_dbgmsg("FSG: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize , limits->maxfilesize);
595 595
 		    free(section_hdr);
596 596
 		    if(BLOCKMAX) {
597 597
 			*virname = "PE.FSG.ExceededFileSize";
... ...
@@ -745,7 +747,7 @@ int cli_scanpe(int desc, const char **virname, unsigned long int *scanned, const
745 745
 
746 746
 
747 747
 		if(limits && limits->maxfilesize && (ssize > limits->maxfilesize || dsize > limits->maxfilesize)) {
748
-		    cli_dbgmsg("FSG: Sizes exceeded (ssize: %d, dsize: %d, max: %lu)\n", ssize, dsize, limits->maxfilesize);
748
+		    cli_dbgmsg("FSG: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize, limits->maxfilesize);
749 749
 		    free(section_hdr);
750 750
 		    if(BLOCKMAX) {
751 751
 			*virname = "PE.FSG.ExceededFileSize";
... ...
@@ -965,7 +967,7 @@ int cli_scanpe(int desc, const char **virname, unsigned long int *scanned, const
965 965
 		}
966 966
 
967 967
 		if(limits && limits->maxfilesize && (ssize > limits->maxfilesize || dsize > limits->maxfilesize)) {
968
-		    cli_dbgmsg("FSG: Sizes exceeded (ssize: %d, dsize: %d, max: %lu)\n", ssize, dsize, limits->maxfilesize);
968
+		    cli_dbgmsg("FSG: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize, limits->maxfilesize);
969 969
 		    free(section_hdr);
970 970
 		    if(BLOCKMAX) {
971 971
 			*virname = "PE.FSG.ExceededFileSize";
... ...
@@ -1155,7 +1157,7 @@ int cli_scanpe(int desc, const char **virname, unsigned long int *scanned, const
1155 1155
 	    dsize = EC32(section_hdr[i].VirtualSize) + EC32(section_hdr[i + 1].VirtualSize);
1156 1156
 
1157 1157
 	    if(limits && limits->maxfilesize && (ssize > limits->maxfilesize || dsize > limits->maxfilesize)) {
1158
-		cli_dbgmsg("UPX: Sizes exceeded (ssize: %d, dsize: %d, max: %lu)\n", ssize, dsize , limits->maxfilesize);
1158
+		cli_dbgmsg("UPX: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize , limits->maxfilesize);
1159 1159
 		free(section_hdr);
1160 1160
 		if(BLOCKMAX) {
1161 1161
 		    *virname = "PE.UPX.ExceededFileSize";
... ...
@@ -1177,6 +1179,13 @@ int cli_scanpe(int desc, const char **virname, unsigned long int *scanned, const
1177 1177
 		return CL_EMEM;
1178 1178
 	    }
1179 1179
 
1180
+	    if(dsize > CLI_MAX_ALLOCATION) {
1181
+		cli_errmsg("UPX: Too big value of dsize\n");
1182
+		free(section_hdr);
1183
+		free(src);
1184
+		return CL_EMEM;
1185
+	    }
1186
+
1180 1187
 	    if((dest = (char *) cli_calloc(dsize + 1024 + nsections * 40, sizeof(char))) == NULL) {
1181 1188
 		free(section_hdr);
1182 1189
 		free(src);
... ...
@@ -1349,7 +1358,7 @@ int cli_scanpe(int desc, const char **virname, unsigned long int *scanned, const
1349 1349
 	    dsize = max - min;
1350 1350
 
1351 1351
 	    if(limits && limits->maxfilesize && dsize > limits->maxfilesize) {
1352
-		cli_dbgmsg("Petite: Size exceeded (dsize: %d, max: %lu)\n", dsize, limits->maxfilesize);
1352
+		cli_dbgmsg("Petite: Size exceeded (dsize: %u, max: %lu)\n", dsize, limits->maxfilesize);
1353 1353
 		free(section_hdr);
1354 1354
 		if(BLOCKMAX) {
1355 1355
 		    *virname = "PE.Petite.ExceededFileSize";
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
2
+ *  Copyright (C) 2002 - 2006 Tomasz Kojm <tkojm@clamav.net>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -1350,7 +1350,7 @@ static int cli_scanmail(int desc, const char **virname, unsigned long int *scann
1350 1350
 
1351 1351
 static int cli_scanraw(int desc, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec, cli_file_t type)
1352 1352
 {
1353
-	int typerec = 0, ret = CL_CLEAN;
1353
+	int typerec = 0, ret = CL_CLEAN, nret = CL_CLEAN;
1354 1354
 
1355 1355
 
1356 1356
     if(type == CL_TYPE_UNKNOWN_TEXT)
... ...
@@ -1375,17 +1375,18 @@ static int cli_scanraw(int desc, const char **virname, unsigned long int *scanne
1375 1375
 	switch(ret) {
1376 1376
 	    case CL_TYPE_HTML:
1377 1377
 		if(SCAN_HTML)
1378
-		    if(cli_scanhtml(desc, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS)
1378
+		    if((nret = cli_scanhtml(desc, virname, scanned, root, limits, options, arec, mrec)) == CL_VIRUS)
1379 1379
 			return CL_VIRUS;
1380 1380
 		    break;
1381 1381
 
1382 1382
 	    case CL_TYPE_MAIL:
1383 1383
 		if(SCAN_MAIL)
1384
-		    if(cli_scanmail(desc, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS)
1384
+		    if((nret = cli_scanmail(desc, virname, scanned, root, limits, options, arec, mrec)) == CL_VIRUS)
1385 1385
 			return CL_VIRUS;
1386 1386
 		break;
1387 1387
 	}
1388 1388
 	ret == CL_TYPE_MAIL ? mrec-- : arec--;
1389
+	ret = nret;
1389 1390
     }
1390 1391
 
1391 1392
     return ret;
... ...
@@ -1549,7 +1550,7 @@ int cli_magic_scandesc(int desc, const char **virname, unsigned long int *scanne
1549 1549
     type == CL_TYPE_MAIL ? mrec-- : arec--;
1550 1550
 
1551 1551
     if(type != CL_TYPE_DATA && ret != CL_VIRUS && !root->sdb) {
1552
-	if((ret = cli_scanraw(desc, virname, scanned, root, limits, options, arec, mrec, type) == CL_VIRUS))
1552
+	if(cli_scanraw(desc, virname, scanned, root, limits, options, arec, mrec, type) == CL_VIRUS)
1553 1553
 	    return CL_VIRUS;
1554 1554
     }
1555 1555
 
... ...
@@ -24,7 +24,7 @@
24 24
 #include "clamav-config.h"
25 25
 #endif
26 26
 
27
-static	char	const	rcsid[] = "$Id: tnef.c,v 1.26 2005/07/11 15:01:40 nigelhorne Exp $";
27
+static	char	const	rcsid[] = "$Id: tnef.c,v 1.31 2006/03/14 11:39:43 nigelhorne Exp $";
28 28
 
29 29
 #include <stdio.h>
30 30
 #include <fcntl.h>
... ...
@@ -38,8 +38,8 @@ static	char	const	rcsid[] = "$Id: tnef.c,v 1.26 2005/07/11 15:01:40 nigelhorne E
38 38
 #endif
39 39
 #include "blob.h"
40 40
 
41
-static	int	tnef_message(FILE *fp, uint16_t type, uint16_t tag, int32_t length);
42
-static	int	tnef_attachment(FILE *fp, uint16_t type, uint16_t tag, int32_t length, const char *dir, fileblob **fbref);
41
+static	int	tnef_message(FILE *fp, uint16_t type, uint16_t tag, int32_t length, off_t fsize);
42
+static	int	tnef_attachment(FILE *fp, uint16_t type, uint16_t tag, int32_t length, const char *dir, fileblob **fbref, off_t fsize);
43 43
 static	int	tnef_header(FILE *fp, uint8_t *part, uint16_t *type, uint16_t *tag, int32_t *length);
44 44
 
45 45
 #define	TNEF_SIGNATURE	0x223E9f78
... ...
@@ -73,9 +73,17 @@ cli_tnef(const char *dir, int desc)
73 73
 	fileblob *fb;
74 74
 	int i, ret, alldone;
75 75
 	FILE *fp;
76
+	off_t fsize;
77
+	struct stat statb;
76 78
 
77 79
 	lseek(desc, 0L, SEEK_SET);
78 80
 
81
+	if(fstat(desc, &statb) < 0) {
82
+		cli_errmsg("Can't fstat descriptor %d\n", desc);
83
+		return CL_EIO;
84
+	}
85
+	fsize = statb.st_size;
86
+
79 87
 	i = dup(desc);
80 88
 	if((fp = fdopen(i, "rb")) == NULL) {
81 89
 		cli_errmsg("Can't open descriptor %d\n", desc);
... ...
@@ -102,9 +110,9 @@ cli_tnef(const char *dir, int desc)
102 102
 	alldone = 0;
103 103
 
104 104
 	do {
105
-		uint8_t part;
106
-		uint16_t type, tag;
107
-		int32_t length;
105
+		uint8_t part = 0;
106
+		uint16_t type = 0, tag = 0;
107
+		int32_t length = 0;
108 108
 
109 109
 		switch(tnef_header(fp, &part, &type, &tag, &length)) {
110 110
 			case 0:
... ...
@@ -121,6 +129,13 @@ cli_tnef(const char *dir, int desc)
121 121
 				alldone = 1;
122 122
 				break;
123 123
 		}
124
+		if(length == 0)
125
+			continue;
126
+		if(length < 0) {
127
+			cli_warnmsg("Corrupt TNEF header detected - length %d\n", length);
128
+			ret = CL_EFORMAT;
129
+			break;
130
+		}
124 131
 		if(alldone)
125 132
 			break;
126 133
 		switch(part) {
... ...
@@ -131,7 +146,7 @@ cli_tnef(const char *dir, int desc)
131 131
 					fb = NULL;
132 132
 				}
133 133
 				fb = fileblobCreate();
134
-				if(tnef_message(fp, type, tag, length) != 0) {
134
+				if(tnef_message(fp, type, tag, length, fsize) != 0) {
135 135
 					cli_errmsg("Error reading TNEF message\n");
136 136
 					ret = CL_EFORMAT;
137 137
 					alldone = 1;
... ...
@@ -139,7 +154,7 @@ cli_tnef(const char *dir, int desc)
139 139
 				break;
140 140
 			case LVL_ATTACHMENT:
141 141
 				cli_dbgmsg("TNEF - found attachment\n");
142
-				if(tnef_attachment(fp, type, tag, length, dir, &fb) != 0) {
142
+				if(tnef_attachment(fp, type, tag, length, dir, &fb, fsize) != 0) {
143 143
 					cli_errmsg("Error reading TNEF message\n");
144 144
 					ret = CL_EFORMAT;
145 145
 					alldone = 1;
... ...
@@ -149,7 +164,7 @@ cli_tnef(const char *dir, int desc)
149 149
 				break;
150 150
 			default:
151 151
 				cli_warnmsg("TNEF - unknown level %d tag 0x%x\n", (int)part, (int)tag);
152
-				
152
+
153 153
 				/*
154 154
 				 * Dump the file incase it was part of an
155 155
 				 * email that's about to be deleted
... ...
@@ -188,7 +203,7 @@ cli_tnef(const char *dir, int desc)
188 188
 	if(fb) {
189 189
 		cli_dbgmsg("cli_tnef: flushing final data\n");
190 190
 		if(fileblobGetFilename(fb) == NULL) {
191
-			cli_dbgmsg("Saving TNEF portion with an unknown name");
191
+			cli_dbgmsg("Saving TNEF portion with an unknown name\n");
192 192
 			fileblobSetFilename(fb, dir, "tnef");
193 193
 		}
194 194
 		fileblobDestroy(fb);
... ...
@@ -200,10 +215,10 @@ cli_tnef(const char *dir, int desc)
200 200
 }
201 201
 
202 202
 static int
203
-tnef_message(FILE *fp, uint16_t type, uint16_t tag, int32_t length)
203
+tnef_message(FILE *fp, uint16_t type, uint16_t tag, int32_t length, off_t fsize)
204 204
 {
205 205
 	uint16_t i16;
206
-	/* off_t offset; */
206
+	off_t offset;
207 207
 #if	CL_DEBUG
208 208
 	uint32_t i32;
209 209
 	char *string;
... ...
@@ -211,7 +226,7 @@ tnef_message(FILE *fp, uint16_t type, uint16_t tag, int32_t length)
211 211
 
212 212
 	cli_dbgmsg("message tag 0x%x, type 0x%x, length %d\n", tag, type, length);
213 213
 
214
-	/* offset = ftell(fp); */
214
+	offset = ftell(fp);
215 215
 
216 216
 	/*
217 217
 	 * a lot of this stuff should be only discovered in debug mode...
... ...
@@ -261,27 +276,31 @@ tnef_message(FILE *fp, uint16_t type, uint16_t tag, int32_t length)
261 261
 
262 262
 	/*cli_dbgmsg("%lu %lu\n", (long)(offset + length), ftell(fp));*/
263 263
 
264
-	/* fseek(fp, offset + length, SEEK_SET); */
264
+	if(!CLI_ISCONTAINED2(0, fsize, (off_t)offset, (off_t)length)) {
265
+		cli_errmsg("TNEF: Incorrect length field\n");
266
+		return -1;
267
+	}
268
+	if(fseek(fp, offset + length, SEEK_SET) < 0)
269
+		return -1;
265 270
 
266 271
 	/* Checksum - TODO, verify */
267
-	/* if(fread(&i16, sizeof(uint16_t), 1, fp) != 1)
272
+	if(fread(&i16, sizeof(uint16_t), 1, fp) != 1)
268 273
 		return -1;
269
-	 */
270 274
 
271 275
 	return 0;
272 276
 }
273 277
 
274 278
 static int
275
-tnef_attachment(FILE *fp, uint16_t type, uint16_t tag, int32_t length, const char *dir, fileblob **fbref)
279
+tnef_attachment(FILE *fp, uint16_t type, uint16_t tag, int32_t length, const char *dir, fileblob **fbref, off_t fsize)
276 280
 {
277 281
 	uint32_t todo;
278 282
 	uint16_t i16;
279
-/*	off_t offset; */
283
+	off_t offset;
280 284
 	char *string;
281 285
 
282 286
 	cli_dbgmsg("attachment tag 0x%x, type 0x%x, length %d\n", tag, type, length);
283 287
 
284
-	/* offset = ftell(fp); */
288
+	offset = ftell(fp);
285 289
 
286 290
 	switch(tag) {
287 291
 		case attATTACHTITLE:
... ...
@@ -337,12 +356,16 @@ tnef_attachment(FILE *fp, uint16_t type, uint16_t tag, int32_t length, const cha
337 337
 
338 338
 	/*cli_dbgmsg("%lu %lu\n", (long)(offset + length), ftell(fp));*/
339 339
 
340
-	/* fseek(fp, (long)(offset + length), SEEK_SET); */	/* shouldn't be needed */
340
+	if(!CLI_ISCONTAINED2(0, fsize, (off_t)offset, (off_t)length)) {
341
+		cli_errmsg("TNEF: Incorrect length field\n");
342
+		return -1;
343
+	}
344
+	if(fseek(fp, (long)(offset + length), SEEK_SET) < 0)	/* shouldn't be needed */
345
+		return -1;
341 346
 
342 347
 	/* Checksum - TODO, verify */
343
-	/* if(fread(&i16, sizeof(uint16_t), 1, fp) != 1)
348
+	if(fread(&i16, sizeof(uint16_t), 1, fp) != 1)
344 349
 		return -1;
345
-	 */
346 350
 
347 351
 	return 0;
348 352
 }
... ...
@@ -362,8 +385,8 @@ tnef_header(FILE *fp, uint8_t *part, uint16_t *type, uint16_t *tag, int32_t *len
362 362
 		return -1;
363 363
 
364 364
 	i32 = host32(i32);
365
-	*tag = i32 & 0xFFFF;
366
-	*type = (i32 & 0xFFFF0000) >> 16;
365
+	*tag = (uint16_t)(i32 & 0xFFFF);
366
+	*type = (uint16_t)((i32 & 0xFFFF0000) >> 16);
367 367
 
368 368
 	if(fread(&i32, sizeof(uint32_t), 1, fp) != 1)
369 369
 		return -1;
370 370
new file mode 100644
... ...
@@ -0,0 +1,140 @@
0
+/*
1
+ *  Copyright (C) 2006 Nigel Horne <njh@bandsman.co.uk>
2
+ *
3
+ *  This program is free software; you can redistribute it and/or modify
4
+ *  it under the terms of the GNU General Public License as published by
5
+ *  the Free Software Foundation; either version 2 of the License, or
6
+ *  (at your option) any later version.
7
+ *
8
+ *  This program is distributed in the hope that it will be useful,
9
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
+ *  GNU General Public License for more details.
12
+ *
13
+ *  You should have received a copy of the GNU General Public License
14
+ *  along with this program; if not, write to the Free Software
15
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
+ */
17
+static	char	const	rcsid[] = "$Id: uuencode.c,v 1.2 2006/01/23 10:35:38 nigelhorne Exp $";
18
+
19
+#include "clamav.h"
20
+
21
+#if HAVE_CONFIG_H
22
+#include "clamav-config.h"
23
+#endif
24
+
25
+#include <strings.h>
26
+#include <stdio.h>
27
+#include <memory.h>
28
+#include <sys/stat.h>
29
+#include "others.h"
30
+#include "mbox.h"
31
+#include "blob.h"
32
+#include "line.h"
33
+#include "text.h"
34
+#include "message.h"
35
+#include "uuencode.h"
36
+#include "str.h"
37
+
38
+/* Maximum line length according to RFC821 */
39
+#define	RFC2821LENGTH	1000
40
+
41
+int
42
+cli_uuencode(const char *dir, int desc)
43
+{
44
+	FILE *fin;
45
+	int i;
46
+	message *m;
47
+	char buffer[RFC2821LENGTH + 1];
48
+
49
+	i = dup(desc);
50
+	if((fin = fdopen(i, "rb")) == NULL) {
51
+		cli_errmsg("Can't open descriptor %d\n", desc);
52
+		close(i);
53
+		return CL_EOPEN;
54
+	}
55
+	if(fgets(buffer, sizeof(buffer) - 1, fin) == NULL) {
56
+		/* empty message */
57
+		fclose(fin);
58
+		return CL_CLEAN;
59
+	}
60
+	if(!isuuencodebegin(buffer)) {
61
+		fclose(fin);
62
+		cli_errmsg("Message is not in uuencoded format\n");
63
+		return CL_EFORMAT;
64
+	}
65
+
66
+	m = messageCreate();
67
+	if(m == NULL) {
68
+		fclose(fin);
69
+		return CL_EMEM;
70
+	}
71
+
72
+	cli_dbgmsg("found uuencode file\n");
73
+
74
+	if(uudecodeFile(m, buffer, dir, fin) < 0) {
75
+		messageDestroy(m);
76
+		fclose(fin);
77
+		cli_errmsg("Message is not in uuencoded format\n");
78
+		return CL_EFORMAT;
79
+	}
80
+	messageDestroy(m);
81
+
82
+	fclose(fin);
83
+
84
+	return CL_CLEAN;	/* a lie - but it gets things going */
85
+}
86
+
87
+/*
88
+ * Save the uuencoded part of the file as it is read in since there's no need
89
+ * to include it in the parse tree. Saves memory and parse time.
90
+ * Return < 0 for failure
91
+ */
92
+int
93
+uudecodeFile(message *m, const char *firstline, const char *dir, FILE *fin)
94
+{
95
+	fileblob *fb;
96
+	char buffer[RFC2821LENGTH + 1];
97
+	char *filename = cli_strtok(firstline, 2, " ");
98
+
99
+	if(filename == NULL)
100
+		return -1;
101
+
102
+	fb = fileblobCreate();
103
+	if(fb == NULL) {
104
+		free(filename);
105
+		return -1;
106
+	}
107
+
108
+	fileblobSetFilename(fb, dir, filename);
109
+	cli_dbgmsg("uudecode %s\n", filename);
110
+	free(filename);
111
+
112
+	while(fgets(buffer, sizeof(buffer) - 1, fin) != NULL) {
113
+		unsigned char data[1024];
114
+		const unsigned char *uptr;
115
+		size_t len;
116
+
117
+		cli_chomp(buffer);
118
+		if(strcasecmp(buffer, "end") == 0)
119
+			break;
120
+		if(buffer[0] == '\0')
121
+			break;
122
+
123
+		uptr = decodeLine(m, UUENCODE, buffer, data, sizeof(data));
124
+		if(uptr == NULL)
125
+			break;
126
+
127
+		len = (size_t)(uptr - data);
128
+		if((len > 62) || (len == 0))
129
+			break;
130
+
131
+		if(fileblobAddData(fb, data, len) < 0)
132
+			break;
133
+	}
134
+
135
+	fileblobDestroy(fb);
136
+
137
+	return 1;
138
+}
139
+
0 140
new file mode 100644
... ...
@@ -0,0 +1,25 @@
0
+/*
1
+ *  Copyright (C) 2006 Nigel Horne <njh@bandsman.co.uk>
2
+ *
3
+ *  This program is free software; you can redistribute it and/or modify
4
+ *  it under the terms of the GNU General Public License as published by
5
+ *  the Free Software Foundation; either version 2 of the License, or
6
+ *  (at your option) any later version.
7
+ *
8
+ *  This program is distributed in the hope that it will be useful,
9
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
+ *  GNU General Public License for more details.
12
+ *
13
+ *  You should have received a copy of the GNU General Public License
14
+ *  along with this program; if not, write to the Free Software
15
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
+ */
17
+
18
+#ifndef __UUENCODE_H
19
+#define __UUENCODE_H
20
+
21
+int	cli_uuencode(const char *dir, int desc);
22
+int	uudecodeFile(message *m, const char *firstline, const char *dir, FILE *fin);
23
+
24
+#endif
... ...
@@ -208,7 +208,7 @@ zzip_file_open(ZZIP_DIR * dir, zzip_char_t* name, int o_mode, int d_off)
208 208
                 /* memset(zfp, 0, sizeof *fp); cleared in zzip_file_close() */
209 209
             }else
210 210
             {
211
-                if (! (fp = (ZZIP_FILE *)calloc(1, sizeof(*fp))))
211
+                if (! (fp = (ZZIP_FILE *)cli_calloc(1, sizeof(*fp))))
212 212
                     { err =  ZZIP_OUTOFMEM; goto error; }
213 213
             }
214 214
 
... ...
@@ -220,7 +220,7 @@ zzip_file_open(ZZIP_DIR * dir, zzip_char_t* name, int o_mode, int d_off)
220 220
               { fp->buf32k = dir->cache.buf32k; dir->cache.buf32k = NULL; }
221 221
             else
222 222
             {
223
-                if (! (fp->buf32k = (char *)malloc(ZZIP_32K)))
223
+                if (! (fp->buf32k = (char *)cli_malloc(ZZIP_32K)))
224 224
                     { err = ZZIP_OUTOFMEM; goto error; }
225 225
             }
226 226
 
... ...
@@ -710,7 +710,7 @@ zzip_open_shared_io (ZZIP_FILE* stream,
710 710
 	int fd = os->open(filename, o_flags); /* io->open */
711 711
         if (fd != -1)
712 712
         {
713
-            ZZIP_FILE* fp = calloc (1, sizeof(ZZIP_FILE));
713
+            ZZIP_FILE* fp = cli_calloc (1, sizeof(ZZIP_FILE));
714 714
             if (!fp) { os->close(fd); return 0; } /* io->close */
715 715
 
716 716
             fp->fd = fd; 
... ...
@@ -973,7 +973,7 @@ zzip_seek(ZZIP_FILE * fp, zzip_off_t offset, int whence)
973 973
     { /* method == 8, inflate */
974 974
         char *buf;
975 975
         /*FIXME: use a static buffer! */
976
-        buf = (char *)malloc(ZZIP_32K);
976
+        buf = (char *)cli_malloc(ZZIP_32K);
977 977
         if (! buf) return -1;
978 978
         
979 979
         while (read_size > 0)  
... ...
@@ -26,9 +26,9 @@
26 26
 #include <stdlib.h>
27 27
 #include <string.h>
28 28
 #include <fcntl.h>
29
-#ifdef ZZIP_HAVE_SYS_STAT_H
29
+#include <sys/types.h>
30 30
 #include <sys/stat.h>
31
-#endif
31
+#include <unistd.h>
32 32
 
33 33
 /*
34 34
 #include "__mmap.h"
... ...
@@ -185,7 +185,7 @@ __zzip_find_disk_trailer(int fd, zzip_off_t filesize,
185 185
     auto char buffer[2*ZZIP_BUFSIZ];
186 186
     char* buf = buffer;
187 187
 #else
188
-    char* buf = malloc(2*ZZIP_BUFSIZ);
188
+    char* buf = cli_malloc(2*ZZIP_BUFSIZ);
189 189
 #endif
190 190
     zzip_off_t offset = 0;
191 191
     zzip_off_t maplen = 0; /* mmap(),read(),getpagesize() use size_t !! */
... ...
@@ -349,12 +349,23 @@ __zzip_parse_root_directory(int fd,
349 349
     long offset;          /* offset from start of root directory */
350 350
     char* fd_map = 0; 
351 351
     int32_t  fd_gap = 0;
352
+    struct stat sb;
352 353
     uint16_t u_entries  = ZZIP_GET16(trailer->z_entries);   
353 354
     uint32_t u_rootsize = ZZIP_GET32(trailer->z_rootsize);  
354 355
     uint32_t u_rootseek = ZZIP_GET32(trailer->z_rootseek);
355 356
     __correct_rootseek (u_rootseek, u_rootsize, trailer);
356 357
 
357
-    hdr0 = (struct zzip_dir_hdr*) malloc(u_rootsize);
358
+    if(fstat(fd, &sb) == -1) {
359
+	cli_errmsg("zziplib: Can't fstat file descriptor %d\n", fd);
360
+	return ZZIP_DIR_STAT;
361
+    }
362
+
363
+    if(u_rootsize > sb.st_size) {
364
+	cli_errmsg("zziplib: Incorrect root size\n");
365
+	return ZZIP_CORRUPTED;
366
+    }
367
+
368
+    hdr0 = (struct zzip_dir_hdr*) cli_malloc(u_rootsize);
358 369
     if (!hdr0) 
359 370
         return ZZIP_DIRSIZE;
360 371
     hdr = hdr0;                  __debug_dir_hdr (hdr);
... ...
@@ -533,7 +544,7 @@ ZZIP_DIR*
533 533
 zzip_dir_alloc_ext_io (zzip_strings_t* ext, const zzip_plugin_io_t io)
534 534
 {
535 535
     ZZIP_DIR* dir;
536
-    if ((dir = (ZZIP_DIR *)calloc(1, sizeof(*dir))) == NULL)
536
+    if ((dir = (ZZIP_DIR *)cli_calloc(1, sizeof(*dir))) == NULL)
537 537
         return 0; 
538 538
 
539 539
     /* dir->fileext is currently unused - so what, still initialize it */
... ...
@@ -34,14 +34,14 @@
34 34
 
35 35
 struct cfgstruct *parsecfg(const char *cfgfile, int messages)
36 36
 {
37
-	char buff[LINE_LENGTH], *name, *arg;
37
+	char buff[LINE_LENGTH], *name, *arg, *c;
38 38
 	FILE *fs;
39 39
 	int line = 0, i, found, ctype, calc;
40 40
 	struct cfgstruct *copt = NULL;
41 41
 	struct cfgoption *pt;
42 42
 
43 43
 	struct cfgoption cfg_options[] = {
44
-	    {"LogFile", OPT_STR},
44
+	    {"LogFile", OPT_FULLSTR},
45 45
 	    {"LogFileUnlock", OPT_NOARG},
46 46
 	    {"LogFileMaxSize", OPT_COMPSIZE},
47 47
 	    {"LogTime", OPT_NOARG},
... ...
@@ -49,8 +49,8 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
49 49
 	    {"LogVerbose", OPT_NOARG}, /* clamd + freshclam */
50 50
 	    {"LogSyslog", OPT_NOARG},
51 51
 	    {"LogFacility", OPT_STR},
52
-	    {"PidFile", OPT_STR},
53
-	    {"TemporaryDirectory", OPT_STR},
52
+	    {"PidFile", OPT_FULLSTR},
53
+	    {"TemporaryDirectory", OPT_FULLSTR},
54 54
 	    {"DisableDefaultScanOptions", OPT_NOARG},
55 55
 	    {"ScanPE", OPT_NOARG},
56 56
 	    {"DetectBrokenExecutables", OPT_NOARG},
... ...
@@ -67,11 +67,11 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
67 67
 	    {"ArchiveLimitMemoryUsage", OPT_NOARG},
68 68
 	    {"ArchiveBlockEncrypted", OPT_NOARG},
69 69
 	    {"ArchiveBlockMax", OPT_NOARG},
70
-	    {"DataDirectory", OPT_STR}, /* obsolete */
71
-	    {"DatabaseDirectory", OPT_STR}, /* clamd + freshclam */
70
+	    {"DataDirectory", OPT_FULLSTR}, /* obsolete */
71
+	    {"DatabaseDirectory", OPT_FULLSTR}, /* clamd + freshclam */
72 72
 	    {"TCPAddr", OPT_STR},
73 73
 	    {"TCPSocket", OPT_NUM},
74
-	    {"LocalSocket", OPT_STR},
74
+	    {"LocalSocket", OPT_FULLSTR},
75 75
 	    {"MaxConnectionQueueLength", OPT_NUM},
76 76
 	    {"StreamMaxLength", OPT_COMPSIZE},
77 77
 	    {"StreamMinPort", OPT_NUM},
... ...
@@ -102,7 +102,7 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
102 102
 	    {"ClamukoScanArchive", OPT_NOARG},
103 103
 	    {"DatabaseOwner", OPT_STR}, /* freshclam */
104 104
 	    {"Checks", OPT_NUM}, /* freshclam */
105
-	    {"UpdateLogFile", OPT_STR}, /* freshclam */
105
+	    {"UpdateLogFile", OPT_FULLSTR}, /* freshclam */
106 106
 	    {"DNSDatabaseInfo", OPT_STR}, /* freshclam */
107 107
 	    {"DatabaseMirror", OPT_STR}, /* freshclam */
108 108
 	    {"MaxAttempts", OPT_NUM}, /* freshclam */
... ...
@@ -166,6 +166,8 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
166 166
 				free(arg);
167 167
 				arg = strstr(buff, " ");
168 168
 				arg = strdup(++arg);
169
+				if((c = strpbrk(arg, "\n\r")))
170
+				    *c = '\0';
169 171
 				copt = regcfg(copt, name, arg, 0);
170 172
 				break;
171 173
 			    case OPT_NUM:
... ...
@@ -52,9 +52,9 @@
52 52
 pthread_mutex_t logg_mutex = PTHREAD_MUTEX_INITIALIZER;
53 53
 #endif
54 54
 
55
-FILE *logg_fd = NULL;
55
+FILE *logg_fs = NULL;
56 56
 
57
-short int logg_verbose = 0, logg_lock = 0, logg_time = 0;
57
+short int logg_verbose = 0, logg_lock = 1, logg_time = 0;
58 58
 int logg_size = 0;
59 59
 const char *logg_file = NULL;
60 60
 #if defined(USE_SYSLOG) && !defined(C_AIX)
... ...
@@ -71,10 +71,16 @@ int mdprintf(int desc, const char *str, ...)
71 71
 	int bytes;
72 72
 
73 73
     va_start(args, str);
74
-    bytes = vsnprintf(buff, 512, str, args);
74
+    bytes = vsnprintf(buff, sizeof(buff), str, args);
75 75
     va_end(args);
76
-    write(desc, buff, bytes);
77
-    return bytes;
76
+
77
+    if(bytes == -1)
78
+	return bytes;
79
+
80
+    if(bytes >= sizeof(buff))
81
+	bytes = sizeof(buff) - 1;
82
+
83
+    return send(desc, buff, bytes, 0);
78 84
 }
79 85
 
80 86
 void logg_close(void) {
... ...
@@ -82,9 +88,9 @@ void logg_close(void) {
82 82
 #ifdef CL_THREAD_SAFE
83 83
     pthread_mutex_lock(&logg_mutex);
84 84
 #endif
85
-    if (logg_fd) {
86
-	fclose(logg_fd);
87
-	logg_fd = NULL;
85
+    if (logg_fs) {
86
+	fclose(logg_fs);
87
+	logg_fs = NULL;
88 88
     }
89 89
 #ifdef CL_THREAD_SAFE
90 90
     pthread_mutex_unlock(&logg_mutex);
... ...
@@ -115,9 +121,9 @@ int logg(const char *str, ...)
115 115
 #ifdef CL_THREAD_SAFE
116 116
 	pthread_mutex_lock(&logg_mutex);
117 117
 #endif
118
-	if(!logg_fd) {
118
+	if(!logg_fs) {
119 119
 	    old_umask = umask(0037);
120
-	    if((logg_fd = fopen(logg_file, "a")) == NULL) {
120
+	    if((logg_fs = fopen(logg_file, "a")) == NULL) {
121 121
 		umask(old_umask);
122 122
 #ifdef CL_THREAD_SAFE
123 123
 		pthread_mutex_unlock(&logg_mutex);
... ...
@@ -129,7 +135,7 @@ int logg(const char *str, ...)
129 129
 	    if(logg_lock) {
130 130
 		memset(&fl, 0, sizeof(fl));
131 131
 		fl.l_type = F_WRLCK;
132
-		if(fcntl(fileno(logg_fd), F_SETLK, &fl) == -1) {
132
+		if(fcntl(fileno(logg_fs), F_SETLK, &fl) == -1) {
133 133
 #ifdef CL_THREAD_SAFE
134 134
 		    pthread_mutex_unlock(&logg_mutex);
135 135
 #endif
... ...
@@ -146,7 +152,7 @@ int logg(const char *str, ...)
146 146
 	    pt = ctime(&currtime);
147 147
 	    timestr = mcalloc(strlen(pt), sizeof(char));
148 148
 	    strncpy(timestr, pt, strlen(pt) - 1);
149
-	    fprintf(logg_fd, "%s -> ", timestr);
149
+	    fprintf(logg_fs, "%s -> ", timestr);
150 150
 	    free(timestr);
151 151
 	}
152 152
 
... ...
@@ -154,10 +160,10 @@ int logg(const char *str, ...)
154 154
 	    if(stat(logg_file, &sb) != -1) {
155 155
 		if(sb.st_size > logg_size) {
156 156
 		    logg_file = NULL;
157
-		    fprintf(logg_fd, "Log size = %d, maximal = %d\n", (int) sb.st_size, logg_size);
158
-		    fprintf(logg_fd, "LOGGING DISABLED (Maximal log file size exceeded).\n");
159
-		    fclose(logg_fd);
160
-		    logg_fd = NULL;
157
+		    fprintf(logg_fs, "Log size = %d, maximal = %d\n", (int) sb.st_size, logg_size);
158
+		    fprintf(logg_fs, "LOGGING DISABLED (Maximal log file size exceeded).\n");
159
+		    fclose(logg_fs);
160
+		    logg_fs = NULL;
161 161
 #ifdef CL_THREAD_SAFE
162 162
 		    pthread_mutex_unlock(&logg_mutex);
163 163
 #endif
... ...
@@ -168,18 +174,18 @@ int logg(const char *str, ...)
168 168
 
169 169
 
170 170
 	if(*str == '!') {
171
-	    fprintf(logg_fd, "ERROR: ");
172
-	    vfprintf(logg_fd, str + 1, args);
171
+	    fprintf(logg_fs, "ERROR: ");
172
+	    vfprintf(logg_fs, str + 1, args);
173 173
 	} else if(*str == '^') {
174
-	    fprintf(logg_fd, "WARNING: ");
175
-	    vfprintf(logg_fd, str + 1, args);
174
+	    fprintf(logg_fs, "WARNING: ");
175
+	    vfprintf(logg_fs, str + 1, args);
176 176
 	} else if(*str == '*') {
177 177
 	    if(logg_verbose)
178
-		vfprintf(logg_fd, str + 1, args);
179
-	} else vfprintf(logg_fd, str, args);
178
+		vfprintf(logg_fs, str + 1, args);
179
+	} else vfprintf(logg_fs, str, args);
180 180
 
181 181
 
182
-	fflush(logg_fd);
182
+	fflush(logg_fs);
183 183
 
184 184
 #ifdef CL_THREAD_SAFE
185 185
 	pthread_mutex_unlock(&logg_mutex);
... ...
@@ -188,28 +194,18 @@ int logg(const char *str, ...)
188 188
 
189 189
 #if defined(USE_SYSLOG) && !defined(C_AIX)
190 190
     if(logg_syslog) {
191
-
192
-	/* due to a problem with superfluous control characters (which
193
-	 * vsnprintf() handles correctly) in (v)syslog we have to remove
194
-	 * them in a final string
195
-	 *
196
-	 * FIXME: substitute %% instead of _
197
-	 */
198 191
 	vsnprintf(vbuff, 1024, str, argscpy);
199 192
 	vbuff[1024] = 0;
200 193
 
201
-	while((pt = strchr(vbuff, '%')))
202
-	    *pt = '_';
203
-
204 194
 	if(vbuff[0] == '!') {
205
-	    syslog(LOG_ERR, vbuff + 1);
195
+	    syslog(LOG_ERR, "%s", vbuff + 1);
206 196
 	} else if(vbuff[0] == '^') {
207
-	    syslog(LOG_WARNING, vbuff + 1);
197
+	    syslog(LOG_WARNING, "%s", vbuff + 1);
208 198
 	} else if(vbuff[0] == '*') {
209 199
 	    if(logg_verbose) {
210
-		syslog(LOG_DEBUG, vbuff + 1);
200
+		syslog(LOG_DEBUG, "%s", vbuff + 1);
211 201
 	    }
212
-	} else syslog(LOG_INFO, vbuff);
202
+	} else syslog(LOG_INFO, "%s", vbuff);
213 203
 
214 204
     }
215 205
 #endif
... ...
@@ -237,7 +237,7 @@ int build(struct optstruct *opt)
237 237
 	int ret, realno = 0, bytes, itmp;
238 238
 	unsigned int no = 0;
239 239
 	struct stat foo;
240
-	char buffer[FILEBUFF], *tarfile = NULL, *gzfile = NULL, header[512],
240
+	char buffer[FILEBUFF], *tarfile = NULL, *gzfile = NULL, header[513],
241 241
 	     smbuff[30], *pt, *dbdir;
242 242
         struct cl_node *root = NULL;
243 243
 	FILE *tar, *cvd, *fd;