Browse code

add ARJ and SFX-ARJ support

git-svn: trunk@3138

Trog authored on 2007/07/11 19:14:08
Showing 10 changed files
... ...
@@ -1,3 +1,7 @@
1
+Wed Jul 11 10:12:36 BST 2007 (trog)
2
+-----------------------------------
3
+  * libclamav: add ARJ and SFX-ARJ support
4
+
1 5
 Wed Jul 11 00:56:02 CEST 2007 (tk)
2 6
 ----------------------------------
3 7
   * 0.91 (released with JS and PST code removed)
... ...
@@ -128,6 +128,8 @@ libclamav_la_SOURCES = \
128 128
 	unrar/unrarcmd.c \
129 129
 	unrar/unrarfilter.h \
130 130
 	unrar/unrarppm.h \
131
+	unarj.c \
132
+	unarj.h \
131 133
 	nsis/LZMADecode.c \
132 134
 	nsis/LZMADecode.h \
133 135
 	nsis/bzlib.c \
... ...
@@ -86,8 +86,8 @@ am_libclamav_la_OBJECTS = matcher-ac.lo matcher-bm.lo matcher-ncore.lo \
86 86
 	packlibs.lo fsg.lo mew.lo upack.lo line.lo untar.lo unzip.lo \
87 87
 	special.lo binhex.lo is_tar.lo tnef.lo unrar15.lo unrarvm.lo \
88 88
 	unrar.lo unrarfilter.lo unrarppm.lo unrar20.lo unrarcmd.lo \
89
-	LZMADecode.lo bzlib.lo infblock.lo nulsft.lo pdf.lo spin.lo \
90
-	yc.lo elf.lo sis.lo uuencode.lo pst.lo phishcheck.lo \
89
+	unarj.lo LZMADecode.lo bzlib.lo infblock.lo nulsft.lo pdf.lo \
90
+	spin.lo yc.lo elf.lo sis.lo uuencode.lo pst.lo phishcheck.lo \
91 91
 	phish_domaincheck_db.lo phish_whitelist.lo regex_list.lo \
92 92
 	sha256.lo mspack.lo cab.lo entconv.lo hashtab.lo dconf.lo \
93 93
 	lockdb.lo
... ...
@@ -149,7 +149,6 @@ F77 = @F77@
149 149
 FFLAGS = @FFLAGS@
150 150
 FRESHCLAM_LIBS = @FRESHCLAM_LIBS@
151 151
 GETENT = @GETENT@
152
-GREP = @GREP@
153 152
 HAVE_MILTER_FALSE = @HAVE_MILTER_FALSE@
154 153
 HAVE_MILTER_TRUE = @HAVE_MILTER_TRUE@
155 154
 INSTALL_DATA = @INSTALL_DATA@
... ...
@@ -183,9 +182,12 @@ STRIP = @STRIP@
183 183
 THREAD_LIBS = @THREAD_LIBS@
184 184
 TH_SAFE = @TH_SAFE@
185 185
 VERSION = @VERSION@
186
+ac_ct_AR = @ac_ct_AR@
186 187
 ac_ct_CC = @ac_ct_CC@
187 188
 ac_ct_CXX = @ac_ct_CXX@
188 189
 ac_ct_F77 = @ac_ct_F77@
190
+ac_ct_RANLIB = @ac_ct_RANLIB@
191
+ac_ct_STRIP = @ac_ct_STRIP@
189 192
 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
190 193
 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
191 194
 am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
... ...
@@ -202,30 +204,23 @@ build_cpu = @build_cpu@
202 202
 build_os = @build_os@
203 203
 build_vendor = @build_vendor@
204 204
 datadir = @datadir@
205
-datarootdir = @datarootdir@
206
-docdir = @docdir@
207
-dvidir = @dvidir@
208 205
 exec_prefix = @exec_prefix@
209 206
 host = @host@
210 207
 host_alias = @host_alias@
211 208
 host_cpu = @host_cpu@
212 209
 host_os = @host_os@
213 210
 host_vendor = @host_vendor@
214
-htmldir = @htmldir@
215 211
 includedir = @includedir@
216 212
 infodir = @infodir@
217 213
 install_sh = @install_sh@
218 214
 libdir = @libdir@
219 215
 libexecdir = @libexecdir@
220
-localedir = @localedir@
221 216
 localstatedir = @localstatedir@
222 217
 mandir = @mandir@
223 218
 mkdir_p = @mkdir_p@
224 219
 oldincludedir = @oldincludedir@
225
-pdfdir = @pdfdir@
226 220
 prefix = @prefix@
227 221
 program_transform_name = @program_transform_name@
228
-psdir = @psdir@
229 222
 sbindir = @sbindir@
230 223
 sendmailprog = @sendmailprog@
231 224
 sharedstatedir = @sharedstatedir@
... ...
@@ -342,6 +337,8 @@ libclamav_la_SOURCES = \
342 342
 	unrar/unrarcmd.c \
343 343
 	unrar/unrarfilter.h \
344 344
 	unrar/unrarppm.h \
345
+	unarj.c \
346
+	unarj.h \
345 347
 	nsis/LZMADecode.c \
346 348
 	nsis/LZMADecode.h \
347 349
 	nsis/bzlib.c \
... ...
@@ -520,6 +517,7 @@ distclean-compile:
520 520
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/table.Plo@am__quote@
521 521
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/text.Plo@am__quote@
522 522
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnef.Plo@am__quote@
523
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unarj.Plo@am__quote@
523 524
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unrar.Plo@am__quote@
524 525
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unrar15.Plo@am__quote@
525 526
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unrar20.Plo@am__quote@
... ...
@@ -62,6 +62,7 @@ extern "C"
62 62
 #define CL_EFORMAT	-124 /* bad format or broken file */
63 63
 #define CL_ESUPPORT	-125 /* not supported data format */
64 64
 #define CL_ELOCKDB	-126 /* can't lock DB directory */
65
+#define CL_EARJ         -127 /* ARJ handler error */
65 66
 
66 67
 /* NodalCore */
67 68
 #define CL_ENCINIT	-200 /* NodalCore initialization failed */
... ...
@@ -73,6 +73,7 @@ static struct dconf_module modules[] = {
73 73
     { "ARCHIVE",    "ZIP",	    ARCH_CONF_ZIP,	    1 },
74 74
     { "ARCHIVE",    "GZIP",	    ARCH_CONF_GZ,	    1 },
75 75
     { "ARCHIVE",    "BZIP",	    ARCH_CONF_BZ,	    1 },
76
+    { "ARCHIVE",    "ARJ",          ARCH_CONF_ARJ,          1 },
76 77
     { "ARCHIVE",    "SZDD",	    ARCH_CONF_SZDD,	    1 },
77 78
     { "ARCHIVE",    "CAB",	    ARCH_CONF_CAB,	    1 },
78 79
     { "ARCHIVE",    "CHM",	    ARCH_CONF_CHM,	    1 },
... ...
@@ -65,6 +65,7 @@ struct cli_dconf {
65 65
 #define ARCH_CONF_BINHEX    0x200
66 66
 #define ARCH_CONF_SIS	    0x400
67 67
 #define ARCH_CONF_NSIS	    0x800
68
+#define ARCH_CONF_ARJ       0x1000
68 69
 
69 70
 /* Document flags */
70 71
 #define DOC_CONF_HTML	    0x1
... ...
@@ -68,6 +68,7 @@ static const struct cli_magic_s cli_magic[] = {
68 68
     {0,	    "PK00PK\003\004",		8,  "ZIP",		CL_TYPE_ZIP},
69 69
     {0,	    "\037\213",			2,  "GZip",		CL_TYPE_GZ},
70 70
     {0,	    "BZh",			3,  "BZip",		CL_TYPE_BZ},
71
+    {0,	    "\x60\xea",			2,  "ARJ",		CL_TYPE_ARJ},
71 72
     {0,	    "SZDD",			4,  "compress.exe'd",	CL_TYPE_MSSZDD},
72 73
     {0,	    "MSCF",			4,  "MS CAB",		CL_TYPE_MSCAB},
73 74
     {0,	    "ITSF",			4,  "MS CHM",           CL_TYPE_MSCHM},
... ...
@@ -190,6 +191,9 @@ static const struct cli_smagic_s cli_smagic[] = {
190 190
     {"526172211a0700", "RAR-SFX", CL_TYPE_RARSFX},
191 191
     {"504b0304", "ZIP-SFX", CL_TYPE_ZIPSFX},
192 192
     {"4d534346", "CAB-SFX", CL_TYPE_CABSFX},
193
+    {"60ea{7}0002", "ARJ-SFX", CL_TYPE_ARJSFX},
194
+    {"60ea{7}0102", "ARJ-SFX", CL_TYPE_ARJSFX},
195
+    {"60ea{7}0202", "ARJ-SFX", CL_TYPE_ARJSFX},
193 196
     {"efbeadde4e756c6c736f6674496e7374", "NSIS", CL_TYPE_NULSFT},
194 197
 
195 198
     {"4d5a{180-300}50450000", "PE", CL_TYPE_MSEXE},
... ...
@@ -38,6 +38,7 @@ typedef enum {
38 38
     CL_TYPE_ZIP,
39 39
     CL_TYPE_BZ,
40 40
     CL_TYPE_RAR,
41
+    CL_TYPE_ARJ,
41 42
     CL_TYPE_MSSZDD,
42 43
     CL_TYPE_MSOLE2,
43 44
     CL_TYPE_MSCAB,
... ...
@@ -62,8 +63,8 @@ typedef enum {
62 62
     CL_TYPE_ZIPSFX, /* on the fly */
63 63
     CL_TYPE_RARSFX, /* on the fly */
64 64
     CL_TYPE_CABSFX,
65
+    CL_TYPE_ARJSFX,
65 66
     CL_TYPE_NULSFT /* on the fly */
66
-
67 67
 } cli_file_t;
68 68
 
69 69
 struct cli_matched_type {
... ...
@@ -211,6 +211,8 @@ const char *cl_strerror(int clerror)
211 211
 	    return "NodalCore accelerator Input/Output error";
212 212
 	case CL_ELOCKDB:
213 213
 	    return "Unable to lock database directory";
214
+	case CL_EARJ:
215
+	    return "ARJ module failure";
214 216
 	default:
215 217
 	    return "Unknown error code";
216 218
     }
... ...
@@ -85,6 +85,7 @@ extern short cli_leavetemps_flag;
85 85
 #include "mspack.h"
86 86
 #include "cab.h"
87 87
 #include "rtf.h"
88
+#include "unarj.h"
88 89
 
89 90
 #ifdef HAVE_ZLIB_H
90 91
 #include <zlib.h>
... ...
@@ -311,6 +312,116 @@ static int cli_scanrar(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_c
311 311
     return ret;
312 312
 }
313 313
 
314
+static int cli_unarj_checklimits(const cli_ctx *ctx, const arj_metadata_t *metadata, unsigned int files)
315
+{
316
+    if (ctx->limits) {
317
+	if (ctx->limits->maxfilesize && (metadata->orig_size > ctx->limits->maxfilesize)) {
318
+	    cli_dbgmsg("ARJ: %s: Size exceeded (%lu, max: %lu)\n", metadata->filename ? metadata->filename : "(none)",
319
+	    		(unsigned long int) metadata->orig_size, ctx->limits->maxfilesize);
320
+	    if (BLOCKMAX) {
321
+		*ctx->virname = "ARJ.ExceededFileSize";
322
+		return CL_VIRUS;
323
+	    }
324
+	    return CL_EMAXSIZE;
325
+	}
326
+	
327
+	if (ctx->limits->maxratio && metadata->orig_size && metadata->comp_size) {
328
+	    if (metadata->orig_size / metadata->comp_size >= ctx->limits->maxratio) {
329
+		cli_dbgmsg("ARJ: Max ratio reached (%u, max: %u)\n", (unsigned int) (metadata->orig_size / metadata->comp_size), ctx->limits->maxratio);
330
+		if (ctx->limits->maxfilesize && (metadata->orig_size <= ctx->limits->maxfilesize)) {
331
+		    cli_dbgmsg("ARJ: Ignoring ratio limit (file size doesn't hit limits)\n");
332
+		} else {
333
+		    if(BLOCKMAX) {
334
+		    	*ctx->virname = "Oversized.ARJ";
335
+			return CL_VIRUS;
336
+		    }
337
+		}
338
+	    }
339
+	}
340
+	
341
+	if(ctx->limits->maxfiles && (files > ctx->limits->maxfiles)) {
342
+	    cli_dbgmsg("ARJ: Files limit reached (max: %u)\n", ctx->limits->maxfiles);
343
+	    if (BLOCKMAX) {
344
+	    	*ctx->virname = "ARJ.ExceededFilesLimit";
345
+		return CL_VIRUS;
346
+	    }
347
+	    return CL_EMAXFILES;
348
+	}
349
+    }
350
+    
351
+    return CL_SUCCESS;
352
+}
353
+
354
+static int cli_scanarj(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_check)
355
+{
356
+	int ret = CL_CLEAN, rc;
357
+	arj_metadata_t metadata;
358
+	char *dir;
359
+	unsigned int file_count = 1;
360
+
361
+    cli_dbgmsg("in cli_scanarj()\n");
362
+
363
+     /* generate the temporary directory */
364
+    dir = cli_gentemp(NULL);
365
+    if(mkdir(dir, 0700)) {
366
+	cli_dbgmsg("RAR: Can't create temporary directory %s\n", dir);
367
+	free(dir);
368
+	return CL_ETMPDIR;
369
+    }
370
+
371
+    if(sfx_offset)
372
+	lseek(desc, sfx_offset, SEEK_SET);
373
+
374
+    ret = cli_unarj_open(desc, dir);
375
+    if (ret != CL_SUCCESS) {
376
+	if(!cli_leavetemps_flag)
377
+	    cli_rmdirs(dir);
378
+	free(dir);
379
+	cli_dbgmsg("ARJ: Error: %s\n", cl_strerror(ret));
380
+	return ret;
381
+    }
382
+    
383
+   metadata.filename = NULL;
384
+
385
+   do {
386
+	ret = cli_unarj_prepare_file(desc, dir, &metadata);
387
+	if (ret != CL_SUCCESS) {
388
+	   break;
389
+	}
390
+	ret = cli_unarj_checklimits(ctx, &metadata, file_count);
391
+	if (ret == CL_VIRUS) {
392
+		break;
393
+	}
394
+	ret = cli_unarj_extract_file(desc, dir, &metadata);
395
+	if (metadata.ofd >= 0) {
396
+	    lseek(metadata.ofd, 0, SEEK_SET);
397
+	    rc = cli_magic_scandesc(metadata.ofd, ctx);
398
+	    close(metadata.ofd);
399
+	    if (rc == CL_VIRUS) {
400
+		cli_dbgmsg("ARJ: infected with %s\n",*ctx->virname);
401
+		ret = CL_VIRUS;
402
+		break;
403
+	    }
404
+	}
405
+	if (metadata.filename) {
406
+		free(metadata.filename);
407
+		metadata.filename = NULL;
408
+	}
409
+
410
+    } while(ret == CL_SUCCESS);
411
+    
412
+    if(!cli_leavetemps_flag)
413
+	cli_rmdirs(dir);
414
+
415
+    free(dir);
416
+    if (metadata.filename) {
417
+	free(metadata.filename);
418
+    }
419
+
420
+    cli_dbgmsg("ARJ: Exit code: %d\n", ret);
421
+
422
+    return ret;
423
+}
314 424
 #ifdef HAVE_ZLIB_H
315 425
 static int cli_scanzip(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_check)
316 426
 {
... ...
@@ -1808,6 +1919,12 @@ static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type)
1808 1808
 			    nret = cli_scanmscab(desc, ctx, fpt->offset);
1809 1809
 			}
1810 1810
 			break;
1811
+		    case CL_TYPE_ARJSFX:
1812
+			if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_ARJ)) {
1813
+			    cli_dbgmsg("ARJ-SFX signature found at %u\n", (unsigned int) fpt->offset);
1814
+			    nret = cli_scanarj(desc, ctx, fpt->offset, &lastrar);
1815
+			}
1816
+			break;
1811 1817
 
1812 1818
 		    case CL_TYPE_NULSFT:
1813 1819
 		        if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_NSIS) && fpt->offset > 4) {
... ...
@@ -1961,6 +2078,10 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
1961 1961
 		ret = cli_scanbzip(desc, ctx);
1962 1962
 #endif
1963 1963
 	    break;
1964
+	case CL_TYPE_ARJ:
1965
+	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ARJ))
1966
+		ret = cli_scanarj(desc, ctx, 0, NULL);
1967
+	    break;
1964 1968
 
1965 1969
         case CL_TYPE_NULSFT:
1966 1970
 	    if(SCAN_ARCHIVE)