"Fossies" - the Fresh Open Source Software Archive

Member "clamav-0.102.3/libclamav/7z_iface.c" (12 May 2020, 7540 Bytes) of package /linux/misc/clamav-0.102.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "7z_iface.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.102.1_vs_0.102.2.

    1 /*
    2  *  Copyright (C) 2013-2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
    3  *  Copyright (C) 2011-2013 Sourcefire, Inc.
    4  *
    5  *  Authors: aCaB
    6  *
    7  *  This program is free software; you can redistribute it and/or modify
    8  *  it under the terms of the GNU General Public License version 2 as
    9  *  published by the Free Software Foundation.
   10  *
   11  *  This program is distributed in the hope that it will be useful,
   12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  *  GNU General Public License for more details.
   15  *
   16  *  You should have received a copy of the GNU General Public License
   17  *  along with this program; if not, write to the Free Software
   18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
   19  *  MA 02110-1301, USA.
   20  */
   21 
   22 #if defined(_WIN32)
   23 #include <WinSock2.h>
   24 #include <Windows.h>
   25 #endif
   26 
   27 #include "clamav.h"
   28 #include "7z_iface.h"
   29 #include "lzma_iface.h"
   30 #include "scanners.h"
   31 #include "others.h"
   32 #include "fmap.h"
   33 
   34 #include "7z/7z.h"
   35 #include "7z/7zAlloc.h"
   36 #include "7z/7zFile.h"
   37 
   38 static ISzAlloc allocImp = {__lzma_wrap_alloc, __lzma_wrap_free}, allocTempImp = {__lzma_wrap_alloc, __lzma_wrap_free};
   39 
   40 static SRes FileInStream_fmap_Read(void *pp, void *buf, size_t *size)
   41 {
   42     CFileInStream *p = (CFileInStream *)pp;
   43     size_t read_sz;
   44 
   45     if (*size == 0)
   46         return 0;
   47 
   48     read_sz = fmap_readn(p->file.fmap, buf, p->s.curpos, *size);
   49     if (read_sz == (size_t)-1) {
   50         *size = 0;
   51         return SZ_ERROR_READ;
   52     }
   53 
   54     p->s.curpos += read_sz;
   55 
   56     *size = read_sz;
   57     return SZ_OK;
   58 }
   59 
   60 static SRes FileInStream_fmap_Seek(void *pp, Int64 *pos, ESzSeek origin)
   61 {
   62     CFileInStream *p = (CFileInStream *)pp;
   63 
   64     switch (origin) {
   65         case SZ_SEEK_SET:
   66             p->s.curpos = *pos;
   67             break;
   68         case SZ_SEEK_CUR:
   69             p->s.curpos += *pos;
   70             *pos = p->s.curpos;
   71             break;
   72         case SZ_SEEK_END:
   73             p->s.curpos = p->file.fmap->len + *pos;
   74             *pos        = p->s.curpos;
   75             break;
   76         default:
   77             return 1;
   78     }
   79     return 0;
   80 }
   81 
   82 #define UTFBUFSZ 256
   83 int cli_7unz(cli_ctx *ctx, size_t offset)
   84 {
   85     CFileInStream archiveStream;
   86     CLookToRead lookStream;
   87     CSzArEx db;
   88     SRes res;
   89     UInt16 utf16buf[UTFBUFSZ], *utf16name = utf16buf;
   90     int namelen            = UTFBUFSZ;
   91     cl_error_t found       = CL_CLEAN;
   92     Int64 begin_of_archive = offset;
   93     UInt32 viruses_found   = 0;
   94 
   95     /* Replacement for
   96        FileInStream_CreateVTable(&archiveStream); */
   97     archiveStream.s.Read    = FileInStream_fmap_Read;
   98     archiveStream.s.Seek    = FileInStream_fmap_Seek;
   99     archiveStream.s.curpos  = 0;
  100     archiveStream.file.fmap = *ctx->fmap;
  101 
  102     LookToRead_CreateVTable(&lookStream, False);
  103 
  104     if (archiveStream.s.Seek(&archiveStream.s, &begin_of_archive, SZ_SEEK_SET) != 0)
  105         return CL_CLEAN;
  106 
  107     lookStream.realStream = &archiveStream.s;
  108     LookToRead_Init(&lookStream);
  109 
  110     SzArEx_Init(&db);
  111     res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
  112     if (res == SZ_ERROR_ENCRYPTED && SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) {
  113         cli_dbgmsg("cli_7unz: Encrypted header found in archive.\n");
  114         found = cli_append_virus(ctx, "Heuristics.Encrypted.7Zip");
  115     } else if (res == SZ_OK) {
  116         UInt32 i, blockIndex = 0xFFFFFFFF;
  117         Byte *outBuffer        = 0;
  118         size_t outBufferSize   = 0;
  119         unsigned int encrypted = 0;
  120 
  121         for (i = 0; i < db.db.NumFiles; i++) {
  122             size_t offset           = 0;
  123             size_t outSizeProcessed = 0;
  124             const CSzFileItem *f    = db.db.Files + i;
  125             char *name;
  126             size_t j;
  127             int newnamelen, fd;
  128 
  129             if ((found = cli_checklimits("7unz", ctx, 0, 0, 0)))
  130                 break;
  131 
  132             if (f->IsDir)
  133                 continue;
  134 
  135             if (cli_checklimits("7unz", ctx, f->Size, 0, 0))
  136                 continue;
  137 
  138             if (!db.FileNameOffsets)
  139                 newnamelen = 0; /* no filename */
  140             else {
  141                 newnamelen = SzArEx_GetFileNameUtf16(&db, i, NULL);
  142                 if (newnamelen > namelen) {
  143                     if (namelen > UTFBUFSZ)
  144                         free(utf16name);
  145                     utf16name = cli_malloc(newnamelen * 2);
  146                     if (!utf16name) {
  147                         found = CL_EMEM;
  148                         break;
  149                     }
  150                     namelen = newnamelen;
  151                 }
  152                 SzArEx_GetFileNameUtf16(&db, i, utf16name);
  153             }
  154 
  155             name = (char *)utf16name;
  156             for (j = 0; j < (size_t)newnamelen; j++) /* FIXME */
  157                 name[j] = utf16name[j];
  158             name[j] = 0;
  159             cli_dbgmsg("cli_7unz: extracting %s\n", name);
  160 
  161             res = SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp);
  162             if (res == SZ_ERROR_ENCRYPTED) {
  163                 encrypted = 1;
  164                 if (SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) {
  165                     cli_dbgmsg("cli_7unz: Encrypted files found in archive.\n");
  166                     found = cli_append_virus(ctx, "Heuristics.Encrypted.7Zip");
  167                     if (found != CL_CLEAN) {
  168                         if (found == CL_VIRUS) {
  169                             if (SCAN_ALLMATCHES)
  170                                 viruses_found++;
  171                         } else
  172                             break;
  173                     }
  174                 }
  175             }
  176             if (cli_matchmeta(ctx, name, 0, f->Size, encrypted, i, f->CrcDefined ? f->Crc : 0, NULL)) {
  177                 found = CL_VIRUS;
  178                 viruses_found++;
  179                 if (!SCAN_ALLMATCHES)
  180                     break;
  181             }
  182             if (res != SZ_OK)
  183                 cli_dbgmsg("cli_unz: extraction failed with %d\n", res);
  184             else if ((outBuffer == NULL) || (outSizeProcessed == 0)) {
  185                 cli_dbgmsg("cli_unz: extracted empty file\n");
  186             } else {
  187                 if ((found = cli_gentempfd(ctx->engine->tmpdir, &name, &fd)))
  188                     break;
  189 
  190                 cli_dbgmsg("cli_7unz: Saving to %s\n", name);
  191                 if (cli_writen(fd, outBuffer + offset, outSizeProcessed) != outSizeProcessed)
  192                     found = CL_EWRITE;
  193                 else if ((found = cli_magic_scandesc(fd, name, ctx)) == CL_VIRUS)
  194                     viruses_found++;
  195                 close(fd);
  196                 if (!ctx->engine->keeptmp && cli_unlink(name))
  197                     found = CL_EUNLINK;
  198 
  199                 free(name);
  200                 if (found != CL_CLEAN)
  201                     if (!(SCAN_ALLMATCHES && found == CL_VIRUS))
  202                         break;
  203             }
  204         }
  205         IAlloc_Free(&allocImp, outBuffer);
  206     }
  207     SzArEx_Free(&db, &allocImp);
  208     if (namelen > UTFBUFSZ)
  209         free(utf16name);
  210 
  211     if (res == SZ_OK)
  212         cli_dbgmsg("cli_7unz: completed successfully\n");
  213     else if (res == SZ_ERROR_UNSUPPORTED)
  214         cli_dbgmsg("cli_7unz: unsupported\n");
  215     else if (res == SZ_ERROR_MEM)
  216         cli_dbgmsg("cli_7unz: oom\n");
  217     else if (res == SZ_ERROR_CRC)
  218         cli_dbgmsg("cli_7unz: crc mismatch\n");
  219     else if (res == SZ_ERROR_ENCRYPTED)
  220         cli_dbgmsg("cli_7unz: encrypted\n");
  221     else
  222         cli_dbgmsg("cli_7unz: error %d\n", res);
  223 
  224     if (SCAN_ALLMATCHES && viruses_found)
  225         return CL_VIRUS;
  226     return found;
  227 }