add support for old fashioned tar archives

git-svn: trunk@1421
remotes/push_mirror/metadata
Tomasz Kojm 20 years ago
parent 4d4166a9f2
commit a7f5fd00f5
  1. 4
      clamav-devel/ChangeLog
  2. 4
      clamav-devel/libclamav/Makefile.am
  3. 12
      clamav-devel/libclamav/Makefile.in
  4. 43
      clamav-devel/libclamav/filetypes.c
  5. 6
      clamav-devel/libclamav/filetypes.h
  6. 97
      clamav-devel/libclamav/is_tar.c
  7. 45
      clamav-devel/libclamav/is_tar.h
  8. 39
      clamav-devel/libclamav/scanners.c
  9. 19
      clamav-devel/libclamav/untar.c
  10. 5
      clamav-devel/libclamav/untar.h

@ -1,3 +1,7 @@
Tue Mar 22 22:22:30 CET 2005 (tk)
---------------------------------
* libclamav: add support for old fashioned tar archives
Tue Mar 22 11:27:58 GMT 2005 (njh)
----------------------------------
* libclamav/mbox.c: Not all Worm.Bagle.AC were being caught

@ -120,6 +120,8 @@ libclamav_la_SOURCES = \
special.c \
special.h \
binhex.c \
binhex.h
binhex.h \
is_tar.c \
is_tar.h
lib_LTLIBRARIES = libclamav.la

@ -80,7 +80,7 @@ am_libclamav_la_OBJECTS = matcher-ac.lo matcher-bm.lo matcher.lo \
text.lo ole2_extract.lo vba_extract.lo msexpand.lo pe.lo \
cabd.lo lzxd.lo mszipd.lo qtmd.lo system.lo upx.lo htmlnorm.lo \
chmunpack.lo rebuildpe.lo petite.lo fsg.lo line.lo untar.lo \
special.lo binhex.lo
special.lo binhex.lo is_tar.lo
libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
@ -89,8 +89,9 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@ ./$(DEPDIR)/cabd.Plo ./$(DEPDIR)/chmunpack.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/cvd.Plo ./$(DEPDIR)/dsig.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/filetypes.Plo ./$(DEPDIR)/fsg.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/htmlnorm.Plo ./$(DEPDIR)/line.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/lzxd.Plo ./$(DEPDIR)/matcher-ac.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/htmlnorm.Plo ./$(DEPDIR)/is_tar.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/line.Plo ./$(DEPDIR)/lzxd.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/matcher-ac.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/matcher-bm.Plo ./$(DEPDIR)/matcher.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/mbox.Plo ./$(DEPDIR)/md5.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/message.Plo ./$(DEPDIR)/msexpand.Plo \
@ -331,7 +332,9 @@ libclamav_la_SOURCES = \
special.c \
special.h \
binhex.c \
binhex.h
binhex.h \
is_tar.c \
is_tar.h
lib_LTLIBRARIES = libclamav.la
all: all-am
@ -412,6 +415,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filetypes.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htmlnorm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/is_tar.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/line.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lzxd.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/matcher-ac.Plo@am__quote@

@ -61,7 +61,6 @@ static const struct cli_magic_s cli_magic[] = {
{0, "SZDD", 4, "compress.exe'd", CL_TYPE_MSSZDD},
{0, "MSCF", 4, "MS CAB", CL_TYPE_MSCAB},
{0, "ITSF", 4, "MS CHM", CL_TYPE_MSCHM},
{257, "ustar", 5, "POSIX tar", CL_TYPE_TAR},
{0, "#@~^", 4, "SCRENC", CL_TYPE_SCRENC},
{0, "(This file must be converted with BinHex 4.0)",
45, "BinHex", CL_TYPE_BINHEX},
@ -197,6 +196,48 @@ cli_file_t cli_filetype(const char *buf, size_t buflen)
return ascii ? CL_TYPE_UNKNOWN_TEXT : CL_TYPE_UNKNOWN_DATA;
}
int is_tar(unsigned char *buf, int nbytes);
cli_file_t cli_filetype2(int desc)
{
char smallbuff[MAGIC_BUFFER_SIZE + 1];
unsigned char *bigbuff;
int bread;
cli_file_t ret = CL_TYPE_UNKNOWN_DATA;
memset(smallbuff, 0, sizeof(smallbuff));
if((bread = read(desc, smallbuff, MAGIC_BUFFER_SIZE)) > 0)
ret = cli_filetype(smallbuff, bread);
if(ret == CL_TYPE_UNKNOWN_DATA || ret == CL_TYPE_UNKNOWN_TEXT) {
if(!(bigbuff = (unsigned char *) cli_calloc(16384 + 1, sizeof(unsigned char))))
return ret;
lseek(desc, 0, SEEK_SET);
if((bread = read(desc, bigbuff, 16384)) > 0) {
bigbuff[bread] = 0;
switch(is_tar(bigbuff, bread)) {
case 1:
ret = CL_TYPE_OLD_TAR;
cli_dbgmsg("Recognized old fashioned tar file\n");
break;
case 2:
ret = CL_TYPE_POSIX_TAR;
cli_dbgmsg("Recognized POSIX tar file\n");
break;
}
}
free(bigbuff);
}
return ret;
}
int cli_addtypesigs(struct cl_node *root)
{
int i, ret;

@ -20,7 +20,7 @@
#ifndef __FILETYPES_H
#define __FILETYPES_H
#define MAGIC_BUFFER_SIZE 262
#define MAGIC_BUFFER_SIZE 50
#define CL_TYPENO 500
typedef enum {
@ -28,7 +28,8 @@ typedef enum {
CL_TYPE_UNKNOWN_DATA,
CL_TYPE_MSEXE,
CL_TYPE_DATA,
CL_TYPE_TAR,
CL_TYPE_POSIX_TAR,
CL_TYPE_OLD_TAR,
CL_TYPE_GZ,
CL_TYPE_ZIP,
CL_TYPE_BZ,
@ -49,6 +50,7 @@ typedef enum {
} cli_file_t;
cli_file_t cli_filetype(const char *buf, size_t buflen);
cli_file_t cli_filetype2(int desc);
int cli_addtypesigs(struct cl_node *root);
#endif

@ -0,0 +1,97 @@
/*
* is_tar() -- figure out whether file is a tar archive.
*
* Stolen (by the author of the file utility!) from the public domain tar program:
* Public Domain version written 26 Aug 1985 John Gilmore (ihnp4!hoptoad!gnu).
*
* @(#)list.c 1.18 9/23/86 Public Domain - gnu
* $Id: is_tar.c,v 1.1 2005/03/22 21:26:25 kojm Exp $
*
* Comments changed and some code/comments reformatted
* for file command by Ian Darwin.
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include "is_tar.h"
#include "others.h"
#define isodigit(c) ( ((c) >= '0') && ((c) <= '7') )
static int from_oct(int digs, char *where);
/*
* Return
* 0 if the checksum is bad (i.e., probably not a tar archive),
* 1 for old UNIX tar file,
* 2 for Unix Std (POSIX) tar file.
*/
int is_tar(unsigned char *buf, int nbytes)
{
union record *header = (union record *)buf;
int i;
int sum, recsum;
char *p;
if (nbytes < sizeof(union record))
return 0;
recsum = from_oct(8, header->header.chksum);
sum = 0;
p = header->charptr;
for (i = sizeof(union record); --i >= 0;) {
/*
* We can't use unsigned char here because of old compilers,
* e.g. V7.
*/
sum += 0xFF & *p++;
}
/* Adjust checksum to count the "chksum" field as blanks. */
for (i = sizeof(header->header.chksum); --i >= 0;)
sum -= 0xFF & header->header.chksum[i];
sum += ' '* sizeof header->header.chksum;
if (sum != recsum)
return 0; /* Not a tar archive */
if (0==strcmp(header->header.magic, TMAGIC))
return 2; /* Unix Standard tar archive */
return 1; /* Old fashioned tar archive */
}
/*
* Quick and dirty octal conversion.
*
* Result is -1 if the field is invalid (all blank, or nonoctal).
*/
static int from_oct(int digs, char *where)
{
int value;
while (isspace((unsigned char)*where)) { /* Skip spaces */
where++;
if (--digs <= 0)
return -1; /* All blank field */
}
value = 0;
while (digs > 0 && isodigit(*where)) { /* Scan til nonoctal */
value = (value << 3) | (*where++ - '0');
--digs;
}
if (digs > 0 && *where && !isspace((unsigned char)*where))
return -1; /* Ended on non-space/nul */
return value;
}

@ -0,0 +1,45 @@
/*
* Header file for public domain tar (tape archive) program.
*
* @(#)tar.h 1.20 86/10/29 Public Domain.
*
* Created 25 August 1985 by John Gilmore, ihnp4!hoptoad!gnu.
*
* $Id: is_tar.h,v 1.1 2005/03/22 21:26:25 kojm Exp $ # checkin only
*/
/*
* Header block on tape.
*
* I'm going to use traditional DP naming conventions here.
* A "block" is a big chunk of stuff that we do I/O on.
* A "record" is a piece of info that we care about.
* Typically many "record"s fit into a "block".
*/
#define RECORDSIZE 512
#define NAMSIZ 100
#define TUNMLEN 32
#define TGNMLEN 32
union record {
char charptr[RECORDSIZE];
struct header {
char name[NAMSIZ];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char linkflag;
char linkname[NAMSIZ];
char magic[8];
char uname[TUNMLEN];
char gname[TGNMLEN];
char devmajor[8];
char devminor[8];
} header;
};
/* The magic field is filled with this if uname and gname are valid. */
#define TMAGIC "ustar " /* 7 chars and a null */

@ -23,9 +23,9 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/param.h>
#include <fcntl.h>
#include <dirent.h>
@ -1126,7 +1126,7 @@ static int cli_scanole2(int desc, const char **virname, long int *scanned, const
return ret;
}
static int cli_scantar(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
static int cli_scantar(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec, unsigned int posix)
{
char *dir;
int ret = CL_CLEAN;
@ -1141,7 +1141,7 @@ static int cli_scantar(int desc, const char **virname, long int *scanned, const
return CL_ETMPDIR;
}
if((ret = cli_untar(dir, desc)))
if((ret = cli_untar(dir, desc, posix)))
cli_dbgmsg("Tar: %s\n", cl_strerror(ret));
else
ret = cli_scandir(dir, virname, scanned, root, limits, options, arec, mrec);
@ -1289,11 +1289,21 @@ static int cli_scanmail(int desc, const char **virname, long int *scanned, const
int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
{
char magic[MAGIC_BUFFER_SIZE + 1];
int ret = CL_CLEAN, nret;
int bread = 0;
cli_file_t type;
struct stat sb;
if(fstat(desc, &sb) == -1) {
cli_errmsg("Can's fstat descriptor %d\n", desc);
return CL_EIO;
}
if(sb.st_size <= 5) {
cli_dbgmsg("Small data (%d bytes)\n", sb.st_size);
return CL_CLEAN;
}
if(!root) {
cli_errmsg("CRITICAL: root == NULL\n");
@ -1325,18 +1335,8 @@ int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const
}
lseek(desc, 0, SEEK_SET);
memset(magic, 0, sizeof(magic));
if((bread = read(desc, magic, MAGIC_BUFFER_SIZE)) == -1) {
cli_dbgmsg("Can't read from descriptor %d\n");
return CL_EIO;
} else if(bread < 2) {
/* short read - no need to do magic */
return CL_CLEAN;
}
type = cli_filetype2(desc);
lseek(desc, 0, SEEK_SET);
type = cli_filetype(magic, bread);
type == CL_TYPE_MAIL ? mrec++ : arec++;
@ -1388,9 +1388,14 @@ int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const
ret = cli_scanole2(desc, virname, scanned, root, limits, options, arec, mrec);
break;
case CL_TYPE_TAR:
case CL_TYPE_POSIX_TAR:
if(SCAN_ARCHIVE)
ret = cli_scantar(desc, virname, scanned, root, limits, options, arec, mrec, 1);
break;
case CL_TYPE_OLD_TAR:
if(SCAN_ARCHIVE)
ret = cli_scantar(desc, virname, scanned, root, limits, options, arec, mrec);
ret = cli_scantar(desc, virname, scanned, root, limits, options, arec, mrec, 0);
break;
case CL_TYPE_BINHEX:

@ -21,6 +21,9 @@
*
* Change History:
* $Log: untar.c,v $
* Revision 1.25 2005/03/22 21:26:27 kojm
* add support for old fashioned tar archives
*
* Revision 1.24 2005/03/20 18:34:18 nigelhorne
* Minor tidy
*
@ -94,7 +97,7 @@
* First draft
*
*/
static char const rcsid[] = "$Id: untar.c,v 1.24 2005/03/20 18:34:18 nigelhorne Exp $";
static char const rcsid[] = "$Id: untar.c,v 1.25 2005/03/22 21:26:27 kojm Exp $";
#include <stdio.h>
#include <errno.h>
@ -126,7 +129,7 @@ octal(const char *str)
}
int
cli_untar(const char *dir, int desc)
cli_untar(const char *dir, int desc, unsigned int posix)
{
int size = 0;
int in_block = 0;
@ -169,11 +172,13 @@ cli_untar(const char *dir, int desc)
break;
/* Notice assumption that BLOCKSIZE > 262 */
strncpy(magic, block+257, 5);
magic[5] = '\0';
if(strcmp(magic, "ustar") != 0) {
cli_dbgmsg("Incorrect magic string '%s' in tar header\n", magic);
return CL_EFORMAT;
if(posix) {
strncpy(magic, block+257, 5);
magic[5] = '\0';
if(strcmp(magic, "ustar") != 0) {
cli_dbgmsg("Incorrect magic string '%s' in tar header\n", magic);
return CL_EFORMAT;
}
}
type = block[156];

@ -17,6 +17,9 @@
*
* Change History:
* $Log: untar.h,v $
* Revision 1.3 2005/03/22 21:26:27 kojm
* add support for old fashioned tar archives
*
* Revision 1.2 2004/09/05 18:58:22 nigelhorne
* Extract files completed
*
@ -24,4 +27,4 @@
* First draft
*
*/
int cli_untar(const char *dir, int desc);
int cli_untar(const char *dir, int desc, unsigned int posix);

Loading…
Cancel
Save