diff -dPNur clamav-0.90.1/libclamav/clamav.h clamav-0.90.1-new/libclamav/clamav.h --- clamav-0.90.1/libclamav/clamav.h 2007-02-22 16:09:00.000000000 +0100 +++ clamav-0.90.1-new/libclamav/clamav.h 2007-03-29 14:15:14.000000000 +0200 @@ -63,6 +63,7 @@ #define CL_EFORMAT -124 /* bad format or broken file */ #define CL_ESUPPORT -125 /* not supported data format */ #define CL_ELOCKDB -126 /* can't lock DB directory */ +#define CL_E7ZIP -127 /* 7zip module error */ /* NodalCore */ #define CL_ENCINIT -200 /* NodalCore initialization failed */ diff -dPNur clamav-0.90.1/libclamav/filetypes.c clamav-0.90.1-new/libclamav/filetypes.c --- clamav-0.90.1/libclamav/filetypes.c 2007-03-02 00:44:29.000000000 +0100 +++ clamav-0.90.1-new/libclamav/filetypes.c 2007-03-29 14:11:58.000000000 +0200 @@ -67,6 +67,7 @@ /* Archives */ {0, "Rar!", 4, "RAR", CL_TYPE_RAR}, + {0, "7z\274\257\047\034", 6, "7ZIP", CL_TYPE_7ZIP}, {0, "PK\003\004", 4, "ZIP", CL_TYPE_ZIP}, {0, "PK00PK\003\004", 8, "ZIP", CL_TYPE_ZIP}, {0, "\037\213", 2, "GZip", CL_TYPE_GZ}, diff -dPNur clamav-0.90.1/libclamav/filetypes.c.orig clamav-0.90.1-new/libclamav/filetypes.c.orig --- clamav-0.90.1/libclamav/filetypes.c.orig 1970-01-01 01:00:00.000000000 +0100 +++ clamav-0.90.1-new/libclamav/filetypes.c.orig 2007-03-02 00:44:29.000000000 +0100 @@ -0,0 +1,409 @@ +/* + * Copyright (C) 2002 - 2005 Tomasz Kojm + * With enhancements from Thomas Lamy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#if HAVE_CONFIG_H +#include "clamav-config.h" +#endif + +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "clamav.h" +#include "filetypes.h" +#include "others.h" +#include "readdb.h" +#include "matcher-ac.h" +#include "str.h" + +#ifdef CL_EXPERIMENTAL +#include "htmlnorm.h" +#include "entconv.h" +#endif + +struct cli_magic_s { + size_t offset; + const char *magic; + size_t length; + const char *descr; + cli_file_t type; +}; + +struct cli_smagic_s { + const char *sig; + const char *descr; + cli_file_t type; +}; + +static const struct cli_magic_s cli_magic[] = { + + /* Executables */ + + {0, "MZ", 2, "DOS/W32 executable/library/driver", CL_TYPE_MSEXE}, + {0, "\177ELF", 4, "ELF", CL_TYPE_ELF}, + + /* Archives */ + + {0, "Rar!", 4, "RAR", CL_TYPE_RAR}, + {0, "PK\003\004", 4, "ZIP", CL_TYPE_ZIP}, + {0, "PK00PK\003\004", 8, "ZIP", CL_TYPE_ZIP}, + {0, "\037\213", 2, "GZip", CL_TYPE_GZ}, + {0, "BZh", 3, "BZip", CL_TYPE_BZ}, + {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}, + {8, "\x19\x04\x00\x10", 4, "SIS", CL_TYPE_SIS}, + {0, "#@~^", 4, "SCRENC", CL_TYPE_SCRENC}, + {0, "(This file must be converted with BinHex 4.0)", + 45, "BinHex", CL_TYPE_BINHEX}, + + /* Mail */ + + {0, "From ", 5, "MBox", CL_TYPE_MAIL}, + {0, "Received: ", 10, "Raw mail", CL_TYPE_MAIL}, + {0, "Return-Path: ", 13, "Maildir", CL_TYPE_MAIL}, + {0, "Return-path: ", 13, "Maildir", CL_TYPE_MAIL}, + {0, "Delivered-To: ", 14, "Mail", CL_TYPE_MAIL}, + {0, "X-UIDL: ", 8, "Mail", CL_TYPE_MAIL}, + {0, "X-Apparently-To: ", 17, "Mail", CL_TYPE_MAIL}, + {0, "X-Envelope-From: ", 17, "Mail", CL_TYPE_MAIL}, + {0, "X-Original-To: ", 15, "Mail", CL_TYPE_MAIL}, + {0, "X-Symantec-", 11, "Symantec", CL_TYPE_MAIL}, + {0, "X-EVS", 5, "EVS mail", CL_TYPE_MAIL}, + {0, "X-Real-To: ", 11, "Mail", CL_TYPE_MAIL}, + {0, "X-Sieve: ", 9, "Mail", CL_TYPE_MAIL}, + {0, ">From ", 6, "Mail", CL_TYPE_MAIL}, + {0, "Date: ", 6, "Mail", CL_TYPE_MAIL}, + {0, "Message-Id: ", 12, "Mail", CL_TYPE_MAIL}, + {0, "Message-ID: ", 12, "Mail", CL_TYPE_MAIL}, + {0, "Envelope-to: ", 13, "Mail", CL_TYPE_MAIL}, + {0, "Delivery-date: ", 15, "Mail", CL_TYPE_MAIL}, + {0, "To: ", 4, "Mail", CL_TYPE_MAIL}, + {0, "Subject: ", 9, "Mail", CL_TYPE_MAIL}, + {0, "For: ", 5, "Eserv mail", CL_TYPE_MAIL}, + {0, "From: ", 6, "Exim mail", CL_TYPE_MAIL}, + {0, "v:\015\012Received: ", 14, "VPOP3 Mail (DOS)", CL_TYPE_MAIL}, + {0, "v:\012Received: ", 13, "VPOP3 Mail (UNIX)", CL_TYPE_MAIL}, + {0, "Hi. This is the qmail-send", 26, "Qmail bounce", CL_TYPE_MAIL}, + {0, "\170\237\076\042", 4, "TNEF", CL_TYPE_TNEF}, + + {0, "begin ", 6, "UUencoded", CL_TYPE_UUENCODED}, + + /* Graphics (may contain exploits against MS systems) */ + + {0, "GIF", 3, "GIF", CL_TYPE_GRAPHICS}, + {0, "BM", 2, "BMP", CL_TYPE_GRAPHICS}, + {0, "\377\330\377", 3, "JPEG", CL_TYPE_GRAPHICS}, + {6, "JFIF", 4, "JPEG", CL_TYPE_GRAPHICS}, + {6, "Exif", 4, "JPEG", CL_TYPE_GRAPHICS}, + {0, "\x89PNG", 4, "PNG", CL_TYPE_GRAPHICS}, + {0, "RIFF", 4, "RIFF", CL_TYPE_RIFF}, + {0, "RIFX", 4, "RIFX", CL_TYPE_RIFF}, + + /* Others */ + + {0, "\320\317\021\340\241\261\032\341", 8, "OLE2 container", CL_TYPE_MSOLE2}, + {0, "%PDF-", 5, "PDF document", CL_TYPE_PDF}, + {0, "\266\271\254\256\376\377\377\377", 8, "CryptFF", CL_TYPE_CRYPTFF}, + {0, "{\\rtf", 5, "RTF", CL_TYPE_RTF}, + + /* Ignored types */ + + {0, "\000\000\001\263", 4, "MPEG video stream", CL_TYPE_DATA}, + {0, "\000\000\001\272", 4, "MPEG sys stream", CL_TYPE_DATA}, + {0, "OggS", 4, "Ogg Stream", CL_TYPE_DATA}, + {0, "ID3", 3, "MP3", CL_TYPE_DATA}, + {0, "\377\373\220", 3, "MP3", CL_TYPE_DATA}, + {0, "%!PS-Adobe-", 11, "PostScript", CL_TYPE_DATA}, + {0, "\060\046\262\165\216\146\317", 7, "WMA/WMV/ASF", CL_TYPE_DATA}, + {0, ".RMF" , 4, "Real Media File", CL_TYPE_DATA}, + + {0, NULL, 0, NULL, CL_TYPE_UNKNOWN_DATA} +}; + +static const struct cli_smagic_s cli_smagic[] = { + + /* "\nFrom: " * "\nContent-Type: " */ + {"0a46726f6d3a20{-2048}0a436f6e74656e742d547970653a20", "Mail file", CL_TYPE_MAIL}, + + /* "\nReceived: " * "\nContent-Type: " */ + {"0a52656365697665643a20{-2048}0a436f6e74656e742d547970653a20", "Mail file", CL_TYPE_MAIL}, + + /* "\nReceived: " * "\nContent-type: " */ + {"0a52656365697665643a20{-2048}0a436f6e74656e742d747970653a20", "Mail file", CL_TYPE_MAIL}, + + /* "MIME-Version: " * "\nContent-Type: " */ + {"4d494d452d56657273696f6e3a20{-2048}0a436f6e74656e742d547970653a20", "Mail file", CL_TYPE_MAIL}, + + /* remember the matcher is case sensitive */ + {"3c62723e", "HTML data", CL_TYPE_HTML}, /*
*/ + {"3c42723e", "HTML data", CL_TYPE_HTML}, /*
*/ + {"3c42523e", "HTML data", CL_TYPE_HTML}, /*
*/ + {"3c703e", "HTML data", CL_TYPE_HTML}, /*

*/ + {"3c503e", "HTML data", CL_TYPE_HTML}, /*

*/ + {"68726566", "HTML data", CL_TYPE_HTML}, /* href */ + {"48726566", "HTML data", CL_TYPE_HTML}, /* Href */ + {"48524546", "HTML data", CL_TYPE_HTML}, /* HREF */ + {"3c68746d6c3e", "HTML data", CL_TYPE_HTML}, /* */ + {"3c48544d4c3e", "HTML data", CL_TYPE_HTML}, /* */ + {"3c48746d6c3e", "HTML data", CL_TYPE_HTML}, /* */ + {"3c686561643e", "HTML data", CL_TYPE_HTML}, /* */ + {"3c484541443e", "HTML data", CL_TYPE_HTML}, /* */ + {"3c486561643e", "HTML data", CL_TYPE_HTML}, /* */ + {"3c666f6e74", "HTML data", CL_TYPE_HTML}, /* */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, /* 0x0X */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* 0x1X */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x2X */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x3X */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x4X */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x5X */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x6X */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 0x7X */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x8X */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x9X */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xaX */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xbX */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xcX */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xdX */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xeX */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* 0xfX */ +}; + +cli_file_t cli_filetype(const unsigned char *buf, size_t buflen) +{ + int i, text = 1, len; + + + for(i = 0; cli_magic[i].magic; i++) { + if(buflen >= cli_magic[i].offset+cli_magic[i].length) { + if(memcmp(buf+cli_magic[i].offset, cli_magic[i].magic, cli_magic[i].length) == 0) { + cli_dbgmsg("Recognized %s file\n", cli_magic[i].descr); + return cli_magic[i].type; + } + } + } + +/* improve or drop this code + * https://wwws.clamav.net/bugzilla/show_bug.cgi?id=373 + * + buflen < 25 ? (len = buflen) : (len = 25); + for(i = 0; i < len; i++) + if(!iscntrl(buf[i]) && !isprint(buf[i]) && !internat[buf[i] & 0xff]) { + text = 0; + break; + } +*/ + return text ? CL_TYPE_UNKNOWN_TEXT : CL_TYPE_UNKNOWN_DATA; +} + +int is_tar(unsigned char *buf, unsigned int nbytes); + +cli_file_t cli_filetype2(int desc, const struct cl_engine *engine) +{ + unsigned char smallbuff[MAGIC_BUFFER_SIZE + 1], *decoded, *bigbuff; + int bread, sret; + cli_file_t ret = CL_TYPE_UNKNOWN_DATA; + struct cli_matcher *root; + struct cli_ac_data mdata; + + + memset(smallbuff, 0, sizeof(smallbuff)); + if((bread = read(desc, smallbuff, MAGIC_BUFFER_SIZE)) > 0) + ret = cli_filetype(smallbuff, bread); + + if(engine && ret == CL_TYPE_UNKNOWN_TEXT) { + root = engine->root[0]; + if(!root) + return ret; + + if(cli_ac_initdata(&mdata, root->ac_partsigs, AC_DEFAULT_TRACKLEN)) + return ret; + + sret = cli_ac_scanbuff(smallbuff, bread, NULL, engine->root[0], &mdata, 1, 0, 0, -1, NULL); + + cli_ac_freedata(&mdata); + + if(sret >= CL_TYPENO) { + ret = sret; + } else { + if(cli_ac_initdata(&mdata, root->ac_partsigs, AC_DEFAULT_TRACKLEN)) + return ret; + + decoded = (unsigned char *) cli_utf16toascii((char *) smallbuff, bread); + if(decoded) { + sret = cli_ac_scanbuff(decoded, strlen((char *) decoded), NULL, engine->root[0], &mdata, 1, 0, 0, -1, NULL); + free(decoded); + if(sret == CL_TYPE_HTML) + ret = CL_TYPE_HTML_UTF16; + } + cli_ac_freedata(&mdata); + +#ifdef CL_EXPERIMENTAL + if(ret != CL_TYPE_HTML_UTF16) { + struct entity_conv conv; + const size_t conv_size = 2*bread < 256 ? 256 : 2*bread; + + if(init_entity_converter(&conv,UNKNOWN,conv_size) == 0) { + int end = 0; + m_area_t area; + area.buffer = (unsigned char *) smallbuff; + area.length = bread; + area.offset = 0; + + while(!end) { + if(cli_ac_initdata(&mdata, root->ac_partsigs, AC_DEFAULT_TRACKLEN)) + return ret; + + decoded = encoding_norm_readline(&conv, NULL, &area, bread); + + if(decoded) { + sret = cli_ac_scanbuff(decoded, strlen((const char *) decoded), NULL, engine->root[0], &mdata, 1, 0, 0, -1, NULL); + free(decoded); + if(sret == CL_TYPE_HTML) { + ret = CL_TYPE_HTML; + end = 1; + } + } else + end = 1; + + cli_ac_freedata(&mdata); + } + + entity_norm_done(&conv); + + } else { + cli_warnmsg("cli_filetype2: Error initializing entity converter\n"); + } + } +#endif /* CL_EXPERIMENTAL */ + } + } + + if(ret == CL_TYPE_UNKNOWN_DATA || ret == CL_TYPE_UNKNOWN_TEXT) { + + if(!(bigbuff = (unsigned char *) cli_calloc(37638 + 1, sizeof(unsigned char)))) + return ret; + + lseek(desc, 0, SEEK_SET); + if((bread = read(desc, bigbuff, 37638)) > 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; + } + } + + if(ret == CL_TYPE_UNKNOWN_DATA || ret == CL_TYPE_UNKNOWN_TEXT) { + + if(!memcmp(bigbuff + 32769, "CD001" , 5) || !memcmp(bigbuff + 37633, "CD001" , 5)) { + cli_dbgmsg("Recognized ISO 9660 CD-ROM data\n"); + ret = CL_TYPE_DATA; + } else if(!memcmp(bigbuff + 32776, "CDROM" , 5)) { + cli_dbgmsg("Recognized High Sierra CD-ROM data\n"); + ret = CL_TYPE_DATA; + } + } + + free(bigbuff); + } + + return ret; +} + +int cli_addtypesigs(struct cl_engine *engine) +{ + int i, ret; + struct cli_matcher *root; + + + if(!engine->root[0]) { + cli_dbgmsg("cli_addtypesigs: Need to allocate AC trie in engine->root[0]\n"); + root = engine->root[0] = (struct cli_matcher *) cli_calloc(1, sizeof(struct cli_matcher)); + if(!root) { + cli_errmsg("cli_addtypesigs: Can't initialise AC pattern matcher\n"); + return CL_EMEM; + } + + if(engine->ncore) { + /* + cli_dbgmsg("cli_addtypesigs: AC depth 10 (ncore mode)\n"); + cli_ac_setdepth(10); + */ + } + + root->ac_root = (struct cli_ac_node *) cli_calloc(1, sizeof(struct cli_ac_node)); + if(!root->ac_root) { + cli_errmsg("cli_addtypesigs: Can't initialise AC pattern matcher\n"); + /* No need to free previously allocated memory here - all engine + * elements will be properly freed by cl_free() + */ + return CL_EMEM; + } + } else { + root = engine->root[0]; + } + + for(i = 0; cli_smagic[i].sig; i++) { + if((ret = cli_parse_add(root, cli_smagic[i].descr, cli_smagic[i].sig, cli_smagic[i].type, NULL, 0))) { + cli_errmsg("cli_addtypesigs: Problem adding signature for %s\n", cli_smagic[i].descr); + return ret; + } + } + + return 0; +} diff -dPNur clamav-0.90.1/libclamav/filetypes.h clamav-0.90.1-new/libclamav/filetypes.h --- clamav-0.90.1/libclamav/filetypes.h 2007-03-02 00:45:36.000000000 +0100 +++ clamav-0.90.1-new/libclamav/filetypes.h 2007-03-29 14:11:58.000000000 +0200 @@ -39,6 +39,7 @@ CL_TYPE_ZIP, CL_TYPE_BZ, CL_TYPE_RAR, + CL_TYPE_7ZIP, CL_TYPE_MSSZDD, CL_TYPE_MSOLE2, CL_TYPE_MSCAB, diff -dPNur clamav-0.90.1/libclamav/filetypes.h.orig clamav-0.90.1-new/libclamav/filetypes.h.orig --- clamav-0.90.1/libclamav/filetypes.h.orig 1970-01-01 01:00:00.000000000 +0100 +++ clamav-0.90.1-new/libclamav/filetypes.h.orig 2007-03-02 00:45:36.000000000 +0100 @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2002 - 2005 Tomasz Kojm + * With enhancements from Thomas Lamy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef __FILETYPES_H +#define __FILETYPES_H + +#include + +#define MAGIC_BUFFER_SIZE 256 +#define CL_TYPENO 500 +#define SFX_MAX_TESTS 10 + +typedef enum { + CL_TYPE_UNKNOWN_TEXT = CL_TYPENO, + CL_TYPE_UNKNOWN_DATA, + CL_TYPE_MSEXE, + CL_TYPE_ELF, + CL_TYPE_DATA, + CL_TYPE_POSIX_TAR, + CL_TYPE_OLD_TAR, + CL_TYPE_GZ, + CL_TYPE_ZIP, + CL_TYPE_BZ, + CL_TYPE_RAR, + CL_TYPE_MSSZDD, + CL_TYPE_MSOLE2, + CL_TYPE_MSCAB, + CL_TYPE_MSCHM, + CL_TYPE_SIS, + CL_TYPE_SCRENC, + CL_TYPE_GRAPHICS, + CL_TYPE_RIFF, + CL_TYPE_BINHEX, + CL_TYPE_TNEF, + CL_TYPE_CRYPTFF, + CL_TYPE_PDF, + CL_TYPE_UUENCODED, + CL_TYPE_HTML_UTF16, + CL_TYPE_RTF, + + /* bigger numbers have higher priority (in o-t-f detection) */ + CL_TYPE_HTML, /* on the fly */ + CL_TYPE_MAIL, /* magic + on the fly */ + CL_TYPE_SFX, /* foo SFX marker */ + CL_TYPE_ZIPSFX, /* on the fly */ + CL_TYPE_RARSFX, /* on the fly */ + CL_TYPE_CABSFX + +} cli_file_t; + +struct cli_matched_type { + cli_file_t type; + off_t offset; + unsigned short cnt; + struct cli_matched_type *next; +}; + +cli_file_t cli_filetype(const unsigned char *buf, size_t buflen); +cli_file_t cli_filetype2(int desc, const struct cl_engine *engine); +int cli_addtypesigs(struct cl_engine *engine); + +#endif diff -dPNur clamav-0.90.1/libclamav/Makefile.am clamav-0.90.1-new/libclamav/Makefile.am --- clamav-0.90.1/libclamav/Makefile.am 2007-03-02 00:44:21.000000000 +0100 +++ clamav-0.90.1-new/libclamav/Makefile.am 2007-03-29 15:20:51.000000000 +0200 @@ -19,7 +19,7 @@ INCLUDES = -I$(top_srcdir) -I@srcdir@/unrar -libclamav_la_LIBADD = @LIBCLAMAV_LIBS@ @THREAD_LIBS@ +libclamav_la_LIBADD = @LIBCLAMAV_LIBS@ @THREAD_LIBS@ -lun7zip libclamav_la_LDFLAGS = @TH_SAFE@ -version-info @LIBCLAMAV_VERSION@ -no-undefined @@ -52,6 +52,8 @@ scanners.h \ filetypes.c \ filetypes.h \ + un7zip.c \ + un7zip.h \ rtf.c \ rtf.h \ blob.c \ diff -dPNur clamav-0.90.1/libclamav/others.c clamav-0.90.1-new/libclamav/others.c --- clamav-0.90.1/libclamav/others.c 2007-02-28 22:59:01.000000000 +0100 +++ clamav-0.90.1-new/libclamav/others.c 2007-03-29 14:11:58.000000000 +0200 @@ -162,6 +162,8 @@ return "File size limit exceeded"; case CL_EMAXFILES: return "Files number limit exceeded"; + case CL_E7ZIP: + return "7zip module failure"; case CL_ERAR: return "RAR module failure"; case CL_EZIP: diff -dPNur clamav-0.90.1/libclamav/others.c.orig clamav-0.90.1-new/libclamav/others.c.orig --- clamav-0.90.1/libclamav/others.c.orig 1970-01-01 01:00:00.000000000 +0100 +++ clamav-0.90.1-new/libclamav/others.c.orig 2007-02-28 22:59:01.000000000 +0100 @@ -0,0 +1,940 @@ +/* + * Copyright (C) 1999 - 2005 Tomasz Kojm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#if HAVE_CONFIG_H +#include "clamav-config.h" +#endif + +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#ifndef C_WINDOWS +#include +#include +#include +#endif +#include +#include +#ifndef C_WINDOWS +#include +#endif +#include +#include "target.h" +#ifndef C_WINDOWS +#include +#endif +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_MALLOC_H +#include +#endif +#if defined(_MSC_VER) && defined(_DEBUG) +#include +#endif + +#ifdef CL_THREAD_SAFE +# include +static pthread_mutex_t cli_gentempname_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2) +#include +#include +#endif + +#include "clamav.h" +#include "others.h" +#include "md5.h" +#include "cltypes.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#ifdef C_WINDOWS +#undef P_tmpdir +#define P_tmpdir "C:\\WINDOWS\\TEMP" +#endif + +#define CL_FLEVEL 14 /* don't touch it */ + +short cli_debug_flag = 0, cli_leavetemps_flag = 0; + +static unsigned char name_salt[16] = { 16, 38, 97, 12, 8, 4, 72, 196, 217, 144, 33, 124, 18, 11, 17, 253 }; + + +void cli_warnmsg(const char *str, ...) +{ + va_list args; + int sz = sizeof("LibClamAV Warning: ") - 1; + char buff[256]; + + strncpy(buff, "LibClamAV Warning: ", sz); + va_start(args, str); + vsnprintf(buff + sz, sizeof(buff) - sz, str, args); + buff[sizeof(buff) - 1] = '\0'; + fputs(buff, stderr); + va_end(args); +} + +void cli_errmsg(const char *str, ...) +{ + va_list args; + int sz = sizeof("LibClamAV Error: ") - 1; + char buff[256]; + + strncpy(buff, "LibClamAV Error: ", sz); + va_start(args, str); + vsnprintf(buff + sz, sizeof(buff) - sz, str, args); + buff[sizeof(buff) - 1] = '\0'; + fputs(buff, stderr); + va_end(args); +} + +void cli_dbgmsg(const char *str, ...) +{ + + if(cli_debug_flag) { + va_list args; + int sz = sizeof("LibClamAV debug: ") - 1; + char buff[BUFSIZ]; + + memcpy(buff, "LibClamAV debug: ", sz); + va_start(args, str); + vsnprintf(buff + sz, sizeof(buff) - sz, str, args); + buff[sizeof(buff) - 1] = '\0'; + fputs(buff, stderr); + va_end(args); + } else + return; +} + +void cl_debug(void) +{ + cli_debug_flag = 1; +} + +unsigned int cl_retflevel(void) +{ + return CL_FLEVEL; +} + +const char *cl_retver(void) +{ + return VERSION; +} + +const char *cl_strerror(int clerror) +{ + switch(clerror) { + case CL_CLEAN: + return "No viruses detected"; + case CL_VIRUS: + return "Virus(es) detected"; + case CL_EMAXREC: + return "Recursion limit exceeded"; + case CL_EMAXSIZE: + return "File size limit exceeded"; + case CL_EMAXFILES: + return "Files number limit exceeded"; + case CL_ERAR: + return "RAR module failure"; + case CL_EZIP: + return "Zip module failure"; + case CL_EGZIP: + return "GZip module failure"; + case CL_EMSCOMP: + return "MS Expand module failure"; + case CL_EMSCAB: + return "MS CAB module failure"; + case CL_EOLE2: + return "OLE2 module failure"; + case CL_ETMPFILE: + return "Unable to create temporary file"; + case CL_ETMPDIR: + return "Unable to create temporary directory"; + case CL_EFSYNC: + return "Unable to synchronize file <-> disk"; + case CL_EMEM: + return "Unable to allocate memory"; + case CL_EOPEN: + return "Unable to open file or directory"; + case CL_EMALFDB: + return "Malformed database"; + case CL_EPATSHORT: + return "Too short pattern detected"; + case CL_ECVD: + return "Broken or not a CVD file"; + case CL_ECVDEXTR: + return "CVD extraction failure"; + case CL_EMD5: + return "MD5 verification error"; + case CL_EDSIG: + return "Digital signature verification error"; + case CL_ENULLARG: + return "Null argument passed while initialized is required"; + case CL_EIO: + return "Input/Output error"; + case CL_EFORMAT: + return "Bad format or broken data"; + case CL_ESUPPORT: + return "Not supported data format"; + case CL_ENCINIT: + return "NodalCore initialization failure"; + case CL_ENCLOAD: + return "Error loading NodalCore database"; + case CL_ENCIO: + return "NodalCore accelerator Input/Output error"; + case CL_ELOCKDB: + return "Unable to lock database directory"; + default: + return "Unknown error code"; + } +} + +unsigned char *cli_md5digest(int desc) +{ + unsigned char *digest; + char buff[FILEBUFF]; + cli_md5_ctx ctx; + int bytes; + + + if(!(digest = cli_malloc(16))) + return NULL; + + cli_md5_init(&ctx); + + while((bytes = cli_readn(desc, buff, FILEBUFF))) + cli_md5_update(&ctx, buff, bytes); + + cli_md5_final(digest, &ctx); + + return digest; +} + +char *cli_md5stream(FILE *fs, unsigned char *digcpy) +{ + unsigned char digest[16]; + char buff[FILEBUFF]; + cli_md5_ctx ctx; + char *md5str, *pt; + int i, bytes; + + + cli_md5_init(&ctx); + + while((bytes = fread(buff, 1, FILEBUFF, fs))) + cli_md5_update(&ctx, buff, bytes); + + cli_md5_final(digest, &ctx); + + if(!(md5str = (char *) cli_calloc(32 + 1, sizeof(char)))) + return NULL; + + pt = md5str; + for(i = 0; i < 16; i++) { + sprintf(pt, "%02x", digest[i]); + pt += 2; + } + + if(digcpy) + memcpy(digcpy, digest, 16); + + return md5str; +} + +char *cli_md5file(const char *filename) +{ + FILE *fs; + char *md5str; + + + if((fs = fopen(filename, "rb")) == NULL) { + cli_errmsg("cli_md5file(): Can't read file %s\n", filename); + return NULL; + } + + md5str = cli_md5stream(fs, NULL); + fclose(fs); + + return md5str; +} + +static char *cli_md5buff(const char *buffer, unsigned int len, unsigned char *dig) +{ + unsigned char digest[16]; + char *md5str, *pt; + cli_md5_ctx ctx; + int i; + + + cli_md5_init(&ctx); + cli_md5_update(&ctx, (const unsigned char *) buffer, len); + cli_md5_final(digest, &ctx); + + if(dig) + memcpy(dig, digest, 16); + + if(!(md5str = (char *) cli_calloc(32 + 1, sizeof(char)))) + return NULL; + + pt = md5str; + for(i = 0; i < 16; i++) { + sprintf(pt, "%02x", digest[i]); + pt += 2; + } + + return md5str; +} + +void *cli_malloc(size_t size) +{ + void *alloc; + + + if(!size || size > CLI_MAX_ALLOCATION) { + cli_errmsg("cli_malloc(): Attempt to allocate %u bytes. Please report to http://bugs.clamav.net\n", size); + return NULL; + } + +#if defined(_MSC_VER) && defined(_DEBUG) + alloc = _malloc_dbg(size, _NORMAL_BLOCK, __FILE__, __LINE__); +#else + alloc = malloc(size); +#endif + + if(!alloc) { + cli_errmsg("cli_malloc(): Can't allocate memory (%u bytes).\n", size); + perror("malloc_problem"); + /* _exit(1); */ + return NULL; + } else return alloc; +} + +void *cli_calloc(size_t nmemb, size_t size) +{ + void *alloc; + + + if(!size || size > CLI_MAX_ALLOCATION) { + cli_errmsg("cli_calloc(): Attempt to allocate %u bytes. Please report to http://bugs.clamav.net\n", size); + return NULL; + } + +#if defined(_MSC_VER) && defined(_DEBUG) + alloc = _calloc_dbg(nmemb, size, _NORMAL_BLOCK, __FILE__, __LINE__); +#else + alloc = calloc(nmemb, size); +#endif + + if(!alloc) { + cli_errmsg("cli_calloc(): Can't allocate memory (%u bytes).\n", nmemb * size); + perror("calloc_problem"); + /* _exit(1); */ + return NULL; + } else return alloc; +} + +void *cli_realloc(void *ptr, size_t size) +{ + void *alloc; + + + if(!size || size > CLI_MAX_ALLOCATION) { + cli_errmsg("cli_realloc(): Attempt to allocate %u bytes. Please report to http://bugs.clamav.net\n", size); + return NULL; + } + + alloc = realloc(ptr, size); + + if(!alloc) { + cli_errmsg("cli_realloc(): Can't re-allocate memory to %u bytes.\n", size); + perror("realloc_problem"); + return NULL; + } else return alloc; +} + +char *cli_strdup(const char *s) +{ + char *alloc; + + + if(s == NULL) { + cli_errmsg("cli_strdup(): s == NULL. Please report to http://bugs.clamav.net\n"); + return NULL; + } + +#if defined(_MSC_VER) && defined(_DEBUG) + alloc = _strdup_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__); +#else + alloc = strdup(s); +#endif + + if(!alloc) { + cli_errmsg("cli_strdup(): Can't allocate memory (%u bytes).\n", strlen(s)); + perror("strdup_problem"); + return NULL; + } + + return alloc; +} + +unsigned int cli_rndnum(unsigned int max) +{ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *) 0); + srand(tv.tv_usec+clock()); + + return rand() % max; +} + +void cl_settempdir(const char *dir, short leavetemps) +{ + char *var; + + if(dir) { + var = (char *) cli_malloc(8 + strlen(dir)); + sprintf(var, "TMPDIR=%s", dir); + if(!putenv(var)) + cli_dbgmsg("Setting %s as global temporary directory\n", dir); + else + cli_warnmsg("Can't set TMPDIR variable - insufficient space in the environment.\n"); + + /* WARNING: var must not be released - see putenv(3) */ + } + + cli_leavetemps_flag = leavetemps; +} + +static char *cli_gentempname(const char *dir) +{ + char *name, *tmp; + const char *mdir; + unsigned char salt[16 + 32]; + int i; + + if(!dir) { + if((mdir = getenv("TMPDIR")) == NULL) +#ifdef P_tmpdir + mdir = P_tmpdir; +#else + mdir = "/tmp"; +#endif + } else + mdir = dir; + + name = (char *) cli_calloc(strlen(mdir) + 1 + 32 + 1 + 7, sizeof(char)); + if(!name) { + cli_dbgmsg("cli_gentempname('%s'): out of memory\n", mdir); + return NULL; + } + +#ifdef CL_THREAD_SAFE + pthread_mutex_lock(&cli_gentempname_mutex); +#endif + + memcpy(salt, name_salt, 16); + + for(i = 16; i < 48; i++) + salt[i] = cli_rndnum(256); + + tmp = cli_md5buff((char *) salt, 48, name_salt); + +#ifdef CL_THREAD_SAFE + pthread_mutex_unlock(&cli_gentempname_mutex); +#endif + + if(!tmp) { + free(name); + cli_dbgmsg("cli_gentempname('%s'): out of memory\n", mdir); + return NULL; + } + +#ifdef C_WINDOWS + sprintf(name, "%s\\clamav-", mdir); +#else + sprintf(name, "%s/clamav-", mdir); +#endif + strncat(name, tmp, 32); + free(tmp); + + return(name); +} + +char *cli_gentemp(const char *dir) +{ + char *name; + + name = cli_gentempname(dir); + + return(name); +} + + +char *cli_gentempdir(const char *dir) +{ + char *name; + + name = cli_gentempname(dir); + + if(name && mkdir(name, 0700)) { + cli_dbgmsg("cli_gentempdir(): can't create temp directory: %s\n", name); + free(name); + name = NULL; + } + + return(name); +} + +char *cli_gentempdesc(const char *dir, int *fd) +{ + char *name; + + name = cli_gentempname(dir); + + if(name && ((*fd = open(name, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0)) { + cli_dbgmsg("cli_gentempdesc(): can't create temp file: %s\n", name); + free(name); + name = NULL; + } + + return(name); +} + +char *cli_gentempstream(const char *dir, FILE **fs) +{ + char *name; + + name = cli_gentempname(dir); + + if(name && ((*fs = fopen(name, "wb+")) == NULL)) { + cli_dbgmsg("cli_gentempstream(): can't create temp file: %s\n", name); + free(name); + name = NULL; + } + + return(name); +} + +#ifdef C_WINDOWS +/* + * Windows doesn't allow you to delete a directory while it is still open + */ +int +cli_rmdirs(const char *name) +{ + int rc; + struct stat statb; + DIR *dd; + struct dirent *dent; +#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2) + union { + struct dirent d; + char b[offsetof(struct dirent, d_name) + NAME_MAX + 1]; + } result; +#endif + + + if(stat(name, &statb) < 0) { + cli_warnmsg("Can't locate %s: %s\n", name, strerror(errno)); + return -1; + } + + if(!S_ISDIR(statb.st_mode)) { + if(unlink(name) < 0) { + cli_warnmsg("Can't remove %s: %s\n", name, strerror(errno)); + return -1; + } + return 0; + } + + if((dd = opendir(name)) == NULL) + return -1; + + rc = 0; + +#ifdef HAVE_READDIR_R_3 + while((readdir_r(dd, &result.d, &dent) == 0) && dent) { +#elif defined(HAVE_READDIR_R_2) + while((dent = (struct dirent *)readdir_r(dd, &result.d)) != NULL) { +#else + while((dent = readdir(dd)) != NULL) { +#endif + char *fname; + + if(strcmp(dent->d_name, ".") == 0) + continue; + if(strcmp(dent->d_name, "..") == 0) + continue; + + fname = cli_malloc(strlen(name) + strlen(dent->d_name) + 2, sizeof(char)); + if(fname == NULL) { + closedir(dd); + return -1; + } + + sprintf(fname, "%s\\%s", name, dent->d_name); + rc = cli_rmdirs(fname); + free(fname); + if(rc != 0) + break; + } + + closedir(dd); + + if(rmdir(name) < 0) { + cli_errmsg("Can't remove temporary directory %s: %s\n", name, strerror(errno)); + return -1; + } + + return rc; +} +#else +int cli_rmdirs(const char *dirname) +{ + DIR *dd; + struct dirent *dent; +#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2) + union { + struct dirent d; + char b[offsetof(struct dirent, d_name) + NAME_MAX + 1]; + } result; +#endif + struct stat maind, statbuf; + char *fname; + int ret; + + + chmod(dirname, 0700); + if((dd = opendir(dirname)) != NULL) { + while(stat(dirname, &maind) != -1) { + if(!rmdir(dirname)) break; + if(errno != ENOTEMPTY && errno != EEXIST && errno != EBADF) { + cli_errmsg("Can't remove temporary directory %s: %s\n", dirname, strerror(errno)); + closedir(dd); + return -1; + } + +#ifdef HAVE_READDIR_R_3 + while(!readdir_r(dd, &result.d, &dent) && dent) { +#elif defined(HAVE_READDIR_R_2) + while((dent = (struct dirent *) readdir_r(dd, &result.d))) { +#else + while((dent = readdir(dd))) { +#endif +#if (!defined(C_CYGWIN)) && (!defined(C_INTERIX)) && (!defined(C_WINDOWS)) + if(dent->d_ino) +#endif + { + if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) { + fname = cli_malloc(strlen(dirname) + strlen(dent->d_name) + 2); + if(!fname) { + closedir(dd); + return -1; + } + +#ifdef C_WINDOWS + sprintf(fname, "%s\\%s", dirname, dent->d_name); +#else + sprintf(fname, "%s/%s", dirname, dent->d_name); +#endif + + /* stat the file */ + if(lstat(fname, &statbuf) != -1) { + if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) { + if(rmdir(fname) == -1) { /* can't be deleted */ + if(errno == EACCES) { + cli_errmsg("Can't remove some temporary directories due to access problem.\n"); + closedir(dd); + free(fname); + return -1; + } + ret = cli_rmdirs(fname); + if(ret) { + cli_warnmsg("Can't remove directory %s\n", fname); + free(fname); + closedir(dd); + return -1; + } + } + } else + if(unlink(fname) < 0) { + cli_warnmsg("Couldn't remove %s: %s\n", fname, strerror(errno)); + free(fname); + closedir(dd); + return -1; + } + } + + free(fname); + } + } + } + + rewinddir(dd); + } + + } else { + return -1; + } + + closedir(dd); + return 0; +} +#endif + +/* Function: readn + Try hard to read the requested number of bytes +*/ +int cli_readn(int fd, void *buff, unsigned int count) +{ + int retval; + unsigned int todo; + unsigned char *current; + + + todo = count; + current = (unsigned char *) buff; + + do { + retval = read(fd, current, todo); + if (retval == 0) { + return (count - todo); + } + if (retval < 0) { + if (errno == EINTR) { + continue; + } + cli_errmsg("cli_readn: read error: %s\n", strerror(errno)); + return -1; + } + todo -= retval; + current += retval; + } while (todo > 0); + + + return count; +} + +/* Function: writen + Try hard to write the specified number of bytes +*/ +int cli_writen(int fd, const void *buff, unsigned int count) +{ + int retval; + unsigned int todo; + const unsigned char *current; + + + todo = count; + current = (const unsigned char *) buff; + + do { + retval = write(fd, current, todo); + if (retval < 0) { + if (errno == EINTR) { + continue; + } + cli_errmsg("cli_writen: write error: %s\n", strerror(errno)); + return -1; + } + todo -= retval; + current += retval; + } while (todo > 0); + + + return count; +} + +int32_t cli_readint32(const char *buff) +{ + int32_t ret; + +#if WORDS_BIGENDIAN == 0 + ret = *(const int32_t *) buff; +#else + ret = buff[0] & 0xff; + ret |= (buff[1] & 0xff) << 8; + ret |= (buff[2] & 0xff) << 16; + ret |= (buff[3] & 0xff) << 24; +#endif + + return ret; +} + +void cli_writeint32(char *offset, uint32_t value) +{ + offset[0] = value & 0xff; + offset[1] = (value & 0xff00) >> 8; + offset[2] = (value & 0xff0000) >> 16; + offset[3] = (value & 0xff000000) >> 24; +} + +int cli_filecopy(const char *src, const char *dest) +{ + char *buffer; + int s, d, bytes; + + + if((s = open(src, O_RDONLY|O_BINARY)) == -1) + return -1; + + if((d = open(dest, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, S_IRWXU)) == -1) { + close(s); + return -1; + } + + if(!(buffer = cli_malloc(FILEBUFF))) + return -1; + + while((bytes = cli_readn(s, buffer, FILEBUFF)) > 0) + cli_writen(d, buffer, bytes); + + free(buffer); + close(s); + + return close(d); +} + +/* Implement a generic bitset, trog@clamav.net */ + +#define BITS_PER_CHAR (8) +#define BITSET_DEFAULT_SIZE (1024) +#define FALSE (0) +#define TRUE (1) + +static unsigned long nearest_power(unsigned long num) +{ + unsigned long n = BITSET_DEFAULT_SIZE; + + while (n < num) { + n <<= 1; + if (n == 0) { + return num; + } + } + return n; +} + +bitset_t *cli_bitset_init(void) +{ + bitset_t *bs; + + bs = cli_malloc(sizeof(bitset_t)); + if (!bs) { + return NULL; + } + bs->length = BITSET_DEFAULT_SIZE; + bs->bitset = cli_calloc(BITSET_DEFAULT_SIZE, 1); + return bs; +} + +void cli_bitset_free(bitset_t *bs) +{ + if (!bs) { + return; + } + if (bs->bitset) { + free(bs->bitset); + } + free(bs); +} + +static bitset_t *bitset_realloc(bitset_t *bs, unsigned long min_size) +{ + unsigned long new_length; + + new_length = nearest_power(min_size); + bs->bitset = (unsigned char *) cli_realloc(bs->bitset, new_length); + if (!bs->bitset) { + return NULL; + } + memset(bs->bitset+bs->length, 0, new_length-bs->length); + bs->length = new_length; + return bs; +} + +int cli_bitset_set(bitset_t *bs, unsigned long bit_offset) +{ + unsigned long char_offset; + + char_offset = bit_offset / BITS_PER_CHAR; + bit_offset = bit_offset % BITS_PER_CHAR; + + if (char_offset >= bs->length) { + bs = bitset_realloc(bs, char_offset+1); + if (!bs) { + return FALSE; + } + } + bs->bitset[char_offset] |= ((unsigned char)1 << bit_offset); + return TRUE; +} + +int cli_bitset_test(bitset_t *bs, unsigned long bit_offset) +{ + unsigned long char_offset; + + char_offset = bit_offset / BITS_PER_CHAR; + bit_offset = bit_offset % BITS_PER_CHAR; + + if (char_offset >= bs->length) { + return FALSE; + } + return (bs->bitset[char_offset] & ((unsigned char)1 << bit_offset)); +} + + +/* + * Code from NJH + * Different operating systems allow different characters in their filenames + * FIXME: What does QNX want? There is no #ifdef C_QNX, but if there were + * it may be best to treat it like MSDOS + */ +void +cli_sanitise_filename(char *name) +{ + if(name == NULL) + return; + + while(*name) { +#ifdef C_DARWIN + *name &= '\177'; +#endif + /* Also check for tab - "Heinz Martin" */ +#if defined(MSDOS) || defined(C_CYGWIN) || defined(C_WINDOWS) || defined(C_OS2) + if(strchr("%/*?<>|\\\"+=,;:\t ~", *name)) +#else + if(*name == '/') +#endif + *name = '_'; + name++; + } +} diff -dPNur clamav-0.90.1/libclamav/scanners.c clamav-0.90.1-new/libclamav/scanners.c --- clamav-0.90.1/libclamav/scanners.c 2007-03-02 00:44:49.000000000 +0100 +++ clamav-0.90.1-new/libclamav/scanners.c 2007-03-29 14:57:28.000000000 +0200 @@ -65,6 +65,7 @@ #include "matcher-bm.h" #include "matcher.h" #include "unrar.h" +#include "un7zip.h" #include "ole2_extract.h" #include "vba_extract.h" #include "msexpand.h" @@ -984,6 +985,40 @@ return 0; } +static int cli_scan7zip(int desc, cli_ctx *ctx) { + const char *tmpdir; + char *dir; + int ret = CL_CLEAN; + + + cli_dbgmsg("in cli_scan7zip()\n"); + + if((tmpdir = getenv("TMPDIR")) == NULL) +#ifdef P_tmpdir + tmpdir = P_tmpdir; +#else + tmpdir = "/tmp"; +#endif + + /* generate temporary directory */ + dir = cli_gentemp(tmpdir); + if(mkdir(dir, 0700)) { + cli_errmsg("7zip: Can't create temporary directory %s\n", dir); + return CL_ETMPDIR; + } + + if((ret = cli_un7zip(dir, desc))) + cli_dbgmsg("7zip: %s\n", cl_strerror(ret)); + else + ret = cli_scandir(dir, ctx); + + if(!cli_leavetemps_flag) + cli_rmdirs(dir); + + free(dir); + return ret; +} + static int cli_vba_scandir(const char *dirname, cli_ctx *ctx) { int ret = CL_CLEAN, i, fd, ofd, data_len; @@ -1808,7 +1843,12 @@ if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR)) ret = cli_scanrar(desc, ctx, 0, NULL); break; - + + case CL_TYPE_7ZIP: + if(SCAN_ARCHIVE) + ret = cli_scan7zip(desc, ctx); + break; + case CL_TYPE_ZIP: if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) ret = cli_scanzip(desc, ctx, 0, NULL); diff -dPNur clamav-0.90.1/libclamav/un7zip.c clamav-0.90.1-new/libclamav/un7zip.c --- clamav-0.90.1/libclamav/un7zip.c 1970-01-01 01:00:00.000000000 +0100 +++ clamav-0.90.1-new/libclamav/un7zip.c 2007-03-29 14:11:58.000000000 +0200 @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2005 McMCC + * + * Support check archives 7zip + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +static char const rcsid[] = "$Id: un7zip.c,v 1.0 2005/09/05 01:40:44 mcmcc Exp $"; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "clamav.h" +#include "others.h" +#include "un7zip.h" +#include "mbox.h" +#include "blob.h" + +int cli_un7zip(const char *dir, int desc) +{ + int fd, s_buff, res; + char buff[4096], uname[48]; + const char *tmpdir; + FILE *out; + + if((tmpdir = getenv("TMPDIR")) == NULL) +#ifdef P_tmpdir + tmpdir = P_tmpdir; +#else + tmpdir = "/tmp"; +#endif + + sprintf(uname, "%s/szpXXXXXX", tmpdir); + + if((fd = mkstemp(uname)) < 0 || (out = fdopen(fd, "w+")) == NULL) + { + + cli_dbgmsg("cli_un7zip: can't generate temporary file %s or open descriptor %d.\n", + uname, fd); + if(fd >= 0) + close(fd); + unlink(uname); + return CL_ETMPFILE; + } + + while((s_buff=read(desc, buff, sizeof(buff))) > 0) + { + if(fwrite(buff, 1, s_buff, out) != s_buff) + { + cli_dbgmsg("cli_un7zip: can't write to file %s.\n", uname); + fclose(out); + close(fd); + unlink(uname); + return CL_EOPEN; + } + } + fclose(out); + close(fd); + + res = un7zip(uname, dir, EXTRACT_7Z); + unlink(uname); + if(res) return CL_E7ZIP; + return CL_CLEAN; +} diff -dPNur clamav-0.90.1/libclamav/un7zip.h clamav-0.90.1-new/libclamav/un7zip.h --- clamav-0.90.1/libclamav/un7zip.h 1970-01-01 01:00:00.000000000 +0100 +++ clamav-0.90.1-new/libclamav/un7zip.h 2007-03-29 14:11:58.000000000 +0200 @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2005 McMCC + * + * Support check archives 7zip + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +int cli_un7zip(const char *dir, int desc);