2
* Copyright (C) 2011 Sourcefire, Inc.
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 as
8
* published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23
#include "lzma_iface.h"
29
#include "7z/7zAlloc.h"
30
#include "7z/7zFile.h"
33
static ISzAlloc allocImp = { __lzma_wrap_alloc, __lzma_wrap_free}, allocTempImp = { __lzma_wrap_alloc, __lzma_wrap_free};
35
static SRes FileInStream_fmap_Read(void *pp, void *buf, size_t *size) {
36
CFileInStream *p = (CFileInStream *)pp;
42
read_sz = fmap_readn(p->file.fmap, buf, p->s.curpos, *size);
48
p->s.curpos += read_sz;
54
static SRes FileInStream_fmap_Seek(void *pp, Int64 *pos, ESzSeek origin) {
55
CFileInStream *p = (CFileInStream *)pp;
66
p->s.curpos = p->file.fmap->len + *pos;
76
int cli_7unz (cli_ctx *ctx, size_t offset) {
77
CFileInStream archiveStream;
78
CLookToRead lookStream;
81
UInt16 utf16buf[UTFBUFSZ], *utf16name = utf16buf;
82
int namelen = UTFBUFSZ, found = CL_CLEAN;
83
Int64 begin_of_archive = offset;
84
UInt32 viruses_found = 0;
87
FileInStream_CreateVTable(&archiveStream); */
88
archiveStream.s.Read = FileInStream_fmap_Read;
89
archiveStream.s.Seek = FileInStream_fmap_Seek;
90
archiveStream.s.curpos = 0;
91
archiveStream.file.fmap = *ctx->fmap;
93
LookToRead_CreateVTable(&lookStream, False);
95
if(archiveStream.s.Seek(&archiveStream.s, &begin_of_archive, SZ_SEEK_SET) != 0)
98
lookStream.realStream = &archiveStream.s;
99
LookToRead_Init(&lookStream);
102
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
104
UInt32 i, blockIndex = 0xFFFFFFFF;
106
size_t outBufferSize = 0;
107
unsigned int encrypted = 0;
109
for (i = 0; i < db.db.NumFiles; i++) {
111
size_t outSizeProcessed = 0;
112
const CSzFileItem *f = db.db.Files + i;
117
if((found = cli_checklimits("7unz", ctx, 0, 0, 0)))
123
if(cli_checklimits("7unz", ctx, f->Size, 0, 0))
126
if (!db.FileNameOffsets)
127
newnamelen = 0; /* no filename */
129
newnamelen = SzArEx_GetFileNameUtf16(&db, i, NULL);
130
if (newnamelen > namelen) {
131
if(namelen > UTFBUFSZ)
133
utf16name = cli_malloc(newnamelen*2);
138
namelen = newnamelen;
140
SzArEx_GetFileNameUtf16(&db, i, utf16name);
143
name = (char *)utf16name;
144
for(j=0; j<newnamelen; j++) /* FIXME */
145
name[j] = utf16name[j];
147
cli_dbgmsg("cli_7unz: extracting %s\n", name);
149
res = SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp);
150
if(res == SZ_ERROR_ENCRYPTED) {
152
if(DETECT_ENCRYPTED) {
153
cli_dbgmsg("cli_7unz: Encrypted files found in archive.\n");
154
cli_append_virus(ctx, "Heuristics.Encrypted.7Zip");
162
if(cli_matchmeta(ctx, name, 0, f->Size, encrypted, i, f->CrcDefined ? f->Crc : 0, NULL)) {
169
cli_dbgmsg("cli_unz: extraction failed with %d\n", res);
171
if((found = cli_gentempfd(ctx->engine->tmpdir, &name, &fd)))
174
cli_dbgmsg("cli_7unz: Saving to %s\n", name);
175
if(cli_writen(fd, outBuffer + offset, outSizeProcessed) != outSizeProcessed)
178
if ((found = cli_magic_scandesc(fd, ctx)) == CL_VIRUS)
181
if(!ctx->engine->keeptmp && cli_unlink(name))
185
if(found != CL_CLEAN)
186
if (!(SCAN_ALL && found == CL_VIRUS))
190
IAlloc_Free(&allocImp, outBuffer);
192
SzArEx_Free(&db, &allocImp);
193
if(namelen > UTFBUFSZ)
197
cli_dbgmsg("cli_7unz: completed successfully\n");
198
else if (res == SZ_ERROR_UNSUPPORTED)
199
cli_dbgmsg("cli_7unz: unsupported\n");
200
else if (res == SZ_ERROR_MEM)
201
cli_dbgmsg("cli_7unz: oom\n");
202
else if (res == SZ_ERROR_CRC)
203
cli_dbgmsg("cli_7unz: crc mismatch\n");
205
cli_dbgmsg("cli_7unz: error %d\n", res);
207
if (SCAN_ALL && viruses_found)