2003-07-29 15:48:06 +00:00
/*
2019-01-25 10:15:50 -05:00
* Copyright ( C ) 2013 - 2019 Cisco Systems , Inc . and / or its affiliates . All rights reserved .
2013-10-08 17:17:44 -04:00
* Copyright ( C ) 2007 - 2013 Sourcefire , Inc .
2008-02-11 18:34:28 +00:00
*
2008-04-02 15:24:51 +00:00
* Authors : Tomasz Kojm
2003-07-29 15:48:06 +00:00
*
* This program is free software ; you can redistribute it and / or modify
2007-03-31 20:31:04 +00:00
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
2003-07-29 15:48:06 +00:00
*
* 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
2006-04-09 19:59:28 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston ,
* MA 02110 - 1301 , USA .
2003-07-29 15:48:06 +00:00
*/
2004-02-06 13:46:08 +00:00
# if HAVE_CONFIG_H
# include "clamav-config.h"
# endif
2009-10-12 23:32:27 +02:00
# ifndef _WIN32
2009-09-10 03:19:43 +02:00
# include <sys/time.h>
2009-10-12 23:32:27 +02:00
# endif
2003-07-29 15:48:06 +00:00
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
2018-07-30 20:19:28 -04:00
# include <libgen.h>
2008-07-03 13:03:26 +00:00
# include <errno.h>
2003-07-29 15:48:06 +00:00
# include <sys/types.h>
# include <sys/stat.h>
2017-08-08 17:38:17 -04:00
# ifdef HAVE_UNISTD_H
2005-03-22 21:26:27 +00:00
# include <unistd.h>
2006-10-09 15:23:50 +00:00
# endif
2017-08-08 17:38:17 -04:00
# ifdef HAVE_SYS_PARAM_H
2004-11-13 14:47:20 +00:00
# include <sys/param.h>
2006-10-09 15:23:50 +00:00
# endif
2003-07-29 15:48:06 +00:00
# include <fcntl.h>
# include <dirent.h>
2011-02-14 19:19:20 +02:00
# ifdef HAVE_SYS_TIMES_H
# include <sys/times.h>
# endif
2004-07-02 23:00:58 +00:00
2017-08-08 17:38:17 -04:00
# define DCONF_ARCH ctx->dconf->archive
# define DCONF_DOC ctx->dconf->doc
# define DCONF_MAIL ctx->dconf->mail
2007-01-09 20:06:51 +00:00
# define DCONF_OTHER ctx->dconf->other
2003-07-29 15:48:06 +00:00
# include "clamav.h"
# include "others.h"
2007-01-09 20:06:51 +00:00
# include "dconf.h"
2004-08-02 17:09:06 +00:00
# include "scanners.h"
2004-07-19 17:54:40 +00:00
# include "matcher-ac.h"
# include "matcher-bm.h"
2003-07-29 15:48:06 +00:00
# include "matcher.h"
2004-01-23 11:17:16 +00:00
# include "ole2_extract.h"
# include "vba_extract.h"
2004-05-02 00:51:01 +00:00
# include "msexpand.h"
2006-05-18 11:29:24 +00:00
# include "mbox.h"
2016-03-24 12:26:04 -04:00
# include "libmspack.h"
2004-07-05 23:50:55 +00:00
# include "pe.h"
2006-05-18 11:29:24 +00:00
# include "elf.h"
2004-07-02 23:00:58 +00:00
# include "filetypes.h"
# include "htmlnorm.h"
2004-09-07 21:19:02 +00:00
# include "untar.h"
2004-09-30 00:26:52 +00:00
# include "special.h"
2005-01-26 17:45:25 +00:00
# include "binhex.h"
2006-05-18 11:29:24 +00:00
/* #include "uuencode.h" */
2006-04-10 09:59:51 +00:00
# include "tnef.h"
2005-12-15 02:02:29 +00:00
# include "sis.h"
2006-03-08 15:37:52 +00:00
# include "pdf.h"
2006-10-25 15:40:47 +00:00
# include "str.h"
2006-12-04 00:10:46 +00:00
# include "rtf.h"
2018-07-30 20:19:28 -04:00
# include "libclamunrar_iface/unrar_iface.h"
2007-07-11 10:14:08 +00:00
# include "unarj.h"
2009-10-12 23:32:27 +02:00
# include "nsis/nulsft.h"
2007-10-30 18:53:25 +00:00
# include "autoit.h"
2008-02-04 21:38:34 +00:00
# include "textnorm.h"
2003-07-29 15:48:06 +00:00
# include <zlib.h>
2006-05-22 16:44:11 +00:00
# include "unzip.h"
2008-04-16 18:47:42 +00:00
# include "dlp.h"
2009-02-14 15:35:26 +00:00
# include "default.h"
2009-07-06 16:35:55 +02:00
# include "cpio.h"
2009-07-08 15:05:22 +02:00
# include "macho.h"
2009-07-13 02:37:16 +02:00
# include "ishield.h"
2011-06-18 01:44:38 +02:00
# include "7z_iface.h"
2009-08-30 19:14:49 +02:00
# include "fmap.h"
2009-08-11 12:23:14 +02:00
# include "cache.h"
2011-03-11 20:30:45 +01:00
# include "events.h"
2011-04-06 15:53:28 +02:00
# include "swf.h"
# include "jpeg.h"
2011-04-07 18:19:19 +02:00
# include "png.h"
2011-11-14 21:23:15 +01:00
# include "iso9660.h"
2013-08-27 13:44:11 -04:00
# include "dmg.h"
# include "xar.h"
2013-09-26 11:12:54 -04:00
# include "hfsplus.h"
2013-10-08 17:17:44 -04:00
# include "xz_iface.h"
2014-02-07 12:22:44 -05:00
# include "mbr.h"
2014-01-24 14:24:56 -05:00
# include "gpt.h"
2014-02-06 19:01:26 -05:00
# include "apm.h"
2014-07-09 13:16:31 -04:00
# include "ooxml.h"
2014-07-31 19:11:22 -04:00
# include "xdp.h"
2014-04-24 14:22:00 -04:00
# include "json_api.h"
2015-03-10 15:33:32 -04:00
# include "msxml.h"
2015-07-30 17:37:05 -04:00
# include "tiff.h"
2015-12-08 17:28:49 -05:00
# include "hwp.h"
2017-08-10 15:40:52 -04:00
# include "msdoc.h"
2003-07-29 15:48:06 +00:00
# ifdef HAVE_BZLIB_H
# include <bzlib.h>
# endif
2004-10-20 20:20:20 +00:00
# if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2)
# include <limits.h>
2004-11-02 04:08:09 +00:00
# include <stddef.h>
2004-10-20 20:20:20 +00:00
# endif
2018-07-30 20:19:28 -04:00
# include <fcntl.h>
2014-02-08 00:31:12 -05:00
# include <string.h>
2006-02-15 00:41:40 +00:00
static int cli_scanfile ( const char * filename , cli_ctx * ctx ) ;
2004-07-13 03:30:49 +00:00
2009-08-30 19:46:26 +02:00
static int cli_scandir ( const char * dirname , cli_ctx * ctx )
2008-02-11 18:34:28 +00:00
{
2017-08-08 17:38:17 -04:00
DIR * dd ;
struct dirent * dent ;
2008-02-11 18:34:28 +00:00
# if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2)
2017-08-08 17:38:17 -04:00
union {
struct dirent d ;
char b [ offsetof ( struct dirent , d_name ) + NAME_MAX + 1 ] ;
} result ;
2008-02-11 18:34:28 +00:00
# endif
2017-08-08 17:38:17 -04:00
STATBUF statbuf ;
char * fname ;
unsigned int viruses_found = 0 ;
2008-02-11 18:34:28 +00:00
2018-12-03 12:40:13 -05:00
if ( ( dd = opendir ( dirname ) ) ! = NULL ) {
2008-02-11 18:34:28 +00:00
# ifdef HAVE_READDIR_R_3
2018-12-03 12:40:13 -05:00
while ( ! readdir_r ( dd , & result . d , & dent ) & & dent ) {
2008-02-11 18:34:28 +00:00
# elif defined(HAVE_READDIR_R_2)
2018-12-03 12:40:13 -05:00
while ( ( dent = ( struct dirent * ) readdir_r ( dd , & result . d ) ) ) {
2008-02-11 18:34:28 +00:00
# else
2018-12-03 12:40:13 -05:00
while ( ( dent = readdir ( dd ) ) ) {
2008-02-11 18:34:28 +00:00
# endif
2018-12-03 12:40:13 -05:00
if ( dent - > d_ino ) {
if ( strcmp ( dent - > d_name , " . " ) & & strcmp ( dent - > d_name , " .. " ) ) {
2017-08-08 17:38:17 -04:00
/* build the full name */
fname = cli_malloc ( strlen ( dirname ) + strlen ( dent - > d_name ) + 2 ) ;
2018-12-03 12:40:13 -05:00
if ( ! fname ) {
2017-08-08 17:38:17 -04:00
closedir ( dd ) ;
cli_dbgmsg ( " cli_scandir: Unable to allocate memory for filename \n " ) ;
return CL_EMEM ;
}
sprintf ( fname , " %s " PATHSEP " %s " , dirname , dent - > d_name ) ;
/* stat the file */
2018-12-03 12:40:13 -05:00
if ( LSTAT ( fname , & statbuf ) ! = - 1 ) {
if ( S_ISDIR ( statbuf . st_mode ) & & ! S_ISLNK ( statbuf . st_mode ) ) {
if ( cli_scandir ( fname , ctx ) = = CL_VIRUS ) {
2017-08-08 17:38:17 -04:00
free ( fname ) ;
2018-12-03 12:40:13 -05:00
if ( SCAN_ALLMATCHES ) {
2017-08-08 17:38:17 -04:00
viruses_found + + ;
continue ;
}
2012-10-18 14:12:58 -07:00
closedir ( dd ) ;
return CL_VIRUS ;
2017-08-08 17:38:17 -04:00
}
2018-12-03 12:40:13 -05:00
} else {
if ( S_ISREG ( statbuf . st_mode ) ) {
if ( cli_scanfile ( fname , ctx ) = = CL_VIRUS ) {
2017-08-08 17:38:17 -04:00
free ( fname ) ;
2018-12-03 12:40:13 -05:00
if ( SCAN_ALLMATCHES ) {
2017-08-08 17:38:17 -04:00
viruses_found + + ;
continue ;
}
2012-10-18 14:12:58 -07:00
closedir ( dd ) ;
return CL_VIRUS ;
2017-08-08 17:38:17 -04:00
}
}
}
}
free ( fname ) ;
}
}
}
2018-12-03 12:40:13 -05:00
} else {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_scandir: Can't open directory %s. \n " , dirname ) ;
return CL_EOPEN ;
2008-02-11 18:34:28 +00:00
}
closedir ( dd ) ;
2018-07-20 22:28:48 -04:00
if ( SCAN_ALLMATCHES & & viruses_found )
2017-08-08 17:38:17 -04:00
return CL_VIRUS ;
2008-02-11 18:34:28 +00:00
return CL_CLEAN ;
}
2018-07-30 20:19:28 -04:00
/**
* @ brief Scan the metadata using cli_matchmeta ( )
*
* @ param metadata unrar metadata structure
* @ param ctx scanning context structure
* @ param files
2018-09-24 15:01:22 -04:00
* @ return cl_error_t Returns CL_CLEAN if nothing found , CL_VIRUS if something found , CL_EUNPACK if encrypted .
2018-07-30 20:19:28 -04:00
*/
2018-12-03 12:40:13 -05:00
static cl_error_t cli_unrar_scanmetadata ( unrar_metadata_t * metadata , cli_ctx * ctx , unsigned int files )
2003-07-29 15:48:06 +00:00
{
2018-07-30 20:19:28 -04:00
cl_error_t status = CL_CLEAN ;
2018-12-03 12:40:13 -05:00
int virus_found = 0 ;
2003-07-29 15:48:06 +00:00
2008-02-06 21:19:10 +00:00
cli_dbgmsg ( " RAR: %s, crc32: 0x%x, encrypted: %u, compressed: %u, normal: %u, method: %u, ratio: %u \n " ,
2018-12-03 12:40:13 -05:00
metadata - > filename , metadata - > crc , metadata - > encrypted , ( unsigned int ) metadata - > pack_size ,
( unsigned int ) metadata - > unpack_size , metadata - > method ,
metadata - > pack_size ? ( unsigned int ) ( metadata - > unpack_size / metadata - > pack_size ) : 0 ) ;
2005-03-18 01:27:45 +00:00
2018-07-30 20:19:28 -04:00
if ( CL_VIRUS = = cli_matchmeta ( ctx , metadata - > filename , metadata - > pack_size , metadata - > unpack_size , metadata - > encrypted , files , metadata - > crc , NULL ) ) {
status = CL_VIRUS ;
} else if ( SCAN_HEURISTIC_ENCRYPTED_ARCHIVE & & metadata - > encrypted ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " RAR: Encrypted files found in archive. \n " ) ;
2018-07-30 20:19:28 -04:00
status = CL_EUNPACK ;
2007-01-13 00:01:39 +00:00
}
2005-03-18 01:27:45 +00:00
2018-07-30 20:19:28 -04:00
done :
return status ;
2007-01-28 20:22:16 +00:00
}
2018-12-03 12:40:13 -05:00
static cl_error_t cli_scanrar ( const char * filepath , int desc , cli_ctx * ctx )
2007-01-13 00:01:39 +00:00
{
2018-12-03 12:40:13 -05:00
cl_error_t status = CL_EPARSE ;
2018-07-30 20:19:28 -04:00
cl_unrar_error_t unrar_ret = UNRAR_ERR ;
2018-12-03 12:40:13 -05:00
char * extract_dir = NULL ; /* temp dir to write extracted files to */
char * comment_dir = NULL ; /* temp dir to write file comments to */
unsigned int file_count = 0 ;
2017-08-08 17:38:17 -04:00
unsigned int viruses_found = 0 ;
2007-01-13 00:01:39 +00:00
2018-07-30 20:19:28 -04:00
uint32_t nEncryptedFilesFound = 0 ;
2018-12-03 12:40:13 -05:00
uint32_t nTooLargeFilesFound = 0 ;
2007-01-13 00:01:39 +00:00
2018-12-03 12:40:13 -05:00
void * hArchive = NULL ;
2007-12-15 20:34:31 +00:00
2018-12-03 12:40:13 -05:00
char * comment = NULL ;
2018-07-30 20:19:28 -04:00
uint32_t comment_size = 0 ;
2017-08-08 17:38:17 -04:00
2018-07-30 20:19:28 -04:00
unrar_metadata_t metadata ;
2018-12-03 12:40:13 -05:00
char * filename_base = NULL ;
char * extract_fullpath = NULL ;
char * comment_fullpath = NULL ;
2018-07-30 20:19:28 -04:00
if ( filepath = = NULL | | ctx = = NULL ) {
cli_dbgmsg ( " RAR: Invalid arguments! \n " ) ;
return CL_EARG ;
2017-08-08 17:38:17 -04:00
}
2018-07-30 20:19:28 -04:00
cli_dbgmsg ( " in scanrar() \n " ) ;
/* Zero out the metadata struct before we read the header */
memset ( & metadata , 0 , sizeof ( unrar_metadata_t ) ) ;
2018-12-03 12:40:13 -05:00
2018-07-30 20:19:28 -04:00
/* Determine file basename */
if ( CL_SUCCESS ! = cli_basename ( filepath , strlen ( filepath ) , & filename_base ) ) {
status = CL_EARG ;
goto done ;
}
/* generate the temporary directory for extracted files. */
if ( ! ( extract_dir = cli_gentemp_with_prefix ( ctx - > engine - > tmpdir , filename_base ) ) ) {
status = CL_EMEM ;
goto done ;
}
if ( mkdir ( extract_dir , 0700 ) ) {
cli_dbgmsg ( " RAR: Can't create temporary directory for extracted files %s \n " , extract_dir ) ;
status = CL_ETMPDIR ;
goto done ;
}
/*
* Open the archive .
*/
if ( UNRAR_OK ! = ( unrar_ret = cli_unrar_open ( filepath , & hArchive , & comment , & comment_size , cli_debug_flag ) ) ) {
if ( unrar_ret = = UNRAR_ENCRYPTED ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " RAR: Encrypted main header \n " ) ;
2018-07-30 20:19:28 -04:00
status = CL_EUNPACK ;
goto done ;
2017-08-08 17:38:17 -04:00
}
2018-07-30 20:19:28 -04:00
if ( unrar_ret = = UNRAR_EMEM ) {
status = CL_EMEM ;
goto done ;
} else {
status = CL_EFORMAT ;
goto done ;
2017-08-08 17:38:17 -04:00
}
}
2018-07-30 20:19:28 -04:00
/* If the archive header had a comment, write it to the comment dir. */
if ( ( comment ! = NULL ) & & ( comment_size > 0 ) ) {
int comment_fd = - 1 ;
if ( ! ( comment_fullpath = cli_gentemp_with_prefix ( extract_dir , " comments " ) ) ) {
status = CL_EMEM ;
goto done ;
2017-08-08 17:38:17 -04:00
}
2018-07-30 20:19:28 -04:00
comment_fd = open ( comment_fullpath , O_WRONLY | O_CREAT | O_TRUNC | O_BINARY , 0600 ) ;
if ( comment_fd < 0 ) {
cli_dbgmsg ( " RAR: ERROR: Failed to open output file \n " ) ;
} else {
cli_dbgmsg ( " RAR: Writing the archive comment to temp file: %s \n " , comment_fullpath ) ;
if ( 0 = = write ( comment_fd , comment , comment_size ) ) {
cli_dbgmsg ( " RAR: ERROR: Failed to write to output file \n " ) ;
} else {
/* Scan the comment file */
status = cli_scanfile ( comment_fullpath , ctx ) ;
/* Delete the tempfile if not --leave-temps */
if ( ! ctx - > engine - > keeptmp )
if ( cli_unlink ( comment_fullpath ) )
cli_dbgmsg ( " RAR: Failed to unlink the extracted comment file: %s \n " , comment_fullpath ) ;
if ( ( status = = CL_VIRUS ) & & SCAN_ALLMATCHES ) {
status = CL_CLEAN ;
viruses_found + + ;
}
if ( ( status = = CL_VIRUS ) | | ( status = = CL_BREAK ) ) {
goto done ;
}
}
2018-11-14 16:58:30 -05:00
close ( comment_fd ) ;
2017-08-08 17:38:17 -04:00
}
2018-07-30 20:19:28 -04:00
}
2017-08-08 17:38:17 -04:00
2018-07-30 20:19:28 -04:00
/*
* Read & scan each file header .
* Extract & scan each file .
*
* Skip files if they will exceed max filesize or max scansize .
* Count the number of encrypted file headers and encrypted files .
* - Alert if there are encrypted files ,
* if the Heuristic for encrypted archives is enabled ,
* and if we have not detected a signature match .
*/
do {
status = CL_CLEAN ;
2017-08-08 17:38:17 -04:00
2018-07-30 20:19:28 -04:00
/* Zero out the metadata struct before we read the header */
memset ( & metadata , 0 , sizeof ( unrar_metadata_t ) ) ;
/*
* Get the header information for the next file in the archive .
*/
unrar_ret = cli_unrar_peek_file_header ( hArchive , & metadata ) ;
if ( unrar_ret ! = UNRAR_OK ) {
if ( unrar_ret = = UNRAR_ENCRYPTED ) {
/* Found an encrypted file header, must skip. */
cli_dbgmsg ( " RAR: Encrypted file header, unable to reading file metadata and file contents. Skipping file... \n " ) ;
nEncryptedFilesFound + = 1 ;
if ( UNRAR_OK ! = cli_unrar_skip_file ( hArchive ) ) {
/* Failed to skip! Break extraction loop. */
cli_dbgmsg ( " RAR: Failed to skip file. RAR archive extraction has failed. \n " ) ;
break ;
}
} else if ( unrar_ret = = UNRAR_BREAK ) {
/* No more files. Break extraction loop. */
cli_dbgmsg ( " RAR: No more files in archive. \n " ) ;
break ;
} else {
/* Memory error or some other error reading the header info. */
cli_dbgmsg ( " RAR: Error (%u) reading file header! \n " , unrar_ret ) ;
break ;
2017-08-08 17:38:17 -04:00
}
2018-12-03 12:40:13 -05:00
} else {
2018-07-30 20:19:28 -04:00
file_count + = 1 ;
/*
* Scan the metadata for the file in question since the content was clean , or we ' re running in all - match .
*/
2018-09-24 15:01:22 -04:00
status = cli_unrar_scanmetadata ( & metadata , ctx , file_count ) ;
2018-07-30 20:19:28 -04:00
if ( ( status = = CL_VIRUS ) & & SCAN_ALLMATCHES ) {
status = CL_CLEAN ;
2017-08-08 17:38:17 -04:00
viruses_found + + ;
}
2018-07-30 20:19:28 -04:00
if ( ( status = = CL_VIRUS ) | | ( status = = CL_BREAK ) ) {
break ;
}
/* Check if we've already exceeded the scan limit */
if ( cli_checklimits ( " RAR " , ctx , 0 , 0 , 0 ) )
break ;
2018-12-03 12:40:13 -05:00
2018-07-30 20:19:28 -04:00
if ( metadata . is_dir ) {
/* Entry is a directory. Skip. */
cli_dbgmsg ( " RAR: Found directory. Skipping to next file. \n " ) ;
if ( UNRAR_OK ! = cli_unrar_skip_file ( hArchive ) ) {
/* Failed to skip! Break extraction loop. */
cli_dbgmsg ( " RAR: Failed to skip directory. RAR archive extraction has failed. \n " ) ;
break ;
}
} else if ( cli_checklimits ( " RAR " , ctx , metadata . unpack_size , 0 , 0 ) ) {
/* File size exceeds maxfilesize, must skip extraction.
* Although we may be able to scan the metadata */
nTooLargeFilesFound + = 1 ;
cli_dbgmsg ( " RAR: Next file is too large (% " PRIu64 " bytes); it would exceed max scansize. Skipping to next file. \n " , metadata . unpack_size ) ;
if ( UNRAR_OK ! = cli_unrar_skip_file ( hArchive ) ) {
/* Failed to skip! Break extraction loop. */
cli_dbgmsg ( " RAR: Failed to skip file. RAR archive extraction has failed. \n " ) ;
break ;
}
} else if ( metadata . encrypted ! = 0 ) {
/* Found an encrypted file, must skip. */
cli_dbgmsg ( " RAR: Encrypted file, unable to extract file contents. Skipping file... \n " ) ;
nEncryptedFilesFound + = 1 ;
if ( UNRAR_OK ! = cli_unrar_skip_file ( hArchive ) ) {
/* Failed to skip! Break extraction loop. */
cli_dbgmsg ( " RAR: Failed to skip file. RAR archive extraction has failed. \n " ) ;
break ;
}
} else {
/*
* Extract the file . . .
*/
extract_fullpath = cli_gentemp_with_prefix ( extract_dir , metadata . filename ) ;
if ( NULL = = extract_fullpath ) {
cli_dbgmsg ( " RAR: Memory error allocating filename for extracted file. " ) ;
status = CL_EMEM ;
break ;
}
cli_dbgmsg ( " RAR: Extracting file: %s to %s \n " , metadata . filename , extract_fullpath ) ;
unrar_ret = cli_unrar_extract_file ( hArchive , extract_fullpath , NULL ) ;
if ( unrar_ret ! = UNRAR_OK ) {
/*
* Some other error extracting the file
*/
cli_dbgmsg ( " RAR: Error extracting file: %s \n " , metadata . filename ) ;
/* TODO:
* may need to manually skip the file depending on what , specifically , cli_unrar_extract_file ( ) returned .
*/
} else {
/* File should be extracted...
* . . . scan the extracted file .
*/
cli_dbgmsg ( " RAR: Extraction complete. Scanning now... \n " ) ;
status = cli_scanfile ( extract_fullpath , ctx ) ;
if ( status = = CL_EOPEN ) {
cli_dbgmsg ( " RAR: File not found, Extraction failed! \n " ) ;
status = CL_CLEAN ;
} else {
/* Delete the tempfile if not --leave-temps */
if ( ! ctx - > engine - > keeptmp )
if ( cli_unlink ( extract_fullpath ) )
cli_dbgmsg ( " RAR: Failed to unlink the extracted file: %s \n " , extract_fullpath ) ;
if ( status = = CL_VIRUS ) {
cli_dbgmsg ( " RAR: infected with %s \n " , cli_get_last_virus ( ctx ) ) ;
status = CL_VIRUS ;
viruses_found + + ;
}
}
}
/* Free up that the filepath */
if ( NULL ! = extract_fullpath ) {
free ( extract_fullpath ) ;
extract_fullpath = NULL ;
}
}
2017-08-08 17:38:17 -04:00
}
2018-07-30 20:19:28 -04:00
if ( status = = CL_VIRUS ) {
2018-07-20 22:28:48 -04:00
if ( SCAN_ALLMATCHES )
2018-07-30 20:19:28 -04:00
status = CL_SUCCESS ;
2017-08-08 17:38:17 -04:00
else
break ;
}
2018-07-30 20:19:28 -04:00
if ( ctx - > engine - > maxscansize & & ctx - > scansize > = ctx - > engine - > maxscansize ) {
status = CL_CLEAN ;
break ;
}
2017-08-08 17:38:17 -04:00
2018-07-30 20:19:28 -04:00
/*
* TODO : Free up any malloced metadata . . .
*/
if ( metadata . filename ! = NULL ) {
free ( metadata . filename ) ;
metadata . filename = NULL ;
}
2017-08-08 17:38:17 -04:00
2018-07-30 20:19:28 -04:00
} while ( status = = CL_CLEAN ) ;
2017-08-08 17:38:17 -04:00
2018-07-30 20:19:28 -04:00
if ( status = = CL_BREAK )
status = CL_CLEAN ;
2017-08-08 17:38:17 -04:00
2018-07-30 20:19:28 -04:00
done :
if ( NULL ! = comment ) {
free ( comment ) ;
comment = NULL ;
}
2003-07-29 15:48:06 +00:00
2018-07-30 20:19:28 -04:00
if ( NULL ! = comment_fullpath ) {
if ( ! ctx - > engine - > keeptmp ) {
cli_rmdirs ( comment_fullpath ) ;
}
free ( comment_fullpath ) ;
comment_fullpath = NULL ;
}
2007-01-20 11:38:54 +00:00
2018-07-30 20:19:28 -04:00
if ( NULL ! = hArchive ) {
cli_unrar_close ( hArchive ) ;
hArchive = NULL ;
}
2003-07-29 15:48:06 +00:00
2018-07-30 20:19:28 -04:00
if ( NULL ! = filename_base ) {
free ( filename_base ) ;
filename_base = NULL ;
}
2007-01-13 00:01:39 +00:00
2018-07-30 20:19:28 -04:00
if ( metadata . filename ! = NULL ) {
free ( metadata . filename ) ;
metadata . filename = NULL ;
}
if ( NULL ! = extract_fullpath ) {
free ( extract_fullpath ) ;
extract_fullpath = NULL ;
2003-07-29 15:48:06 +00:00
}
2018-07-30 20:19:28 -04:00
if ( NULL ! = extract_dir ) {
if ( ! ctx - > engine - > keeptmp ) {
cli_rmdirs ( extract_dir ) ;
}
free ( extract_dir ) ;
extract_dir = NULL ;
}
/* If return value was a failure due to encryption, scan the un-extracted archive just in case... */
if ( ( CL_VIRUS ! = status ) & & ( ( CL_EUNPACK = = status ) | | ( nEncryptedFilesFound > 0 ) ) ) {
status = cli_scandesc ( desc , ctx , 0 , 0 , NULL , AC_SCAN_VIR , NULL ) ;
/* If no virus, and user requests enabled the Heuristic for encrypted archives... */
if ( ( status ! = CL_VIRUS ) & & SCAN_HEURISTIC_ENCRYPTED_ARCHIVE ) {
if ( CL_VIRUS = = cli_append_virus ( ctx , " Heuristics.Encrypted.RAR " ) ) {
status = CL_VIRUS ;
}
}
if ( status ! = CL_VIRUS ) {
status = CL_CLEAN ;
}
}
cli_dbgmsg ( " RAR: Exit code: %d \n " , status ) ;
2004-03-16 19:39:49 +00:00
2018-07-20 22:28:48 -04:00
if ( SCAN_ALLMATCHES & & viruses_found )
2018-07-30 20:19:28 -04:00
status = CL_VIRUS ;
return status ;
2003-07-29 15:48:06 +00:00
}
2018-09-24 15:01:22 -04:00
static int cli_scanarj ( cli_ctx * ctx , off_t sfx_offset )
2007-07-11 10:14:08 +00:00
{
2017-08-08 17:38:17 -04:00
int ret = CL_CLEAN , rc , file = 0 ;
arj_metadata_t metadata ;
char * dir ;
int virus_found = 0 ;
2007-07-11 10:14:08 +00:00
cli_dbgmsg ( " in cli_scanarj() \n " ) ;
2016-03-08 14:37:20 -05:00
memset ( & metadata , 0 , sizeof ( arj_metadata_t ) ) ;
2017-08-08 17:38:17 -04:00
/* generate the temporary directory */
if ( ! ( dir = cli_gentemp ( ctx - > engine - > tmpdir ) ) )
return CL_EMEM ;
2008-03-06 20:19:22 +00:00
2018-12-03 12:40:13 -05:00
if ( mkdir ( dir , 0700 ) ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " ARJ: Can't create temporary directory %s \n " , dir ) ;
free ( dir ) ;
return CL_ETMPDIR ;
2007-07-11 10:14:08 +00:00
}
2011-06-10 19:54:43 +03:00
ret = cli_unarj_open ( * ctx - > fmap , dir , & metadata , sfx_offset ) ;
2018-12-03 12:40:13 -05:00
if ( ret ! = CL_SUCCESS ) {
2017-08-08 17:38:17 -04:00
if ( ! ctx - > engine - > keeptmp )
cli_rmdirs ( dir ) ;
free ( dir ) ;
cli_dbgmsg ( " ARJ: Error: %s \n " , cl_strerror ( ret ) ) ;
return ret ;
}
2018-12-03 12:40:13 -05:00
do {
2009-10-23 20:49:12 +02:00
metadata . filename = NULL ;
2018-12-03 12:40:13 -05:00
ret = cli_unarj_prepare_file ( dir , & metadata ) ;
if ( ret ! = CL_SUCCESS ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " ARJ: cli_unarj_prepare_file Error: %s \n " , cl_strerror ( ret ) ) ;
break ;
}
file + + ;
2018-12-03 12:40:13 -05:00
if ( cli_matchmeta ( ctx , metadata . filename , metadata . comp_size , metadata . orig_size , metadata . encrypted , file , 0 , NULL ) = = CL_VIRUS ) {
if ( ! SCAN_ALLMATCHES ) {
2016-06-08 16:25:34 -04:00
cli_rmdirs ( dir ) ;
free ( dir ) ;
return CL_VIRUS ;
}
virus_found = 1 ;
2018-12-03 12:40:13 -05:00
ret = CL_SUCCESS ;
2016-06-08 16:25:34 -04:00
}
2010-01-14 23:32:35 +01:00
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_checklimits ( " ARJ " , ctx , metadata . orig_size , metadata . comp_size , 0 ) ) ! = CL_CLEAN ) {
2017-08-08 17:38:17 -04:00
ret = CL_SUCCESS ;
if ( metadata . filename )
free ( metadata . filename ) ;
continue ;
}
ret = cli_unarj_extract_file ( dir , & metadata ) ;
2018-12-03 12:40:13 -05:00
if ( ret ! = CL_SUCCESS ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " ARJ: cli_unarj_extract_file Error: %s \n " , cl_strerror ( ret ) ) ;
}
2018-12-03 12:40:13 -05:00
if ( metadata . ofd > = 0 ) {
if ( lseek ( metadata . ofd , 0 , SEEK_SET ) = = - 1 ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " ARJ: call to lseek() failed \n " ) ;
}
2018-07-30 20:19:28 -04:00
rc = cli_magic_scandesc ( metadata . ofd , NULL , ctx ) ;
2017-08-08 17:38:17 -04:00
close ( metadata . ofd ) ;
2018-12-03 12:40:13 -05:00
if ( rc = = CL_VIRUS ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " ARJ: infected with %s \n " , cli_get_last_virus ( ctx ) ) ;
2018-12-03 12:40:13 -05:00
if ( ! SCAN_ALLMATCHES ) {
2016-06-08 16:25:34 -04:00
ret = CL_VIRUS ;
2018-12-03 12:40:13 -05:00
if ( metadata . filename ) {
2016-06-08 16:25:34 -04:00
free ( metadata . filename ) ;
metadata . filename = NULL ;
}
break ;
}
virus_found = 1 ;
2018-12-03 12:40:13 -05:00
ret = CL_SUCCESS ;
2017-08-08 17:38:17 -04:00
}
}
2018-12-03 12:40:13 -05:00
if ( metadata . filename ) {
2017-08-08 17:38:17 -04:00
free ( metadata . filename ) ;
metadata . filename = NULL ;
}
} while ( ret = = CL_SUCCESS ) ;
if ( ! ctx - > engine - > keeptmp )
cli_rmdirs ( dir ) ;
2007-07-11 10:14:08 +00:00
free ( dir ) ;
2018-12-03 12:40:13 -05:00
if ( metadata . filename ) {
2017-08-08 17:38:17 -04:00
free ( metadata . filename ) ;
2007-07-11 10:14:08 +00:00
}
2016-06-08 16:25:34 -04:00
if ( virus_found ! = 0 )
ret = CL_VIRUS ;
2007-07-11 10:14:08 +00:00
cli_dbgmsg ( " ARJ: Exit code: %d \n " , ret ) ;
2007-12-07 09:40:51 +00:00
if ( ret = = CL_BREAK )
2017-08-08 17:38:17 -04:00
ret = CL_CLEAN ;
2007-07-11 10:14:08 +00:00
return ret ;
}
2003-07-29 15:48:06 +00:00
2017-08-08 17:38:17 -04:00
static int cli_scangzip_with_zib_from_the_80s ( cli_ctx * ctx , unsigned char * buff )
{
2010-02-09 16:36:14 +01:00
int fd , ret , outsize = 0 , bytes ;
fmap_t * map = * ctx - > fmap ;
char * tmpname ;
gzFile gz ;
2013-02-19 15:56:26 -05:00
ret = fmap_fd ( map ) ;
2017-08-08 17:38:17 -04:00
if ( ret < 0 )
return CL_EDUP ;
2013-02-19 15:56:26 -05:00
fd = dup ( ret ) ;
2017-08-08 17:38:17 -04:00
if ( fd < 0 )
return CL_EDUP ;
2018-12-03 12:40:13 -05:00
if ( ! ( gz = gzdopen ( fd , " rb " ) ) ) {
2017-08-08 17:38:17 -04:00
close ( fd ) ;
return CL_EOPEN ;
}
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_gentempfd ( ctx - > engine - > tmpdir , & tmpname , & fd ) ) ! = CL_SUCCESS ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " GZip: Can't generate temporary file. \n " ) ;
gzclose ( gz ) ;
close ( fd ) ;
return ret ;
}
2018-12-03 12:40:13 -05:00
while ( ( bytes = gzread ( gz , buff , FILEBUFF ) ) > 0 ) {
2017-08-08 17:38:17 -04:00
outsize + = bytes ;
if ( cli_checklimits ( " GZip " , ctx , outsize , 0 , 0 ) ! = CL_CLEAN )
break ;
2018-12-03 12:40:13 -05:00
if ( cli_writen ( fd , buff , bytes ) ! = bytes ) {
2017-08-08 17:38:17 -04:00
close ( fd ) ;
gzclose ( gz ) ;
2018-12-03 12:40:13 -05:00
if ( cli_unlink ( tmpname ) ) {
2017-08-08 17:38:17 -04:00
free ( tmpname ) ;
return CL_EUNLINK ;
}
free ( tmpname ) ;
return CL_EWRITE ;
}
2010-02-09 16:36:14 +01:00
}
gzclose ( gz ) ;
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_magic_scandesc ( fd , tmpname , ctx ) ) = = CL_VIRUS ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " GZip: Infected with %s \n " , cli_get_last_virus ( ctx ) ) ;
close ( fd ) ;
2018-12-03 12:40:13 -05:00
if ( ! ctx - > engine - > keeptmp ) {
if ( cli_unlink ( tmpname ) ) {
2017-08-08 17:38:17 -04:00
free ( tmpname ) ;
return CL_EUNLINK ;
}
}
free ( tmpname ) ;
return CL_VIRUS ;
2010-02-09 16:36:14 +01:00
}
close ( fd ) ;
2017-08-08 17:38:17 -04:00
if ( ! ctx - > engine - > keeptmp )
if ( cli_unlink ( tmpname ) )
ret = CL_EUNLINK ;
2010-02-09 16:36:14 +01:00
free ( tmpname ) ;
return ret ;
}
2009-09-01 23:33:17 +02:00
static int cli_scangzip ( cli_ctx * ctx )
2003-07-29 15:48:06 +00:00
{
2017-08-08 17:38:17 -04:00
int fd , ret = CL_CLEAN ;
unsigned char buff [ FILEBUFF ] ;
char * tmpname ;
z_stream z ;
size_t at = 0 , outsize = 0 ;
fmap_t * map = * ctx - > fmap ;
2003-11-09 19:26:44 +00:00
cli_dbgmsg ( " in cli_scangzip() \n " ) ;
2009-09-01 23:33:17 +02:00
memset ( & z , 0 , sizeof ( z ) ) ;
2018-12-03 12:40:13 -05:00
if ( ( ret = inflateInit2 ( & z , MAX_WBITS + 16 ) ) ! = Z_OK ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " GZip: InflateInit failed: %d \n " , ret ) ;
return cli_scangzip_with_zib_from_the_80s ( ctx , buff ) ;
}
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_gentempfd ( ctx - > engine - > tmpdir , & tmpname , & fd ) ) ! = CL_SUCCESS ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " GZip: Can't generate temporary file. \n " ) ;
inflateEnd ( & z ) ;
return ret ;
}
2018-12-03 12:40:13 -05:00
while ( at < map - > len ) {
2017-08-08 17:38:17 -04:00
unsigned int bytes = MIN ( map - > len - at , map - > pgsz ) ;
2018-12-03 12:40:13 -05:00
if ( ! ( z . next_in = ( void * ) fmap_need_off_once ( map , at , bytes ) ) ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " GZip: Can't read %u bytes @ %lu. \n " , bytes , ( long unsigned ) at ) ;
inflateEnd ( & z ) ;
close ( fd ) ;
2018-12-03 12:40:13 -05:00
if ( cli_unlink ( tmpname ) ) {
2017-08-08 17:38:17 -04:00
free ( tmpname ) ;
return CL_EUNLINK ;
}
free ( tmpname ) ;
return CL_EREAD ;
}
at + = bytes ;
z . avail_in = bytes ;
2018-12-03 12:40:13 -05:00
do {
2017-08-08 17:38:17 -04:00
int inf ;
z . avail_out = sizeof ( buff ) ;
2018-12-03 12:40:13 -05:00
z . next_out = buff ;
inf = inflate ( & z , Z_NO_FLUSH ) ;
if ( inf ! = Z_OK & & inf ! = Z_STREAM_END & & inf ! = Z_BUF_ERROR ) {
if ( sizeof ( buff ) = = z . avail_out ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " GZip: Bad stream, nothing in output buffer. \n " ) ;
at = map - > len ;
break ;
2018-12-03 12:40:13 -05:00
} else {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " GZip: Bad stream, data in output buffer. \n " ) ;
/* no break yet, flush extracted bytes to file */
}
}
2018-12-03 12:40:13 -05:00
if ( cli_writen ( fd , buff , sizeof ( buff ) - z . avail_out ) < 0 ) {
2017-08-08 17:38:17 -04:00
inflateEnd ( & z ) ;
close ( fd ) ;
2018-12-03 12:40:13 -05:00
if ( cli_unlink ( tmpname ) ) {
2017-08-08 17:38:17 -04:00
free ( tmpname ) ;
return CL_EUNLINK ;
}
free ( tmpname ) ;
return CL_EWRITE ;
}
outsize + = sizeof ( buff ) - z . avail_out ;
2018-12-03 12:40:13 -05:00
if ( cli_checklimits ( " GZip " , ctx , outsize , 0 , 0 ) ! = CL_CLEAN ) {
2017-08-08 17:38:17 -04:00
at = map - > len ;
break ;
}
2018-12-03 12:40:13 -05:00
if ( inf = = Z_STREAM_END ) {
2017-08-08 17:38:17 -04:00
at - = z . avail_in ;
inflateReset ( & z ) ;
break ;
2018-12-03 12:40:13 -05:00
} else if ( inf ! = Z_OK & & inf ! = Z_BUF_ERROR ) {
2017-08-08 17:38:17 -04:00
at = map - > len ;
break ;
}
} while ( z . avail_out = = 0 ) ;
}
inflateEnd ( & z ) ;
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_magic_scandesc ( fd , tmpname , ctx ) ) = = CL_VIRUS ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " GZip: Infected with %s \n " , cli_get_last_virus ( ctx ) ) ;
close ( fd ) ;
2018-12-03 12:40:13 -05:00
if ( ! ctx - > engine - > keeptmp ) {
if ( cli_unlink ( tmpname ) ) {
2017-08-08 17:38:17 -04:00
free ( tmpname ) ;
return CL_EUNLINK ;
}
}
free ( tmpname ) ;
return CL_VIRUS ;
2003-07-29 15:48:06 +00:00
}
2007-08-31 19:55:09 +00:00
close ( fd ) ;
2017-08-08 17:38:17 -04:00
if ( ! ctx - > engine - > keeptmp )
if ( cli_unlink ( tmpname ) )
ret = CL_EUNLINK ;
2009-09-01 23:33:17 +02:00
free ( tmpname ) ;
2003-07-29 15:48:06 +00:00
return ret ;
}
2008-07-25 00:44:01 +00:00
# ifndef HAVE_BZLIB_H
2017-08-08 17:38:17 -04:00
static int cli_scanbzip ( cli_ctx * ctx )
{
2008-07-25 00:44:01 +00:00
cli_warnmsg ( " cli_scanbzip: bzip2 support not compiled in \n " ) ;
return CL_CLEAN ;
}
# else
2003-07-29 15:48:06 +00:00
# ifdef NOBZ2PREFIX
2011-06-10 21:22:46 +03:00
# define BZ2_bzDecompressInit bzDecompressInit
# define BZ2_bzDecompress bzDecompress
# define BZ2_bzDecompressEnd bzDecompressEnd
2003-07-29 15:48:06 +00:00
# endif
2011-06-10 21:22:46 +03:00
static int cli_scanbzip ( cli_ctx * ctx )
2003-07-29 15:48:06 +00:00
{
2011-06-10 21:22:46 +03:00
int ret = CL_CLEAN , fd , rc ;
unsigned long int size = 0 ;
char * tmpname ;
bz_stream strm ;
size_t off = 0 ;
size_t avail ;
char buf [ FILEBUFF ] ;
memset ( & strm , 0 , sizeof ( strm ) ) ;
strm . next_out = buf ;
strm . avail_out = sizeof ( buf ) ;
rc = BZ2_bzDecompressInit ( & strm , 0 , 0 ) ;
2018-12-03 12:40:13 -05:00
if ( BZ_OK ! = rc ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Bzip: DecompressInit failed: %d \n " , rc ) ;
return CL_EOPEN ;
}
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_gentempfd ( ctx - > engine - > tmpdir , & tmpname , & fd ) ) ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Bzip: Can't generate temporary file. \n " ) ;
BZ2_bzDecompressEnd ( & strm ) ;
return ret ;
}
2018-12-03 12:40:13 -05:00
do {
if ( ! strm . avail_in ) {
2017-08-08 17:38:17 -04:00
strm . next_in = ( void * ) fmap_need_off_once_len ( * ctx - > fmap , off , FILEBUFF , & avail ) ;
strm . avail_in = avail ;
off + = avail ;
2018-12-03 12:40:13 -05:00
if ( ! strm . avail_in ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Bzip: premature end of compressed stream \n " ) ;
break ;
}
}
rc = BZ2_bzDecompress ( & strm ) ;
2018-12-03 12:40:13 -05:00
if ( BZ_OK ! = rc & & BZ_STREAM_END ! = rc ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Bzip: decompress error: %d \n " , rc ) ;
break ;
}
2018-12-03 12:40:13 -05:00
if ( ! strm . avail_out | | BZ_STREAM_END = = rc ) {
2017-08-08 17:38:17 -04:00
size + = sizeof ( buf ) - strm . avail_out ;
2018-12-03 12:40:13 -05:00
if ( cli_writen ( fd , buf , sizeof ( buf ) - strm . avail_out ) ! = sizeof ( buf ) - strm . avail_out ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Bzip: Can't write to file. \n " ) ;
BZ2_bzDecompressEnd ( & strm ) ;
close ( fd ) ;
2018-12-03 12:40:13 -05:00
if ( ! ctx - > engine - > keeptmp ) {
if ( cli_unlink ( tmpname ) ) {
2017-08-08 17:38:17 -04:00
free ( tmpname ) ;
return CL_EUNLINK ;
}
}
free ( tmpname ) ;
return CL_EWRITE ;
}
if ( cli_checklimits ( " Bzip " , ctx , size , 0 , 0 ) ! = CL_CLEAN )
break ;
strm . next_out = buf ;
strm . avail_out = sizeof ( buf ) ;
}
2011-06-10 21:22:46 +03:00
} while ( BZ_STREAM_END ! = rc ) ;
2003-07-29 15:48:06 +00:00
2011-06-10 21:22:46 +03:00
BZ2_bzDecompressEnd ( & strm ) ;
2005-04-06 22:48:06 +00:00
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_magic_scandesc ( fd , tmpname , ctx ) ) = = CL_VIRUS ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Bzip: Infected with %s \n " , cli_get_last_virus ( ctx ) ) ;
close ( fd ) ;
2018-12-03 12:40:13 -05:00
if ( ! ctx - > engine - > keeptmp ) {
if ( cli_unlink ( tmpname ) ) {
2017-08-08 17:38:17 -04:00
ret = CL_EUNLINK ;
free ( tmpname ) ;
return ret ;
}
}
free ( tmpname ) ;
return CL_VIRUS ;
2003-07-29 15:48:06 +00:00
}
2007-08-31 19:55:09 +00:00
close ( fd ) ;
2017-08-08 17:38:17 -04:00
if ( ! ctx - > engine - > keeptmp )
if ( cli_unlink ( tmpname ) )
ret = CL_EUNLINK ;
2011-06-10 21:22:46 +03:00
free ( tmpname ) ;
2003-07-29 15:48:06 +00:00
return ret ;
}
# endif
2013-10-08 17:17:44 -04:00
static int cli_scanxz ( cli_ctx * ctx )
{
2018-12-03 12:40:13 -05:00
int ret = CL_CLEAN , fd , rc ;
2013-10-08 17:17:44 -04:00
unsigned long int size = 0 ;
char * tmpname ;
2014-07-09 13:16:31 -04:00
struct CLI_XZ strm ;
2013-10-08 17:17:44 -04:00
size_t off = 0 ;
size_t avail ;
2014-07-09 13:16:31 -04:00
unsigned char * buf ;
2013-10-08 17:17:44 -04:00
2014-07-09 13:16:31 -04:00
buf = cli_malloc ( CLI_XZ_OBUF_SIZE ) ;
2018-12-03 12:40:13 -05:00
if ( buf = = NULL ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " cli_scanxz: nomemory for decompress buffer. \n " ) ;
2013-10-09 15:41:55 -04:00
return CL_EMEM ;
}
2014-07-09 13:16:31 -04:00
memset ( & strm , 0x00 , sizeof ( struct CLI_XZ ) ) ;
2018-12-03 12:40:13 -05:00
strm . next_out = buf ;
2013-10-09 15:41:55 -04:00
strm . avail_out = CLI_XZ_OBUF_SIZE ;
2018-12-03 12:40:13 -05:00
rc = cli_XzInit ( & strm ) ;
if ( rc ! = XZ_RESULT_OK ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " cli_scanxz: DecompressInit failed: %i \n " , rc ) ;
2013-10-09 15:41:55 -04:00
free ( buf ) ;
2017-08-08 17:38:17 -04:00
return CL_EOPEN ;
2013-10-08 17:17:44 -04:00
}
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_gentempfd ( ctx - > engine - > tmpdir , & tmpname , & fd ) ) ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " cli_scanxz: Can't generate temporary file. \n " ) ;
cli_XzShutdown ( & strm ) ;
2013-10-09 15:41:55 -04:00
free ( buf ) ;
2017-08-08 17:38:17 -04:00
return ret ;
2013-10-08 17:17:44 -04:00
}
cli_dbgmsg ( " cli_scanxz: decompressing to file %s \n " , tmpname ) ;
2018-12-03 12:40:13 -05:00
do {
2013-10-08 17:17:44 -04:00
/* set up input buffer */
2018-12-03 12:40:13 -05:00
if ( ! strm . avail_in ) {
strm . next_in = ( void * ) fmap_need_off_once_len ( * ctx - > fmap , off , CLI_XZ_IBUF_SIZE , & avail ) ;
2017-08-08 17:38:17 -04:00
strm . avail_in = avail ;
off + = avail ;
2018-12-03 12:40:13 -05:00
if ( ! strm . avail_in ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " cli_scanxz: premature end of compressed stream \n " ) ;
2013-10-08 17:17:44 -04:00
ret = CL_EFORMAT ;
2017-08-08 17:38:17 -04:00
goto xz_exit ;
}
}
2013-10-08 17:17:44 -04:00
/* xz decompress a chunk */
2017-08-08 17:38:17 -04:00
rc = cli_XzDecode ( & strm ) ;
2018-12-03 12:40:13 -05:00
if ( XZ_RESULT_OK ! = rc & & XZ_STREAM_END ! = rc ) {
if ( rc = = XZ_DIC_HEURISTIC ) {
2018-07-20 22:28:48 -04:00
ret = cli_append_virus ( ctx , " Heuristics.XZ.DicSizeLimit " ) ;
2017-06-19 15:41:17 -04:00
goto xz_exit ;
}
2017-08-08 17:38:17 -04:00
cli_errmsg ( " cli_scanxz: decompress error: %d \n " , rc ) ;
2013-10-08 17:17:44 -04:00
ret = CL_EFORMAT ;
goto xz_exit ;
2017-08-08 17:38:17 -04:00
}
2013-10-08 17:17:44 -04:00
//cli_dbgmsg("cli_scanxz: xz decompressed %li of %li available bytes\n",
// avail - strm.avail_in, avail);
2017-08-08 17:38:17 -04:00
2013-10-08 17:17:44 -04:00
/* write decompress buffer */
2018-12-03 12:40:13 -05:00
if ( ! strm . avail_out | | rc = = XZ_STREAM_END ) {
2017-08-08 17:38:17 -04:00
size_t towrite = CLI_XZ_OBUF_SIZE - strm . avail_out ;
size + = towrite ;
2013-10-08 17:17:44 -04:00
//cli_dbgmsg("Writing %li bytes to XZ decompress temp file(%li byte total)\n",
// towrite, size);
2018-12-03 12:40:13 -05:00
if ( ( size_t ) cli_writen ( fd , buf , towrite ) ! = towrite ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " cli_scanxz: Can't write to file. \n " ) ;
2013-10-08 17:17:44 -04:00
ret = CL_EWRITE ;
goto xz_exit ;
2017-08-08 17:38:17 -04:00
}
2018-12-03 12:40:13 -05:00
if ( cli_checklimits ( " cli_scanxz " , ctx , size , 0 , 0 ) ! = CL_CLEAN ) {
2013-10-08 17:17:44 -04:00
cli_warnmsg ( " cli_scanxz: decompress file size exceeds limits - "
2017-08-08 17:38:17 -04:00
" only scanning %li bytes \n " ,
size ) ;
break ;
2013-10-08 17:17:44 -04:00
}
2018-12-03 12:40:13 -05:00
strm . next_out = buf ;
2017-08-08 17:38:17 -04:00
strm . avail_out = CLI_XZ_OBUF_SIZE ;
}
2013-10-08 17:17:44 -04:00
} while ( XZ_STREAM_END ! = rc ) ;
/* scan decompressed file */
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_magic_scandesc ( fd , tmpname , ctx ) ) = = CL_VIRUS ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_scanxz: Infected with %s \n " , cli_get_last_virus ( ctx ) ) ;
2013-10-08 17:17:44 -04:00
}
2017-08-08 17:38:17 -04:00
xz_exit :
2013-10-08 17:17:44 -04:00
cli_XzShutdown ( & strm ) ;
close ( fd ) ;
2017-08-08 17:38:17 -04:00
if ( ! ctx - > engine - > keeptmp )
if ( cli_unlink ( tmpname ) & & ret = = CL_CLEAN )
2013-10-08 17:17:44 -04:00
ret = CL_EUNLINK ;
free ( tmpname ) ;
2013-10-09 15:41:55 -04:00
free ( buf ) ;
2013-10-08 17:17:44 -04:00
return ret ;
}
2011-06-10 19:09:38 +02:00
static int cli_scanszdd ( cli_ctx * ctx )
2004-05-02 00:51:01 +00:00
{
2017-08-08 17:38:17 -04:00
int ofd , ret ;
char * tmpname ;
2004-09-07 21:19:02 +00:00
2005-06-11 20:27:59 +00:00
cli_dbgmsg ( " in cli_scanszdd() \n " ) ;
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_gentempfd ( ctx - > engine - > tmpdir , & tmpname , & ofd ) ) ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " MSEXPAND: Can't generate temporary file/descriptor \n " ) ;
return ret ;
2004-05-02 00:51:01 +00:00
}
2011-06-10 19:09:38 +02:00
ret = cli_msexpand ( ctx , ofd ) ;
2004-05-02 00:51:01 +00:00
2018-12-03 12:40:13 -05:00
if ( ret ! = CL_SUCCESS ) { /* CL_VIRUS or some error */
2017-08-08 17:38:17 -04:00
close ( ofd ) ;
if ( ! ctx - > engine - > keeptmp )
if ( cli_unlink ( tmpname ) )
ret = CL_EUNLINK ;
free ( tmpname ) ;
return ret ;
2004-05-02 00:51:01 +00:00
}
2007-12-13 23:18:03 +00:00
cli_dbgmsg ( " MSEXPAND: Decompressed into %s \n " , tmpname ) ;
2018-07-30 20:19:28 -04:00
ret = cli_magic_scandesc ( ofd , tmpname , ctx ) ;
2007-12-13 23:18:03 +00:00
close ( ofd ) ;
2017-08-08 17:38:17 -04:00
if ( ! ctx - > engine - > keeptmp )
if ( cli_unlink ( tmpname ) )
ret = CL_EUNLINK ;
free ( tmpname ) ;
2007-12-13 23:18:03 +00:00
2004-05-02 00:51:01 +00:00
return ret ;
}
2011-11-18 15:25:04 +01:00
static int vba_scandata ( const unsigned char * data , unsigned int len , cli_ctx * ctx )
{
2017-08-08 17:38:17 -04:00
struct cli_matcher * groot = ctx - > engine - > root [ 0 ] ;
struct cli_matcher * troot = ctx - > engine - > root [ 2 ] ;
struct cli_ac_data gmdata , tmdata ;
struct cli_ac_data * mdata [ 2 ] ;
int ret ;
unsigned int viruses_found = 0 ;
2011-11-18 15:25:04 +01:00
2017-08-08 17:38:17 -04:00
if ( ( ret = cli_ac_initdata ( & tmdata , troot - > ac_partsigs , troot - > ac_lsigs , troot - > ac_reloff_num , CLI_DEFAULT_AC_TRACKLEN ) ) )
return ret ;
2011-11-18 15:25:04 +01:00
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_ac_initdata ( & gmdata , groot - > ac_partsigs , groot - > ac_lsigs , groot - > ac_reloff_num , CLI_DEFAULT_AC_TRACKLEN ) ) ) {
2017-08-08 17:38:17 -04:00
cli_ac_freedata ( & tmdata ) ;
return ret ;
2011-11-18 15:25:04 +01:00
}
mdata [ 0 ] = & tmdata ;
mdata [ 1 ] = & gmdata ;
ret = cli_scanbuff ( data , len , 0 , ctx , CL_TYPE_MSOLE2 , mdata ) ;
2012-11-30 11:16:47 -08:00
if ( ret = = CL_VIRUS )
2017-08-08 17:38:17 -04:00
viruses_found + + ;
2011-11-18 15:25:04 +01:00
2018-12-03 12:40:13 -05:00
if ( ret = = CL_CLEAN | | ( ret = = CL_VIRUS & & SCAN_ALLMATCHES ) ) {
2017-08-08 17:38:17 -04:00
fmap_t * map = * ctx - > fmap ;
2018-12-03 12:40:13 -05:00
* ctx - > fmap = cl_fmap_open_memory ( data , len ) ;
2016-10-24 18:03:36 -04:00
if ( * ctx - > fmap = = NULL )
return CL_EMEM ;
2017-08-08 17:38:17 -04:00
ret = cli_exp_eval ( ctx , troot , & tmdata , NULL , NULL ) ;
if ( ret = = CL_VIRUS )
viruses_found + + ;
2012-11-30 11:16:47 -08:00
2018-07-20 22:28:48 -04:00
if ( ret = = CL_CLEAN | | ( ret = = CL_VIRUS & & SCAN_ALLMATCHES ) )
2017-08-08 17:38:17 -04:00
ret = cli_exp_eval ( ctx , groot , & gmdata , NULL , NULL ) ;
2016-10-24 18:03:36 -04:00
funmap ( * ctx - > fmap ) ;
* ctx - > fmap = map ;
2011-11-18 15:25:04 +01:00
}
cli_ac_freedata ( & tmdata ) ;
cli_ac_freedata ( & gmdata ) ;
2017-08-08 17:38:17 -04:00
return ( ret ! = CL_CLEAN ) ? ret : viruses_found ? CL_VIRUS : CL_CLEAN ;
2011-11-18 15:25:04 +01:00
}
2008-05-27 16:30:47 +00:00
static int cli_vba_scandir ( const char * dirname , cli_ctx * ctx , struct uniq * U )
2003-07-29 15:48:06 +00:00
{
2017-08-08 17:38:17 -04:00
int ret = CL_CLEAN , i , j , fd , data_len , hasmacros = 0 ;
vba_project_t * vba_project ;
DIR * dd ;
struct dirent * dent ;
2004-10-03 15:12:13 +00:00
# if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2)
2017-08-08 17:38:17 -04:00
union {
struct dirent d ;
char b [ offsetof ( struct dirent , d_name ) + NAME_MAX + 1 ] ;
} result ;
2004-10-03 15:12:13 +00:00
# endif
2017-08-08 17:38:17 -04:00
STATBUF statbuf ;
char * fullname , vbaname [ 1024 ] ;
unsigned char * data ;
char * hash ;
uint32_t hashcnt ;
unsigned int viruses_found = 0 ;
2004-09-07 21:19:02 +00:00
cli_dbgmsg ( " VBADir: %s \n " , dirname ) ;
2008-05-27 16:30:47 +00:00
hashcnt = uniq_get ( U , " _vba_project " , 12 , NULL ) ;
2018-12-03 12:40:13 -05:00
while ( hashcnt - - ) {
2017-08-08 17:38:17 -04:00
if ( ! ( vba_project = ( vba_project_t * ) cli_vba_readdir ( dirname , U , hashcnt ) ) )
continue ;
2018-12-03 12:40:13 -05:00
for ( i = 0 ; i < vba_project - > count ; i + + ) {
for ( j = 0 ; ( unsigned int ) j < vba_project - > colls [ i ] ; j + + ) {
2017-08-08 17:38:17 -04:00
snprintf ( vbaname , 1024 , " %s " PATHSEP " %s_%u " , vba_project - > dir , vba_project - > name [ i ] , j ) ;
vbaname [ sizeof ( vbaname ) - 1 ] = ' \0 ' ;
2018-12-03 12:40:13 -05:00
fd = open ( vbaname , O_RDONLY | O_BINARY ) ;
2017-08-08 17:38:17 -04:00
if ( fd = = - 1 )
continue ;
cli_dbgmsg ( " VBADir: Decompress VBA project '%s_%u' \n " , vba_project - > name [ i ] , j ) ;
data = ( unsigned char * ) cli_vba_inflate ( fd , vba_project - > offset [ i ] , & data_len ) ;
close ( fd ) ;
hasmacros + + ;
2018-12-03 12:40:13 -05:00
if ( ! data ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " VBADir: WARNING: VBA project '%s_%u' decompressed to NULL \n " , vba_project - > name [ i ] , j ) ;
2018-12-03 12:40:13 -05:00
} else {
2017-08-08 17:38:17 -04:00
/* cli_dbgmsg("Project content:\n%s", data); */
if ( ctx - > scanned )
* ctx - > scanned + = data_len / CL_COUNT_PRECISION ;
2018-12-03 12:40:13 -05:00
if ( ctx - > engine - > keeptmp ) {
2017-08-08 17:38:17 -04:00
char * tempfile ;
int of ;
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_gentempfd ( ctx - > engine - > tmpdir , & tempfile , & of ) ) ! = CL_SUCCESS ) {
2017-08-08 17:38:17 -04:00
cli_warnmsg ( " VBADir: WARNING: VBA project '%s_%u' cannot be dumped to file \n " , vba_project - > name [ i ] , j ) ;
return ret ;
}
2018-12-03 12:40:13 -05:00
if ( cli_writen ( of , data , data_len ) ! = data_len ) {
2017-08-08 17:38:17 -04:00
cli_warnmsg ( " VBADir: WARNING: VBA project '%s_%u' failed to write to file \n " , vba_project - > name [ i ] , j ) ;
close ( of ) ;
free ( tempfile ) ;
return CL_EWRITE ;
}
cli_dbgmsg ( " VBADir: VBA project '%s_%u' dumped to %s \n " , vba_project - > name [ i ] , j , tempfile ) ;
free ( tempfile ) ;
}
2018-12-03 12:40:13 -05:00
if ( vba_scandata ( data , data_len , ctx ) = = CL_VIRUS ) {
2018-07-20 22:28:48 -04:00
if ( SCAN_ALLMATCHES )
2017-08-08 17:38:17 -04:00
viruses_found + + ;
2018-12-03 12:40:13 -05:00
else {
2017-08-08 17:38:17 -04:00
free ( data ) ;
ret = CL_VIRUS ;
break ;
}
}
free ( data ) ;
}
}
}
free ( vba_project - > name ) ;
free ( vba_project - > colls ) ;
free ( vba_project - > dir ) ;
free ( vba_project - > offset ) ;
free ( vba_project ) ;
2018-07-20 22:28:48 -04:00
if ( ret = = CL_VIRUS & & ! SCAN_ALLMATCHES )
2017-08-08 17:38:17 -04:00
break ;
}
2018-07-20 22:28:48 -04:00
if ( ( ret = = CL_CLEAN | | ( ret = = CL_VIRUS & & SCAN_ALLMATCHES ) ) & &
2018-12-03 12:40:13 -05:00
( hashcnt = uniq_get ( U , " powerpoint document " , 19 , & hash ) ) ) {
while ( hashcnt - - ) {
2017-08-08 17:38:17 -04:00
snprintf ( vbaname , 1024 , " %s " PATHSEP " %s_%u " , dirname , hash , hashcnt ) ;
vbaname [ sizeof ( vbaname ) - 1 ] = ' \0 ' ;
2018-12-03 12:40:13 -05:00
fd = open ( vbaname , O_RDONLY | O_BINARY ) ;
2017-08-08 17:38:17 -04:00
if ( fd = = - 1 )
continue ;
2018-12-03 12:40:13 -05:00
if ( ( fullname = cli_ppt_vba_read ( fd , ctx ) ) ) {
if ( cli_scandir ( fullname , ctx ) = = CL_VIRUS ) {
2017-08-08 17:38:17 -04:00
ret = CL_VIRUS ;
viruses_found + + ;
}
if ( ! ctx - > engine - > keeptmp )
cli_rmdirs ( fullname ) ;
free ( fullname ) ;
}
close ( fd ) ;
}
}
2018-07-20 22:28:48 -04:00
if ( ( ret = = CL_CLEAN | | ( ret = = CL_VIRUS & & SCAN_ALLMATCHES ) ) & &
2018-12-03 12:40:13 -05:00
( hashcnt = uniq_get ( U , " worddocument " , 12 , & hash ) ) ) {
while ( hashcnt - - ) {
2017-08-08 17:38:17 -04:00
snprintf ( vbaname , sizeof ( vbaname ) , " %s " PATHSEP " %s_%u " , dirname , hash , hashcnt ) ;
vbaname [ sizeof ( vbaname ) - 1 ] = ' \0 ' ;
2018-12-03 12:40:13 -05:00
fd = open ( vbaname , O_RDONLY | O_BINARY ) ;
2017-08-08 17:38:17 -04:00
if ( fd = = - 1 )
continue ;
2018-12-03 12:40:13 -05:00
if ( ! ( vba_project = ( vba_project_t * ) cli_wm_readdir ( fd ) ) ) {
2017-08-08 17:38:17 -04:00
close ( fd ) ;
continue ;
}
2018-12-03 12:40:13 -05:00
for ( i = 0 ; i < vba_project - > count ; i + + ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " VBADir: Decompress WM project macro:%d key:%d length:%d \n " , i , vba_project - > key [ i ] , vba_project - > length [ i ] ) ;
data = ( unsigned char * ) cli_wm_decrypt_macro ( fd , vba_project - > offset [ i ] , vba_project - > length [ i ] , vba_project - > key [ i ] ) ;
2018-12-03 12:40:13 -05:00
if ( ! data ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " VBADir: WARNING: WM project '%s' macro %d decrypted to NULL \n " , vba_project - > name [ i ] , i ) ;
2018-12-03 12:40:13 -05:00
} else {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Project content: \n %s " , data ) ;
if ( ctx - > scanned )
* ctx - > scanned + = vba_project - > length [ i ] / CL_COUNT_PRECISION ;
2018-12-03 12:40:13 -05:00
if ( vba_scandata ( data , vba_project - > length [ i ] , ctx ) = = CL_VIRUS ) {
2018-07-20 22:28:48 -04:00
if ( SCAN_ALLMATCHES )
2017-08-08 17:38:17 -04:00
viruses_found + + ;
2018-12-03 12:40:13 -05:00
else {
2017-08-08 17:38:17 -04:00
free ( data ) ;
ret = CL_VIRUS ;
break ;
}
}
free ( data ) ;
}
}
close ( fd ) ;
free ( vba_project - > name ) ;
free ( vba_project - > colls ) ;
free ( vba_project - > dir ) ;
free ( vba_project - > offset ) ;
free ( vba_project - > key ) ;
free ( vba_project - > length ) ;
free ( vba_project ) ;
2018-12-03 12:40:13 -05:00
if ( ret = = CL_VIRUS ) {
2018-07-20 22:28:48 -04:00
if ( SCAN_ALLMATCHES )
2017-08-08 17:38:17 -04:00
viruses_found + + ;
else
break ;
}
}
}
2018-07-20 22:28:48 -04:00
if ( ret ! = CL_CLEAN & & ! ( ret = = CL_VIRUS & & SCAN_ALLMATCHES ) )
2017-08-08 17:38:17 -04:00
return ret ;
2003-07-29 15:48:06 +00:00
2014-04-23 18:15:29 -04:00
# if HAVE_JSON
2014-04-21 16:44:26 -04:00
/* JSON Output Summary Information */
2018-12-03 12:40:13 -05:00
if ( SCAN_COLLECT_METADATA & & ( ctx - > wrkproperty ! = NULL ) ) {
2014-04-23 18:15:29 -04:00
hashcnt = uniq_get ( U , " _5_summaryinformation " , 21 , & hash ) ;
2018-12-03 12:40:13 -05:00
while ( hashcnt - - ) {
2017-08-08 17:38:17 -04:00
snprintf ( vbaname , sizeof ( vbaname ) , " %s " PATHSEP " %s_%u " , dirname , hash , hashcnt ) ;
vbaname [ sizeof ( vbaname ) - 1 ] = ' \0 ' ;
fd = open ( vbaname , O_RDONLY | O_BINARY ) ;
2018-12-03 12:40:13 -05:00
if ( fd > = 0 ) {
2014-04-23 18:15:29 -04:00
cli_dbgmsg ( " VBADir: detected a '_5_summaryinformation' stream \n " ) ;
2014-04-24 14:22:00 -04:00
/* JSONOLE2 - what to do if something breaks? */
2014-04-23 18:15:29 -04:00
cli_ole2_summary_json ( ctx , fd , 0 ) ;
close ( fd ) ;
}
}
2014-04-21 16:44:26 -04:00
2014-04-23 18:15:29 -04:00
hashcnt = uniq_get ( U , " _5_documentsummaryinformation " , 29 , & hash ) ;
2018-12-03 12:40:13 -05:00
while ( hashcnt - - ) {
2017-08-08 17:38:17 -04:00
snprintf ( vbaname , sizeof ( vbaname ) , " %s " PATHSEP " %s_%u " , dirname , hash , hashcnt ) ;
vbaname [ sizeof ( vbaname ) - 1 ] = ' \0 ' ;
fd = open ( vbaname , O_RDONLY | O_BINARY ) ;
2018-12-03 12:40:13 -05:00
if ( fd > = 0 ) {
2014-04-23 18:15:29 -04:00
cli_dbgmsg ( " VBADir: detected a '_5_documentsummaryinformation' stream \n " ) ;
2014-04-24 14:22:00 -04:00
/* JSONOLE2 - what to do if something breaks? */
2014-04-23 18:15:29 -04:00
cli_ole2_summary_json ( ctx , fd , 1 ) ;
close ( fd ) ;
}
2014-04-21 16:44:26 -04:00
}
}
2017-08-08 17:38:17 -04:00
# endif
2014-04-21 16:44:26 -04:00
2005-04-14 18:42:13 +00:00
/* Check directory for embedded OLE objects */
2008-05-27 16:30:47 +00:00
hashcnt = uniq_get ( U , " _1_ole10native " , 14 , & hash ) ;
2018-12-03 12:40:13 -05:00
while ( hashcnt - - ) {
2017-08-08 17:38:17 -04:00
snprintf ( vbaname , sizeof ( vbaname ) , " %s " PATHSEP " %s_%u " , dirname , hash , hashcnt ) ;
vbaname [ sizeof ( vbaname ) - 1 ] = ' \0 ' ;
fd = open ( vbaname , O_RDONLY | O_BINARY ) ;
2018-12-03 12:40:13 -05:00
if ( fd > = 0 ) {
2017-08-08 17:38:17 -04:00
ret = cli_scan_ole10 ( fd , ctx ) ;
close ( fd ) ;
2018-07-20 22:28:48 -04:00
if ( ret ! = CL_CLEAN & & ! ( ret = = CL_VIRUS & & SCAN_ALLMATCHES ) )
2017-08-08 17:38:17 -04:00
return ret ;
}
2005-04-14 18:42:13 +00:00
}
2008-05-27 16:30:47 +00:00
/* ACAB: since we now hash filenames and handle collisions we
* could avoid recursion by removing the block below and by
* flattening the paths in ole2_walk_property_tree ( case 1 ) */
2018-12-03 12:40:13 -05:00
if ( ( dd = opendir ( dirname ) ) ! = NULL ) {
2004-10-03 15:12:13 +00:00
# ifdef HAVE_READDIR_R_3
2018-12-03 12:40:13 -05:00
while ( ! readdir_r ( dd , & result . d , & dent ) & & dent ) {
2004-10-03 15:12:13 +00:00
# elif defined(HAVE_READDIR_R_2)
2018-12-03 12:40:13 -05:00
while ( ( dent = ( struct dirent * ) readdir_r ( dd , & result . d ) ) ) {
2004-10-03 15:12:13 +00:00
# else
2018-12-03 12:40:13 -05:00
while ( ( dent = readdir ( dd ) ) ) {
2004-10-03 15:12:13 +00:00
# endif
2018-12-03 12:40:13 -05:00
if ( dent - > d_ino ) {
if ( strcmp ( dent - > d_name , " . " ) & & strcmp ( dent - > d_name , " .. " ) ) {
2017-08-08 17:38:17 -04:00
/* build the full name */
fullname = cli_malloc ( strlen ( dirname ) + strlen ( dent - > d_name ) + 2 ) ;
2018-12-03 12:40:13 -05:00
if ( ! fullname ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_vba_scandir: Unable to allocate memory for fullname \n " ) ;
ret = CL_EMEM ;
break ;
}
sprintf ( fullname , " %s " PATHSEP " %s " , dirname , dent - > d_name ) ;
/* stat the file */
2018-12-03 12:40:13 -05:00
if ( LSTAT ( fullname , & statbuf ) ! = - 1 ) {
2017-08-08 17:38:17 -04:00
if ( S_ISDIR ( statbuf . st_mode ) & & ! S_ISLNK ( statbuf . st_mode ) )
2018-12-03 12:40:13 -05:00
if ( cli_vba_scandir ( fullname , ctx , U ) = = CL_VIRUS ) {
2018-07-20 22:28:48 -04:00
if ( SCAN_ALLMATCHES )
2017-08-08 17:38:17 -04:00
viruses_found + + ;
2018-12-03 12:40:13 -05:00
else {
2017-08-08 17:38:17 -04:00
ret = CL_VIRUS ;
free ( fullname ) ;
break ;
}
}
}
free ( fullname ) ;
}
}
}
2018-12-03 12:40:13 -05:00
} else {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " VBADir: Can't open directory %s. \n " , dirname ) ;
return CL_EOPEN ;
2003-07-29 15:48:06 +00:00
}
closedir ( dd ) ;
2014-05-19 16:45:52 -04:00
# if HAVE_JSON
2018-07-20 22:28:48 -04:00
if ( hasmacros & & SCAN_COLLECT_METADATA & & ( ctx - > wrkproperty ! = NULL ) )
2014-05-16 12:39:45 -04:00
cli_jsonbool ( ctx - > wrkproperty , " HasMacros " , 1 ) ;
2014-05-19 16:45:52 -04:00
# endif
2018-12-03 12:40:13 -05:00
if ( SCAN_HEURISTIC_MACROS & & hasmacros ) {
2017-08-08 17:38:17 -04:00
ret = cli_append_virus ( ctx , " Heuristics.OLE2.ContainsMacros " ) ;
if ( ret = = CL_VIRUS )
2017-04-18 12:03:36 -04:00
viruses_found + + ;
2010-10-29 19:04:23 +02:00
}
2018-07-20 22:28:48 -04:00
if ( SCAN_ALLMATCHES & & viruses_found )
2017-08-08 17:38:17 -04:00
return CL_VIRUS ;
2004-04-20 22:33:42 +00:00
return ret ;
}
2009-08-31 06:16:12 +02:00
static int cli_scanhtml ( cli_ctx * ctx )
2005-01-14 14:56:09 +00:00
{
2012-11-27 17:15:02 -05:00
char * tempname , fullname [ 1024 ] ;
2018-12-03 12:40:13 -05:00
int ret = CL_CLEAN , fd ;
fmap_t * map = * ctx - > fmap ;
2012-11-27 17:15:02 -05:00
unsigned int viruses_found = 0 ;
2018-12-03 12:40:13 -05:00
uint64_t curr_len = map - > len ;
2005-01-14 14:56:09 +00:00
cli_dbgmsg ( " in cli_scanhtml() \n " ) ;
2012-11-27 17:15:02 -05:00
/* CL_ENGINE_MAX_HTMLNORMALIZE */
2018-12-03 12:40:13 -05:00
if ( curr_len > ctx - > engine - > maxhtmlnormalize ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_scanhtml: exiting (file larger than MaxHTMLNormalize) \n " ) ;
return CL_CLEAN ;
2007-01-14 13:25:14 +00:00
}
2017-08-08 17:38:17 -04:00
if ( ! ( tempname = cli_gentemp ( ctx - > engine - > tmpdir ) ) )
return CL_EMEM ;
2008-03-06 20:19:22 +00:00
2018-12-03 12:40:13 -05:00
if ( mkdir ( tempname , 0700 ) ) {
2007-01-14 13:25:14 +00:00
cli_errmsg ( " cli_scanhtml: Can't create temporary directory %s \n " , tempname ) ;
2017-08-08 17:38:17 -04:00
free ( tempname ) ;
2005-01-14 14:56:09 +00:00
return CL_ETMPDIR ;
}
2008-03-18 22:44:39 +00:00
cli_dbgmsg ( " cli_scanhtml: using tempdir %s \n " , tempname ) ;
2017-08-08 17:38:17 -04:00
html_normalise_map ( map , tempname , NULL , ctx - > dconf ) ;
snprintf ( fullname , 1024 , " %s " PATHSEP " nocomment.html " , tempname ) ;
fd = open ( fullname , O_RDONLY | O_BINARY ) ;
2018-12-03 12:40:13 -05:00
if ( fd > = 0 ) {
2017-08-08 17:38:17 -04:00
if ( ( ret = cli_scandesc ( fd , ctx , CL_TYPE_HTML , 0 , NULL , AC_SCAN_VIR , NULL ) ) = = CL_VIRUS )
viruses_found + + ;
close ( fd ) ;
}
2018-12-03 12:40:13 -05:00
if ( ret = = CL_CLEAN | | ( ret = = CL_VIRUS & & SCAN_ALLMATCHES ) ) {
2017-08-08 17:38:17 -04:00
/* CL_ENGINE_MAX_HTMLNOTAGS */
curr_len = map - > len ;
2018-12-03 12:40:13 -05:00
if ( curr_len > ctx - > engine - > maxhtmlnotags ) {
2017-08-08 17:38:17 -04:00
/* we're not interested in scanning large files in notags form */
/* TODO: don't even create notags if file is over limit */
cli_dbgmsg ( " cli_scanhtml: skipping notags (normalized size over MaxHTMLNoTags) \n " ) ;
2018-12-03 12:40:13 -05:00
} else {
2017-08-08 17:38:17 -04:00
snprintf ( fullname , 1024 , " %s " PATHSEP " notags.html " , tempname ) ;
fd = open ( fullname , O_RDONLY | O_BINARY ) ;
2018-12-03 12:40:13 -05:00
if ( fd > = 0 ) {
2017-08-08 17:38:17 -04:00
if ( ( ret = cli_scandesc ( fd , ctx , CL_TYPE_HTML , 0 , NULL , AC_SCAN_VIR , NULL ) ) = = CL_VIRUS )
viruses_found + + ;
close ( fd ) ;
}
}
}
2018-12-03 12:40:13 -05:00
if ( ret = = CL_CLEAN | | ( ret = = CL_VIRUS & & SCAN_ALLMATCHES ) ) {
2017-08-08 17:38:17 -04:00
snprintf ( fullname , 1024 , " %s " PATHSEP " javascript " , tempname ) ;
fd = open ( fullname , O_RDONLY | O_BINARY ) ;
2018-12-03 12:40:13 -05:00
if ( fd > = 0 ) {
2017-08-08 17:38:17 -04:00
if ( ( ret = cli_scandesc ( fd , ctx , CL_TYPE_HTML , 0 , NULL , AC_SCAN_VIR , NULL ) ) = = CL_VIRUS )
viruses_found + + ;
2018-12-03 12:40:13 -05:00
if ( ret = = CL_CLEAN | | ( ret = = CL_VIRUS & & SCAN_ALLMATCHES ) ) {
2017-08-08 17:38:17 -04:00
if ( ( ret = cli_scandesc ( fd , ctx , CL_TYPE_TEXT_ASCII , 0 , NULL , AC_SCAN_VIR , NULL ) ) = = CL_VIRUS )
viruses_found + + ;
}
close ( fd ) ;
}
}
2018-12-03 12:40:13 -05:00
if ( ret = = CL_CLEAN | | ( ret = = CL_VIRUS & & SCAN_ALLMATCHES ) ) {
2017-08-08 17:38:17 -04:00
snprintf ( fullname , 1024 , " %s " PATHSEP " rfc2397 " , tempname ) ;
ret = cli_scandir ( fullname , ctx ) ;
}
if ( ! ctx - > engine - > keeptmp )
cli_rmdirs ( tempname ) ;
free ( tempname ) ;
2018-07-20 22:28:48 -04:00
if ( SCAN_ALLMATCHES & & viruses_found )
2017-08-08 17:38:17 -04:00
return CL_VIRUS ;
return ret ;
}
static int cli_scanscript ( cli_ctx * ctx )
{
const unsigned char * buff ;
unsigned char * normalized ;
struct text_norm_state state ;
char * tmpname = NULL ;
2018-12-03 12:40:13 -05:00
int ofd = - 1 , ret ;
2017-08-08 17:38:17 -04:00
struct cli_matcher * troot ;
uint32_t maxpatlen , offset = 0 ;
struct cli_matcher * groot ;
struct cli_ac_data gmdata , tmdata ;
struct cli_ac_data * mdata [ 2 ] ;
fmap_t * map ;
2018-12-03 12:40:13 -05:00
size_t at = 0 ;
2017-08-08 17:38:17 -04:00
unsigned int viruses_found = 0 ;
uint64_t curr_len ;
struct cli_target_info info ;
if ( ! ctx | | ! ctx - > engine - > root )
return CL_ENULLARG ;
2018-12-03 12:40:13 -05:00
map = * ctx - > fmap ;
curr_len = map - > len ;
groot = ctx - > engine - > root [ 0 ] ;
troot = ctx - > engine - > root [ 7 ] ;
2017-08-08 17:38:17 -04:00
maxpatlen = troot ? troot - > maxpatlen : 0 ;
cli_dbgmsg ( " in cli_scanscript() \n " ) ;
/* CL_ENGINE_MAX_SCRIPTNORMALIZE */
2018-12-03 12:40:13 -05:00
if ( curr_len > ctx - > engine - > maxscriptnormalize ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_scanscript: exiting (file larger than MaxScriptSize) \n " ) ;
return CL_CLEAN ;
}
2018-12-03 12:40:13 -05:00
if ( ! ( normalized = cli_malloc ( SCANBUFF + maxpatlen ) ) ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_scanscript: Unable to malloc %u bytes \n " , SCANBUFF ) ;
return CL_EMEM ;
}
text_normalize_init ( & state , normalized , SCANBUFF + maxpatlen ) ;
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_ac_initdata ( & tmdata , troot ? troot - > ac_partsigs : 0 , troot ? troot - > ac_lsigs : 0 , troot ? troot - > ac_reloff_num : 0 , CLI_DEFAULT_AC_TRACKLEN ) ) ) {
2017-08-08 17:38:17 -04:00
free ( normalized ) ;
return ret ;
}
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_ac_initdata ( & gmdata , groot - > ac_partsigs , groot - > ac_lsigs , groot - > ac_reloff_num , CLI_DEFAULT_AC_TRACKLEN ) ) ) {
2017-08-08 17:38:17 -04:00
cli_ac_freedata ( & tmdata ) ;
free ( normalized ) ;
return ret ;
}
/* dump to disk only if explicitly asked to
* or if necessary to check relative offsets ,
* otherwise we can process just in - memory */
2018-12-03 12:40:13 -05:00
if ( ctx - > engine - > keeptmp | | ( troot & & ( troot - > ac_reloff_num > 0 | | troot - > linked_bcs ) ) ) {
if ( ( ret = cli_gentempfd ( ctx - > engine - > tmpdir , & tmpname , & ofd ) ) ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_scanscript: Can't generate temporary file/descriptor \n " ) ;
goto done ;
}
if ( ctx - > engine - > keeptmp )
cli_dbgmsg ( " cli_scanscript: saving normalized file to %s \n " , tmpname ) ;
}
mdata [ 0 ] = & tmdata ;
mdata [ 1 ] = & gmdata ;
/* If there's a relative offset in troot or triggered bytecodes, normalize to file.*/
2018-12-03 12:40:13 -05:00
if ( troot & & ( troot - > ac_reloff_num > 0 | | troot - > linked_bcs ) ) {
2017-08-08 17:38:17 -04:00
size_t map_off = 0 ;
2018-12-03 12:40:13 -05:00
while ( map_off < map - > len ) {
2017-08-08 17:38:17 -04:00
size_t written ;
if ( ! ( written = text_normalize_map ( & state , map , map_off ) ) )
break ;
map_off + = written ;
2018-12-03 12:40:13 -05:00
if ( write ( ofd , state . out , state . out_pos ) = = - 1 ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " cli_scanscript: can't write to file %s \n " , tmpname ) ;
ret = CL_EWRITE ;
goto done ;
}
text_normalize_reset ( & state ) ;
}
/* Temporarily store the normalized file map in the context. */
* ctx - > fmap = fmap ( ofd , 0 , 0 ) ;
2018-12-03 12:40:13 -05:00
if ( ! ( * ctx - > fmap ) ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_scanscript: could not map file %s \n " , tmpname ) ;
2018-12-03 12:40:13 -05:00
} else {
2017-08-08 17:38:17 -04:00
/* scan map */
ret = cli_fmap_scandesc ( ctx , CL_TYPE_TEXT_ASCII , 0 , NULL , AC_SCAN_VIR , NULL , NULL ) ;
2018-12-03 12:40:13 -05:00
if ( ret = = CL_VIRUS ) {
2017-08-08 17:38:17 -04:00
viruses_found + + ;
}
funmap ( * ctx - > fmap ) ;
}
* ctx - > fmap = map ;
2018-12-03 12:40:13 -05:00
} else {
2017-08-08 17:38:17 -04:00
/* Since the above is moderately costly all in all,
* do the old stuff if there ' s no relative offsets . */
2018-12-03 12:40:13 -05:00
if ( troot ) {
2017-08-08 17:38:17 -04:00
cli_targetinfo ( & info , 7 , map ) ;
ret = cli_ac_caloff ( troot , & tmdata , & info ) ;
if ( ret )
goto done ;
}
2005-01-14 14:56:09 +00:00
2018-12-03 12:40:13 -05:00
while ( 1 ) {
2017-08-08 17:38:17 -04:00
size_t len = MIN ( map - > pgsz , map - > len - at ) ;
2018-12-03 12:40:13 -05:00
buff = fmap_need_off_once ( map , at , len ) ;
2017-08-08 17:38:17 -04:00
at + = len ;
2018-12-03 12:40:13 -05:00
if ( ! buff | | ! len | | state . out_pos + len > state . out_len ) {
2017-08-08 17:38:17 -04:00
/* flush if error/EOF, or too little buffer space left */
2018-12-03 12:40:13 -05:00
if ( ( ofd ! = - 1 ) & & ( write ( ofd , state . out , state . out_pos ) = = - 1 ) ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " cli_scanscript: can't write to file %s \n " , tmpname ) ;
close ( ofd ) ;
ofd = - 1 ;
/* we can continue to scan in memory */
}
/* when we flush the buffer also scan */
2018-12-03 12:40:13 -05:00
if ( cli_scanbuff ( state . out , state . out_pos , offset , ctx , CL_TYPE_TEXT_ASCII , mdata ) = = CL_VIRUS ) {
2018-07-20 22:28:48 -04:00
if ( SCAN_ALLMATCHES )
2017-08-08 17:38:17 -04:00
viruses_found + + ;
2018-12-03 12:40:13 -05:00
else {
2017-08-08 17:38:17 -04:00
ret = CL_VIRUS ;
break ;
}
}
if ( ctx - > scanned )
* ctx - > scanned + = state . out_pos / CL_COUNT_PRECISION ;
offset + = state . out_pos ;
/* carry over maxpatlen from previous buffer */
if ( state . out_pos > maxpatlen )
memmove ( state . out , state . out + state . out_pos - maxpatlen , maxpatlen ) ;
text_normalize_reset ( & state ) ;
state . out_pos = maxpatlen ;
}
if ( ! len )
break ;
2018-12-03 12:40:13 -05:00
if ( ! buff | | text_normalize_buffer ( & state , buff , len ) ! = len ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_scanscript: short read during normalizing \n " ) ;
2012-11-27 17:15:02 -05:00
}
}
2005-01-14 14:56:09 +00:00
}
2018-12-03 12:40:13 -05:00
if ( ret ! = CL_VIRUS | | SCAN_ALLMATCHES ) {
2017-08-08 17:38:17 -04:00
if ( ( ret = cli_exp_eval ( ctx , troot , & tmdata , NULL , NULL ) ) = = CL_VIRUS )
viruses_found + + ;
2018-07-20 22:28:48 -04:00
if ( ret ! = CL_VIRUS | | SCAN_ALLMATCHES )
2017-08-08 17:38:17 -04:00
if ( ( ret = cli_exp_eval ( ctx , groot , & gmdata , NULL , NULL ) ) = = CL_VIRUS )
viruses_found + + ;
2008-07-08 11:33:32 +00:00
}
2017-08-08 17:38:17 -04:00
done :
free ( normalized ) ;
cli_ac_freedata ( & tmdata ) ;
cli_ac_freedata ( & gmdata ) ;
if ( ofd ! = - 1 )
close ( ofd ) ;
2018-12-03 12:40:13 -05:00
if ( tmpname ! = NULL ) {
2017-08-08 17:38:17 -04:00
if ( ! ctx - > engine - > keeptmp )
cli_unlink ( tmpname ) ;
free ( tmpname ) ;
2005-01-14 14:56:09 +00:00
}
2017-08-08 17:38:17 -04:00
if ( viruses_found )
return CL_VIRUS ;
2005-01-14 14:56:09 +00:00
return ret ;
}
2009-08-31 06:16:12 +02:00
static int cli_scanhtml_utf16 ( cli_ctx * ctx )
2006-10-25 15:40:47 +00:00
{
2017-08-08 17:38:17 -04:00
char * tempname , * decoded ;
const char * buff ;
2018-12-03 12:40:13 -05:00
int ret = CL_CLEAN , fd , bytes ;
size_t at = 0 ;
2017-08-08 17:38:17 -04:00
fmap_t * map = * ctx - > fmap ;
2006-10-25 15:40:47 +00:00
cli_dbgmsg ( " in cli_scanhtml_utf16() \n " ) ;
2017-08-08 17:38:17 -04:00
if ( ! ( tempname = cli_gentemp ( ctx - > engine - > tmpdir ) ) )
return CL_EMEM ;
2008-03-06 20:19:22 +00:00
2018-12-03 12:40:13 -05:00
if ( ( fd = open ( tempname , O_RDWR | O_CREAT | O_TRUNC | O_BINARY , S_IRWXU ) ) < 0 ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " cli_scanhtml_utf16: Can't create file %s \n " , tempname ) ;
free ( tempname ) ;
return CL_EOPEN ;
2006-10-25 15:40:47 +00:00
}
2008-03-18 22:44:39 +00:00
cli_dbgmsg ( " cli_scanhtml_utf16: using tempfile %s \n " , tempname ) ;
2018-12-03 12:40:13 -05:00
while ( at < map - > len ) {
2017-08-08 17:38:17 -04:00
bytes = MIN ( map - > len - at , map - > pgsz * 16 ) ;
2018-12-03 12:40:13 -05:00
if ( ! ( buff = fmap_need_off_once ( map , at , bytes ) ) ) {
2017-08-08 17:38:17 -04:00
close ( fd ) ;
cli_unlink ( tempname ) ;
free ( tempname ) ;
return CL_EREAD ;
}
at + = bytes ;
decoded = cli_utf16toascii ( buff , bytes ) ;
2018-12-03 12:40:13 -05:00
if ( decoded ) {
if ( write ( fd , decoded , bytes / 2 ) = = - 1 ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " cli_scanhtml_utf16: Can't write to file %s \n " , tempname ) ;
free ( decoded ) ;
close ( fd ) ;
cli_unlink ( tempname ) ;
free ( tempname ) ;
return CL_EWRITE ;
}
free ( decoded ) ;
}
2006-10-25 15:40:47 +00:00
}
2009-08-31 06:16:12 +02:00
* ctx - > fmap = fmap ( fd , 0 , 0 ) ;
2018-12-03 12:40:13 -05:00
if ( * ctx - > fmap ) {
2017-08-08 17:38:17 -04:00
ret = cli_scanhtml ( ctx ) ;
funmap ( * ctx - > fmap ) ;
2018-12-03 12:40:13 -05:00
} else
2017-08-08 17:38:17 -04:00
cli_errmsg ( " cli_scanhtml_utf16: fmap of %s failed \n " , tempname ) ;
2009-08-31 06:16:12 +02:00
* ctx - > fmap = map ;
2006-10-25 15:40:47 +00:00
close ( fd ) ;
2018-12-03 12:40:13 -05:00
if ( ! ctx - > engine - > keeptmp ) {
2017-08-08 17:38:17 -04:00
if ( cli_unlink ( tempname ) )
ret = CL_EUNLINK ;
2018-12-03 12:40:13 -05:00
} else
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_scanhtml_utf16: Decoded HTML data saved in %s \n " , tempname ) ;
2006-10-25 15:40:47 +00:00
free ( tempname ) ;
return ret ;
}
2009-08-31 07:07:32 +02:00
static int cli_scanole2 ( cli_ctx * ctx )
2004-04-20 22:33:42 +00:00
{
2017-08-08 17:38:17 -04:00
char * dir ;
2018-12-03 12:40:13 -05:00
int ret = CL_CLEAN ;
2017-08-08 17:38:17 -04:00
struct uniq * vba = NULL ;
2004-09-07 21:19:02 +00:00
2004-04-20 22:33:42 +00:00
cli_dbgmsg ( " in cli_scanole2() \n " ) ;
2017-08-08 17:38:17 -04:00
if ( ctx - > engine - > maxreclevel & & ctx - > recursion > = ctx - > engine - > maxreclevel )
2008-02-11 13:18:41 +00:00
return CL_EMAXREC ;
2004-04-20 22:33:42 +00:00
/* generate the temporary directory */
2017-08-08 17:38:17 -04:00
if ( ! ( dir = cli_gentemp ( ctx - > engine - > tmpdir ) ) )
return CL_EMEM ;
2008-03-06 20:19:22 +00:00
2018-12-03 12:40:13 -05:00
if ( mkdir ( dir , 0700 ) ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " OLE2: Can't create temporary directory %s \n " , dir ) ;
free ( dir ) ;
return CL_ETMPDIR ;
2004-04-20 22:33:42 +00:00
}
2009-08-31 07:07:32 +02:00
ret = cli_ole2_extract ( dir , ctx , & vba ) ;
2018-12-03 12:40:13 -05:00
if ( ret ! = CL_CLEAN & & ret ! = CL_VIRUS ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " OLE2: %s \n " , cl_strerror ( ret ) ) ;
if ( ! ctx - > engine - > keeptmp )
cli_rmdirs ( dir ) ;
free ( dir ) ;
return ret ;
2004-04-20 22:33:42 +00:00
}
2018-12-03 12:40:13 -05:00
if ( vba ) {
2008-05-27 16:30:47 +00:00
ctx - > recursion + + ;
2008-02-11 13:18:41 +00:00
2017-08-08 17:38:17 -04:00
ret = cli_vba_scandir ( dir , ctx , vba ) ;
uniq_free ( vba ) ;
if ( ret ! = CL_VIRUS )
if ( cli_scandir ( dir , ctx ) = = CL_VIRUS )
ret = CL_VIRUS ;
ctx - > recursion - - ;
2004-04-20 22:33:42 +00:00
}
2017-08-08 17:38:17 -04:00
if ( ! ctx - > engine - > keeptmp )
cli_rmdirs ( dir ) ;
2004-04-20 22:33:42 +00:00
free ( dir ) ;
return ret ;
2003-07-29 15:48:06 +00:00
}
2011-06-13 11:57:59 +03:00
static int cli_scantar ( cli_ctx * ctx , unsigned int posix )
2004-09-07 21:19:02 +00:00
{
2017-08-08 17:38:17 -04:00
char * dir ;
int ret = CL_CLEAN ;
2004-09-07 21:19:02 +00:00
cli_dbgmsg ( " in cli_scantar() \n " ) ;
/* generate temporary directory */
2017-08-08 17:38:17 -04:00
if ( ! ( dir = cli_gentemp ( ctx - > engine - > tmpdir ) ) )
return CL_EMEM ;
2008-03-06 20:19:22 +00:00
2018-12-03 12:40:13 -05:00
if ( mkdir ( dir , 0700 ) ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " Tar: Can't create temporary directory %s \n " , dir ) ;
free ( dir ) ;
return CL_ETMPDIR ;
2004-09-07 21:19:02 +00:00
}
2011-06-13 11:57:59 +03:00
ret = cli_untar ( dir , posix , ctx ) ;
2004-09-07 21:19:02 +00:00
2017-08-08 17:38:17 -04:00
if ( ! ctx - > engine - > keeptmp )
cli_rmdirs ( dir ) ;
2004-09-07 21:19:02 +00:00
free ( dir ) ;
return ret ;
}
2011-06-13 12:03:26 +03:00
static int cli_scanscrenc ( cli_ctx * ctx )
2004-09-13 10:30:14 +00:00
{
2017-08-08 17:38:17 -04:00
char * tempname ;
int ret = CL_CLEAN ;
2004-09-13 10:30:14 +00:00
cli_dbgmsg ( " in cli_scanscrenc() \n " ) ;
2017-08-08 17:38:17 -04:00
if ( ! ( tempname = cli_gentemp ( ctx - > engine - > tmpdir ) ) )
return CL_EMEM ;
2008-03-06 20:19:22 +00:00
2018-12-03 12:40:13 -05:00
if ( mkdir ( tempname , 0700 ) ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " CHM: Can't create temporary directory %s \n " , tempname ) ;
free ( tempname ) ;
return CL_ETMPDIR ;
2004-09-13 10:30:14 +00:00
}
2011-06-13 12:03:26 +03:00
if ( html_screnc_decode ( * ctx - > fmap , tempname ) )
2017-08-08 17:38:17 -04:00
ret = cli_scandir ( tempname , ctx ) ;
2004-09-13 10:30:14 +00:00
2017-08-08 17:38:17 -04:00
if ( ! ctx - > engine - > keeptmp )
cli_rmdirs ( tempname ) ;
2004-09-13 10:30:14 +00:00
free ( tempname ) ;
return ret ;
}
2004-09-18 00:14:00 +00:00
2011-06-15 20:50:42 +02:00
static int cli_scanriff ( cli_ctx * ctx )
2005-02-05 15:50:18 +00:00
{
2017-04-18 12:03:36 -04:00
int ret = CL_CLEAN ;
2005-02-05 15:50:18 +00:00
2017-04-18 12:03:36 -04:00
if ( cli_check_riff_exploit ( ctx ) = = 2 )
2017-08-08 17:38:17 -04:00
ret = cli_append_virus ( ctx , " Heuristics.Exploit.W32.MS05-002 " ) ;
2005-02-05 15:50:18 +00:00
return ret ;
}
2011-06-16 16:30:36 +02:00
static int cli_scanjpeg ( cli_ctx * ctx )
2005-03-19 00:02:47 +00:00
{
2017-04-18 12:03:36 -04:00
int ret = CL_CLEAN ;
2005-03-19 00:02:47 +00:00
2017-08-08 17:38:17 -04:00
if ( cli_check_jpeg_exploit ( ctx , 0 ) = = 1 )
2017-04-18 12:03:36 -04:00
ret = cli_append_virus ( ctx , " Heuristics.Exploit.W32.MS04-028 " ) ;
2005-03-19 00:02:47 +00:00
return ret ;
}
2011-06-13 12:12:01 +03:00
static int cli_scancryptff ( cli_ctx * ctx )
2005-11-14 21:02:26 +00:00
{
2017-08-08 17:38:17 -04:00
int ret = CL_CLEAN , ndesc ;
unsigned int i ;
const unsigned char * src ;
unsigned char * dest = NULL ;
char * tempfile ;
size_t pos ;
size_t bread ;
2005-11-14 21:02:26 +00:00
/* Skip the CryptFF file header */
2011-06-13 12:12:01 +03:00
pos = 0x10 ;
2005-11-14 21:02:26 +00:00
2018-12-03 12:40:13 -05:00
if ( ( dest = ( unsigned char * ) cli_malloc ( FILEBUFF ) ) = = NULL ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " CryptFF: Can't allocate memory \n " ) ;
2005-11-14 21:02:26 +00:00
return CL_EMEM ;
}
2018-12-03 12:40:13 -05:00
if ( ! ( tempfile = cli_gentemp ( ctx - > engine - > tmpdir ) ) ) {
2017-08-08 17:38:17 -04:00
free ( dest ) ;
return CL_EMEM ;
2008-03-06 20:19:22 +00:00
}
2018-12-03 12:40:13 -05:00
if ( ( ndesc = open ( tempfile , O_RDWR | O_CREAT | O_TRUNC | O_BINARY , S_IRWXU ) ) < 0 ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " CryptFF: Can't create file %s \n " , tempfile ) ;
free ( dest ) ;
free ( tempfile ) ;
return CL_ECREAT ;
2005-11-14 21:02:26 +00:00
}
2018-12-03 12:40:13 -05:00
for ( ; ( src = fmap_need_off_once_len ( * ctx - > fmap , pos , FILEBUFF , & bread ) ) & & bread ; pos + = bread ) {
2017-08-08 17:38:17 -04:00
for ( i = 0 ; i < bread ; i + + )
dest [ i ] = src [ i ] ^ ( unsigned char ) 0xff ;
2018-12-03 12:40:13 -05:00
if ( cli_writen ( ndesc , dest , bread ) = = - 1 ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " CryptFF: Can't write to descriptor %d \n " , ndesc ) ;
free ( dest ) ;
close ( ndesc ) ;
free ( tempfile ) ;
return CL_EWRITE ;
}
2005-11-14 21:02:26 +00:00
}
free ( dest ) ;
cli_dbgmsg ( " CryptFF: Scanning decrypted data \n " ) ;
2018-07-30 20:19:28 -04:00
if ( ( ret = cli_magic_scandesc ( ndesc , tempfile , ctx ) ) = = CL_VIRUS )
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " CryptFF: Infected with %s \n " , cli_get_last_virus ( ctx ) ) ;
2005-11-14 21:02:26 +00:00
close ( ndesc ) ;
2017-08-08 17:38:17 -04:00
if ( ctx - > engine - > keeptmp )
cli_dbgmsg ( " CryptFF: Decompressed data saved in %s \n " , tempfile ) ;
else if ( cli_unlink ( tempfile ) )
ret = CL_EUNLINK ;
2005-11-14 21:02:26 +00:00
free ( tempfile ) ;
return ret ;
}
2009-08-31 05:37:43 +02:00
static int cli_scanpdf ( cli_ctx * ctx , off_t offset )
2005-05-03 00:10:46 +00:00
{
2017-08-08 17:38:17 -04:00
int ret ;
char * dir = cli_gentemp ( ctx - > engine - > tmpdir ) ;
2005-05-03 00:10:46 +00:00
2017-08-08 17:38:17 -04:00
if ( ! dir )
return CL_EMEM ;
2005-05-03 00:10:46 +00:00
2018-12-03 12:40:13 -05:00
if ( mkdir ( dir , 0700 ) ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Can't create temporary directory for PDF file %s \n " , dir ) ;
free ( dir ) ;
return CL_ETMPDIR ;
2005-05-03 00:10:46 +00:00
}
2009-08-31 05:37:43 +02:00
ret = cli_pdf ( dir , ctx , offset ) ;
2005-05-03 00:10:46 +00:00
2017-08-08 17:38:17 -04:00
if ( ! ctx - > engine - > keeptmp )
cli_rmdirs ( dir ) ;
2005-05-03 00:10:46 +00:00
free ( dir ) ;
return ret ;
}
2011-06-13 11:47:41 +03:00
static int cli_scantnef ( cli_ctx * ctx )
2005-03-25 15:17:13 +00:00
{
2017-08-08 17:38:17 -04:00
int ret ;
char * dir = cli_gentemp ( ctx - > engine - > tmpdir ) ;
2005-03-25 15:17:13 +00:00
2017-08-08 17:38:17 -04:00
if ( ! dir )
return CL_EMEM ;
2005-03-25 15:17:13 +00:00
2018-12-03 12:40:13 -05:00
if ( mkdir ( dir , 0700 ) ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Can't create temporary directory for tnef file %s \n " , dir ) ;
free ( dir ) ;
return CL_ETMPDIR ;
2005-03-25 15:17:13 +00:00
}
2011-06-13 11:47:41 +03:00
ret = cli_tnef ( dir , ctx ) ;
2005-03-25 15:17:13 +00:00
2017-08-08 17:38:17 -04:00
if ( ret = = CL_CLEAN )
ret = cli_scandir ( dir , ctx ) ;
2005-03-25 15:17:13 +00:00
2017-08-08 17:38:17 -04:00
if ( ! ctx - > engine - > keeptmp )
cli_rmdirs ( dir ) ;
2005-03-25 15:17:13 +00:00
free ( dir ) ;
return ret ;
}
2009-09-10 03:19:43 +02:00
static int cli_scanuuencoded ( cli_ctx * ctx )
2006-01-21 18:37:48 +00:00
{
2017-08-08 17:38:17 -04:00
int ret ;
char * dir = cli_gentemp ( ctx - > engine - > tmpdir ) ;
2006-01-21 18:37:48 +00:00
2017-08-08 17:38:17 -04:00
if ( ! dir )
return CL_EMEM ;
2008-03-06 20:19:22 +00:00
2018-12-03 12:40:13 -05:00
if ( mkdir ( dir , 0700 ) ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Can't create temporary directory for uuencoded file %s \n " , dir ) ;
free ( dir ) ;
return CL_ETMPDIR ;
2006-01-21 18:37:48 +00:00
}
2009-09-10 03:19:43 +02:00
ret = cli_uuencode ( dir , * ctx - > fmap ) ;
2006-01-21 18:37:48 +00:00
2017-08-08 17:38:17 -04:00
if ( ret = = CL_CLEAN )
ret = cli_scandir ( dir , ctx ) ;
2006-01-21 18:37:48 +00:00
2017-08-08 17:38:17 -04:00
if ( ! ctx - > engine - > keeptmp )
cli_rmdirs ( dir ) ;
2006-01-21 18:37:48 +00:00
free ( dir ) ;
return ret ;
}
2011-06-10 20:17:19 +03:00
static int cli_scanmail ( cli_ctx * ctx )
2003-07-29 15:48:06 +00:00
{
2017-08-08 17:38:17 -04:00
char * dir ;
int ret ;
unsigned int viruses_found = 0 ;
2003-07-29 15:48:06 +00:00
2008-02-06 21:19:10 +00:00
cli_dbgmsg ( " Starting cli_scanmail(), recursion = %u \n " , ctx - > recursion ) ;
2003-07-29 15:48:06 +00:00
2004-11-16 17:10:47 +00:00
/* generate the temporary directory */
2017-08-08 17:38:17 -04:00
if ( ! ( dir = cli_gentemp ( ctx - > engine - > tmpdir ) ) )
return CL_EMEM ;
2008-03-06 20:19:22 +00:00
2018-12-03 12:40:13 -05:00
if ( mkdir ( dir , 0700 ) ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Mail: Can't create temporary directory %s \n " , dir ) ;
free ( dir ) ;
return CL_ETMPDIR ;
2004-11-16 17:10:47 +00:00
}
2003-07-29 15:48:06 +00:00
2004-11-16 17:10:47 +00:00
/*
* Extract the attachments into the temporary directory
*/
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_mbox ( dir , ctx ) ) ) {
2018-07-20 22:28:48 -04:00
if ( ret = = CL_VIRUS & & SCAN_ALLMATCHES )
2017-08-08 17:38:17 -04:00
viruses_found + + ;
2018-12-03 12:40:13 -05:00
else {
2017-08-08 17:38:17 -04:00
if ( ! ctx - > engine - > keeptmp )
cli_rmdirs ( dir ) ;
free ( dir ) ;
return ret ;
}
2004-11-16 17:10:47 +00:00
}
2009-08-30 19:46:26 +02:00
ret = cli_scandir ( dir , ctx ) ;
2004-11-16 17:10:47 +00:00
2017-08-08 17:38:17 -04:00
if ( ! ctx - > engine - > keeptmp )
cli_rmdirs ( dir ) ;
2004-11-16 17:10:47 +00:00
free ( dir ) ;
2016-06-08 16:25:34 -04:00
if ( viruses_found )
2017-08-08 17:38:17 -04:00
return CL_VIRUS ;
2004-11-16 17:10:47 +00:00
return ret ;
2003-07-29 15:48:06 +00:00
}
2011-06-13 15:54:44 +03:00
static int cli_scan_structured ( cli_ctx * ctx )
2008-04-16 18:47:42 +00:00
{
2017-08-08 17:38:17 -04:00
char buf [ 8192 ] ;
2018-12-03 12:40:13 -05:00
int result = 0 ;
unsigned int cc_count = 0 ;
2017-08-08 17:38:17 -04:00
unsigned int ssn_count = 0 ;
2018-12-03 12:40:13 -05:00
int done = 0 ;
2017-08-08 17:38:17 -04:00
fmap_t * map ;
size_t pos = 0 ;
int ( * ccfunc ) ( const unsigned char * buffer , int length ) ;
int ( * ssnfunc ) ( const unsigned char * buffer , int length ) ;
unsigned int viruses_found = 0 ;
if ( ctx = = NULL )
return CL_ENULLARG ;
2008-04-16 18:47:42 +00:00
2012-07-23 14:43:36 -04:00
map = * ctx - > fmap ;
2012-07-12 10:21:00 -04:00
2017-08-08 17:38:17 -04:00
if ( ctx - > engine - > min_cc_count = = 1 )
ccfunc = dlp_has_cc ;
2008-04-16 18:47:42 +00:00
else
2017-08-08 17:38:17 -04:00
ccfunc = dlp_get_cc_count ;
2008-04-16 18:47:42 +00:00
2018-12-03 12:40:13 -05:00
switch ( SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL | SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED ) {
case ( CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL | CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED ) :
if ( ctx - > engine - > min_ssn_count = = 1 )
ssnfunc = dlp_has_ssn ;
else
ssnfunc = dlp_get_ssn_count ;
break ;
2008-04-16 18:47:42 +00:00
2018-12-03 12:40:13 -05:00
case CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL :
if ( ctx - > engine - > min_ssn_count = = 1 )
ssnfunc = dlp_has_normal_ssn ;
else
ssnfunc = dlp_get_normal_ssn_count ;
break ;
2008-04-16 18:47:42 +00:00
2018-12-03 12:40:13 -05:00
case CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED :
if ( ctx - > engine - > min_ssn_count = = 1 )
ssnfunc = dlp_has_stripped_ssn ;
else
ssnfunc = dlp_get_stripped_ssn_count ;
break ;
2008-04-18 17:14:20 +00:00
2018-12-03 12:40:13 -05:00
default :
ssnfunc = NULL ;
2008-04-16 18:47:42 +00:00
}
2018-12-03 12:40:13 -05:00
while ( ! done & & ( ( result = fmap_readn ( map , buf , pos , 8191 ) ) > 0 ) ) {
2017-08-08 17:38:17 -04:00
pos + = result ;
2018-12-03 12:40:13 -05:00
if ( ( cc_count + = ccfunc ( ( const unsigned char * ) buf , result ) ) > = ctx - > engine - > min_cc_count ) {
2017-08-08 17:38:17 -04:00
done = 1 ;
}
2008-04-18 17:14:20 +00:00
2018-12-03 12:40:13 -05:00
if ( ssnfunc & & ( ( ssn_count + = ssnfunc ( ( const unsigned char * ) buf , result ) ) > = ctx - > engine - > min_ssn_count ) ) {
2017-08-08 17:38:17 -04:00
done = 1 ;
}
2008-04-16 18:47:42 +00:00
}
2018-12-03 12:40:13 -05:00
if ( cc_count ! = 0 & & cc_count > = ctx - > engine - > min_cc_count ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_scan_structured: %u credit card numbers detected \n " , cc_count ) ;
2018-12-03 12:40:13 -05:00
if ( CL_VIRUS = = cli_append_virus ( ctx , " Heuristics.Structured.CreditCardNumber " ) ) {
if ( SCAN_ALLMATCHES ) {
2017-04-18 12:03:36 -04:00
viruses_found + + ;
2018-12-03 12:40:13 -05:00
} else {
2017-04-18 12:03:36 -04:00
return CL_VIRUS ;
2017-08-08 17:38:17 -04:00
}
}
2008-04-16 18:47:42 +00:00
}
2018-12-03 12:40:13 -05:00
if ( ssn_count ! = 0 & & ssn_count > = ctx - > engine - > min_ssn_count ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_scan_structured: %u social security numbers detected \n " , ssn_count ) ;
2018-12-03 12:40:13 -05:00
if ( CL_VIRUS = = cli_append_virus ( ctx , " Heuristics.Structured.SSN " ) ) {
if ( SCAN_ALLMATCHES ) {
2017-04-18 12:03:36 -04:00
viruses_found + + ;
2018-12-03 12:40:13 -05:00
} else {
2017-04-18 12:03:36 -04:00
return CL_VIRUS ;
2017-08-08 17:38:17 -04:00
}
}
2008-04-16 18:47:42 +00:00
}
2016-06-08 16:25:34 -04:00
if ( viruses_found )
2017-08-08 17:38:17 -04:00
return CL_VIRUS ;
2008-04-16 18:47:42 +00:00
return CL_CLEAN ;
}
2010-07-29 03:55:24 +02:00
static int cli_scanembpe ( cli_ctx * ctx , off_t offset )
2007-03-12 21:31:40 +00:00
{
2017-08-08 17:38:17 -04:00
int fd , bytes , ret = CL_CLEAN ;
unsigned long int size = 0 , todo ;
const char * buff ;
char * tmpname ;
fmap_t * map = * ctx - > fmap ;
unsigned int corrupted_input ;
2007-03-12 21:31:40 +00:00
2008-11-14 22:23:39 +00:00
tmpname = cli_gentemp ( ctx - > engine - > tmpdir ) ;
2017-08-08 17:38:17 -04:00
if ( ! tmpname )
return CL_EMEM ;
2007-03-12 21:31:40 +00:00
2018-12-03 12:40:13 -05:00
if ( ( fd = open ( tmpname , O_RDWR | O_CREAT | O_TRUNC | O_BINARY , S_IRWXU ) ) < 0 ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " cli_scanembpe: Can't create file %s \n " , tmpname ) ;
free ( tmpname ) ;
return CL_ECREAT ;
2007-03-12 21:31:40 +00:00
}
2010-07-29 03:55:24 +02:00
todo = map - > len - offset ;
2018-12-03 12:40:13 -05:00
while ( 1 ) {
2017-08-08 17:38:17 -04:00
bytes = MIN ( todo , map - > pgsz ) ;
if ( ! bytes )
break ;
2018-12-03 12:40:13 -05:00
if ( ! ( buff = fmap_need_off_once ( map , offset + size , bytes ) ) ) {
2017-08-08 17:38:17 -04:00
close ( fd ) ;
2018-12-03 12:40:13 -05:00
if ( ! ctx - > engine - > keeptmp ) {
if ( cli_unlink ( tmpname ) ) {
2017-08-08 17:38:17 -04:00
free ( tmpname ) ;
return CL_EUNLINK ;
}
}
free ( tmpname ) ;
return CL_EREAD ;
}
size + = bytes ;
todo - = bytes ;
if ( cli_checklimits ( " cli_scanembpe " , ctx , size , 0 , 0 ) ! = CL_CLEAN )
break ;
2018-12-03 12:40:13 -05:00
if ( cli_writen ( fd , buff , bytes ) ! = bytes ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_scanembpe: Can't write to temporary file \n " ) ;
close ( fd ) ;
2018-12-03 12:40:13 -05:00
if ( ! ctx - > engine - > keeptmp ) {
if ( cli_unlink ( tmpname ) ) {
2017-08-08 17:38:17 -04:00
free ( tmpname ) ;
return CL_EUNLINK ;
}
}
free ( tmpname ) ;
return CL_EWRITE ;
}
2007-03-12 21:31:40 +00:00
}
2008-02-13 10:34:58 +00:00
ctx - > recursion + + ;
2018-12-03 12:40:13 -05:00
corrupted_input = ctx - > corrupted_input ;
2010-10-18 13:23:51 +02:00
ctx - > corrupted_input = 1 ;
2018-12-03 12:40:13 -05:00
ret = cli_magic_scandesc ( fd , tmpname , ctx ) ;
2010-10-18 13:23:51 +02:00
ctx - > corrupted_input = corrupted_input ;
2018-12-03 12:40:13 -05:00
if ( ret = = CL_VIRUS ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_scanembpe: Infected with %s \n " , cli_get_last_virus ( ctx ) ) ;
close ( fd ) ;
2018-12-03 12:40:13 -05:00
if ( ! ctx - > engine - > keeptmp ) {
if ( cli_unlink ( tmpname ) ) {
2017-08-08 17:38:17 -04:00
free ( tmpname ) ;
return CL_EUNLINK ;
}
}
free ( tmpname ) ;
return CL_VIRUS ;
2007-03-12 21:31:40 +00:00
}
2008-02-13 10:34:58 +00:00
ctx - > recursion - - ;
2007-03-12 21:31:40 +00:00
close ( fd ) ;
2018-12-03 12:40:13 -05:00
if ( ! ctx - > engine - > keeptmp ) {
if ( cli_unlink ( tmpname ) ) {
2017-08-08 17:38:17 -04:00
free ( tmpname ) ;
return CL_EUNLINK ;
}
2008-04-08 17:45:05 +00:00
}
2007-03-12 21:31:40 +00:00
free ( tmpname ) ;
/* intentionally ignore possible errors from cli_magic_scandesc */
return CL_CLEAN ;
}
2018-10-19 20:43:19 -07:00
# if defined(_WIN32) || defined(C_LINUX) || defined(C_DARWIN)
2011-02-14 19:19:20 +02:00
# define PERF_MEASURE
# endif
# ifdef PERF_MEASURE
2017-08-08 17:38:17 -04:00
static struct
{
2011-02-14 19:19:20 +02:00
enum perfev id ;
const char * name ;
enum ev_type type ;
} perf_events [ ] = {
{ PERFT_SCAN , " full scan " , ev_time } ,
{ PERFT_PRECB , " prescan cb " , ev_time } ,
{ PERFT_POSTCB , " postscan cb " , ev_time } ,
{ PERFT_CACHE , " cache " , ev_time } ,
{ PERFT_FT , " filetype " , ev_time } ,
{ PERFT_CONTAINER , " container " , ev_time } ,
{ PERFT_SCRIPT , " script " , ev_time } ,
{ PERFT_PE , " pe " , ev_time } ,
{ PERFT_RAW , " raw " , ev_time } ,
{ PERFT_RAWTYPENO , " raw container " , ev_time } ,
{ PERFT_MAP , " map " , ev_time } ,
2017-08-08 17:38:17 -04:00
{ PERFT_BYTECODE , " bytecode " , ev_time } ,
{ PERFT_KTIME , " kernel " , ev_int } ,
{ PERFT_UTIME , " user " , ev_int } } ;
2011-02-14 19:19:20 +02:00
static void get_thread_times ( uint64_t * kt , uint64_t * ut )
{
# ifdef _WIN32
2017-08-08 17:38:17 -04:00
FILETIME c , e , k , u ;
ULARGE_INTEGER kl , ul ;
2018-12-03 12:40:13 -05:00
if ( ! GetThreadTimes ( GetCurrentThread ( ) , & c , & e , & k , & u ) ) {
2017-08-08 17:38:17 -04:00
* kt = * ut = 0 ;
return ;
2011-02-14 19:19:20 +02:00
}
2018-12-03 12:40:13 -05:00
kl . LowPart = k . dwLowDateTime ;
2011-02-14 19:19:20 +02:00
kl . HighPart = k . dwHighDateTime ;
2018-12-03 12:40:13 -05:00
ul . LowPart = u . dwLowDateTime ;
2011-02-14 19:19:20 +02:00
ul . HighPart = u . dwHighDateTime ;
2018-12-03 12:40:13 -05:00
* kt = kl . QuadPart / 10 ;
* ut = ul . QuadPart / 10 ;
2011-02-14 19:19:20 +02:00
# else
struct tms tbuf ;
2018-12-03 12:40:13 -05:00
if ( times ( & tbuf ) ! = - 1 ) {
2017-08-08 17:38:17 -04:00
clock_t tck = sysconf ( _SC_CLK_TCK ) ;
2018-12-03 12:40:13 -05:00
* kt = ( ( uint64_t ) 1000000 ) * tbuf . tms_stime / tck ;
* ut = ( ( uint64_t ) 1000000 ) * tbuf . tms_utime / tck ;
} else {
2017-08-08 17:38:17 -04:00
* kt = * ut = 0 ;
2011-02-14 19:19:20 +02:00
}
# endif
}
static inline void perf_init ( cli_ctx * ctx )
{
2017-08-08 17:38:17 -04:00
uint64_t kt , ut ;
2011-02-14 19:19:20 +02:00
unsigned i ;
2018-07-20 22:28:48 -04:00
if ( ! SCAN_DEV_COLLECT_PERF_INFO )
2017-08-08 17:38:17 -04:00
return ;
2011-02-14 19:19:20 +02:00
ctx - > perf = cli_events_new ( PERFT_LAST ) ;
2018-12-03 12:40:13 -05:00
for ( i = 0 ; i < sizeof ( perf_events ) / sizeof ( perf_events [ 0 ] ) ; i + + ) {
2017-08-08 17:38:17 -04:00
if ( cli_event_define ( ctx - > perf , perf_events [ i ] . id , perf_events [ i ] . name ,
perf_events [ i ] . type , multiple_sum ) = = - 1 )
continue ;
2011-02-14 19:19:20 +02:00
}
cli_event_time_start ( ctx - > perf , PERFT_SCAN ) ;
get_thread_times ( & kt , & ut ) ;
cli_event_int ( ctx - > perf , PERFT_KTIME , - kt ) ;
cli_event_int ( ctx - > perf , PERFT_UTIME , - ut ) ;
}
2017-08-08 17:38:17 -04:00
static inline void perf_done ( cli_ctx * ctx )
2011-02-14 19:19:20 +02:00
{
char timestr [ 512 ] ;
char * p ;
unsigned i ;
2017-08-08 17:38:17 -04:00
uint64_t kt , ut ;
2011-02-14 19:25:22 +02:00
char * pend ;
2011-02-14 19:19:20 +02:00
cli_events_t * perf = ctx - > perf ;
if ( ! perf )
2017-08-08 17:38:17 -04:00
return ;
2011-02-14 19:19:20 +02:00
2018-12-03 12:40:13 -05:00
p = timestr ;
pend = timestr + sizeof ( timestr ) - 1 ;
2011-02-14 19:19:20 +02:00
* pend = 0 ;
cli_event_time_stop ( perf , PERFT_SCAN ) ;
get_thread_times ( & kt , & ut ) ;
cli_event_int ( perf , PERFT_KTIME , kt ) ;
cli_event_int ( perf , PERFT_UTIME , ut ) ;
2018-12-03 12:40:13 -05:00
for ( i = 0 ; i < sizeof ( perf_events ) / sizeof ( perf_events [ 0 ] ) ; i + + ) {
2017-08-08 17:38:17 -04:00
union ev_val val ;
unsigned count ;
2011-02-14 19:19:20 +02:00
2017-08-08 17:38:17 -04:00
cli_event_get ( perf , perf_events [ i ] . id , & val , & count ) ;
if ( p < pend )
p + = snprintf ( p , pend - p , " %s: %d.%03ums, " , perf_events [ i ] . name ,
( signed ) ( val . v_int / 1000 ) ,
( unsigned ) ( val . v_int % 1000 ) ) ;
2011-02-14 19:19:20 +02:00
}
* p = 0 ;
cli_infomsg ( ctx , " performance: %s \n " , timestr ) ;
cli_events_free ( perf ) ;
ctx - > perf = NULL ;
}
2017-08-08 17:38:17 -04:00
static inline void perf_start ( cli_ctx * ctx , int id )
2011-02-14 19:19:20 +02:00
{
cli_event_time_start ( ctx - > perf , id ) ;
}
2017-08-08 17:38:17 -04:00
static inline void perf_stop ( cli_ctx * ctx , int id )
2011-02-14 19:19:20 +02:00
{
cli_event_time_stop ( ctx - > perf , id ) ;
}
2017-08-08 17:38:17 -04:00
static inline void perf_nested_start ( cli_ctx * ctx , int id , int nestedid )
2011-02-14 19:19:20 +02:00
{
cli_event_time_nested_start ( ctx - > perf , id , nestedid ) ;
}
2017-08-08 17:38:17 -04:00
static inline void perf_nested_stop ( cli_ctx * ctx , int id , int nestedid )
2011-02-14 19:19:20 +02:00
{
cli_event_time_nested_stop ( ctx - > perf , id , nestedid ) ;
}
# else
2017-08-08 17:38:17 -04:00
static inline void perf_init ( cli_ctx * ctx )
{
UNUSEDPARAM ( ctx ) ;
}
static inline void perf_start ( cli_ctx * ctx , int id )
{
UNUSEDPARAM ( ctx ) ;
UNUSEDPARAM ( id ) ;
}
static inline void perf_stop ( cli_ctx * ctx , int id )
{
UNUSEDPARAM ( ctx ) ;
UNUSEDPARAM ( id ) ;
}
static inline void perf_nested_start ( cli_ctx * ctx , int id , int nestedid )
{
UNUSEDPARAM ( ctx ) ;
UNUSEDPARAM ( id ) ;
UNUSEDPARAM ( nestedid ) ;
}
static inline void perf_nested_stop ( cli_ctx * ctx , int id , int nestedid )
{
UNUSEDPARAM ( ctx ) ;
UNUSEDPARAM ( id ) ;
UNUSEDPARAM ( nestedid ) ;
}
2018-12-03 12:40:13 -05:00
static inline void perf_done ( cli_ctx * ctx )
{
UNUSEDPARAM ( ctx ) ;
}
2011-02-14 19:19:20 +02:00
# endif
2010-03-04 19:52:33 +01:00
static int cli_scanraw ( cli_ctx * ctx , cli_file_t type , uint8_t typercg , cli_file_t * dettype , unsigned char * refhash )
2006-01-25 12:11:31 +00:00
{
2017-08-08 17:38:17 -04:00
int ret = CL_CLEAN , nret = CL_CLEAN ;
struct cli_matched_type * ftoffset = NULL , * fpt ;
uint32_t lastrar ;
struct cli_exe_info peinfo ;
unsigned int acmode = AC_SCAN_VIR , break_loop = 0 ;
fmap_t * map = * ctx - > fmap ;
2006-01-25 12:11:31 +00:00
2018-12-03 12:40:13 -05:00
if ( ctx - > engine - > maxreclevel & & ctx - > recursion > = ctx - > engine - > maxreclevel ) {
2016-08-24 17:39:20 -04:00
cli_check_blockmax ( ctx , CL_EMAXREC ) ;
2009-06-10 20:50:49 +00:00
return CL_EMAXREC ;
2016-08-24 17:39:20 -04:00
}
2009-06-10 20:50:49 +00:00
2011-02-14 19:19:20 +02:00
perf_start ( ctx , PERFT_RAW ) ;
2017-08-08 17:38:17 -04:00
if ( typercg )
acmode | = AC_SCAN_FT ;
2006-01-25 12:11:31 +00:00
2010-06-10 12:24:26 +02:00
ret = cli_fmap_scandesc ( ctx , type = = CL_TYPE_TEXT_ASCII ? 0 : type , 0 , & ftoffset , acmode , NULL , refhash ) ;
2011-02-14 19:19:20 +02:00
perf_stop ( ctx , PERFT_RAW ) ;
2006-01-25 12:11:31 +00:00
2018-12-03 12:40:13 -05:00
if ( ret > = CL_TYPENO ) {
2017-08-08 17:38:17 -04:00
perf_nested_start ( ctx , PERFT_RAWTYPENO , PERFT_SCAN ) ;
ctx - > recursion + + ;
2013-10-23 16:21:46 -04:00
fpt = ftoffset ;
2018-12-03 12:40:13 -05:00
while ( fpt ) {
2017-01-19 12:24:46 -05:00
/* set current level as container AFTER recursing */
cli_set_container ( ctx , fpt - > type , map - > len ) ;
2017-08-08 17:38:17 -04:00
if ( fpt - > offset )
2018-12-03 12:40:13 -05:00
switch ( fpt - > type ) {
case CL_TYPE_MHTML :
if ( SCAN_PARSE_MAIL & & ( DCONF_MAIL & MAIL_CONF_MBOX ) ) {
cli_dbgmsg ( " MHTML signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = ret = cli_scanmail ( ctx ) ;
}
break ;
2016-05-02 17:32:03 -04:00
2018-12-03 12:40:13 -05:00
case CL_TYPE_XDP :
if ( SCAN_PARSE_PDF & & ( DCONF_DOC & DOC_CONF_PDF ) ) {
cli_dbgmsg ( " XDP signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = ret = cli_scanxdp ( ctx ) ;
}
break ;
case CL_TYPE_XML_WORD :
if ( SCAN_PARSE_XMLDOCS & & ( DCONF_DOC & DOC_CONF_MSXML ) ) {
cli_dbgmsg ( " XML-WORD signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = ret = cli_scanmsxml ( ctx ) ;
}
break ;
case CL_TYPE_XML_XL :
if ( SCAN_PARSE_XMLDOCS & & ( DCONF_DOC & DOC_CONF_MSXML ) ) {
cli_dbgmsg ( " XML-XL signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = ret = cli_scanmsxml ( ctx ) ;
}
break ;
case CL_TYPE_XML_HWP :
if ( SCAN_PARSE_XMLDOCS & & ( DCONF_DOC & DOC_CONF_HWP ) ) {
cli_dbgmsg ( " XML-HWP signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = ret = cli_scanhwpml ( ctx ) ;
}
break ;
case CL_TYPE_RARSFX :
if ( type ! = CL_TYPE_RAR & & have_rar & & SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_RAR ) ) {
const char * filepath = NULL ;
int fd = - 1 ;
2018-07-30 20:19:28 -04:00
2018-12-03 12:40:13 -05:00
char * tmpname = NULL ;
int tmpfd = - 1 ;
size_t csize = map - > len - fpt - > offset ; /* not precise */
2018-07-30 20:19:28 -04:00
2018-12-03 12:40:13 -05:00
cli_set_container ( ctx , CL_TYPE_RAR , csize ) ;
cli_dbgmsg ( " RAR/RAR-SFX signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
2018-07-30 20:19:28 -04:00
2018-12-03 12:40:13 -05:00
if ( ( ctx - > sub_filepath = = NULL ) | | ( fpt - > offset ! = 0 ) ) {
/*
2018-07-30 20:19:28 -04:00
* If map is not file - backed , or offset is not at the start of the file . . .
* . . . have to dump to file for scanrar .
*/
2018-12-03 12:40:13 -05:00
nret = fmap_dump_to_file ( map , ctx - > sub_filepath , ctx - > engine - > tmpdir , & tmpname , & tmpfd , fpt - > offset , fpt - > offset + csize ) ;
if ( nret ! = CL_SUCCESS ) {
cli_dbgmsg ( " cli_scanraw: failed to generate temporary file. \n " ) ;
ret = nret ;
break_loop = 1 ;
break ;
}
filepath = tmpname ;
fd = tmpfd ;
} else {
/* Use the original file and file descriptor. */
filepath = ctx - > sub_filepath ;
fd = fmap_fd ( map ) ;
2013-11-22 19:41:46 -05:00
}
2018-07-30 20:19:28 -04:00
2018-12-03 12:40:13 -05:00
/* scan file */
nret = cli_scanrar ( filepath , fd , ctx ) ;
2018-07-30 20:19:28 -04:00
2018-12-03 12:40:13 -05:00
if ( tmpfd ! = - 1 ) {
/* If dumped tempfile, need to cleanup */
close ( tmpfd ) ;
if ( ! ctx - > engine - > keeptmp ) {
if ( cli_unlink ( tmpname ) ) {
ret = nret = CL_EUNLINK ;
break_loop = 1 ;
}
2013-11-22 19:41:46 -05:00
}
}
2018-07-30 20:19:28 -04:00
2018-12-03 12:40:13 -05:00
if ( tmpname ! = NULL ) {
free ( tmpname ) ;
}
2013-11-22 19:41:46 -05:00
}
2018-12-03 12:40:13 -05:00
break ;
2013-10-23 16:21:46 -04:00
2018-12-03 12:40:13 -05:00
case CL_TYPE_ZIPSFX :
if ( type ! = CL_TYPE_ZIP & & SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_ZIP ) ) {
size_t csize = map - > len - fpt - > offset ; /* not precise */
cli_set_container ( ctx , CL_TYPE_ZIP , csize ) ;
cli_dbgmsg ( " ZIP/ZIP-SFX signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = cli_unzip_single ( ctx , fpt - > offset ) ;
}
break ;
2013-10-23 16:21:46 -04:00
2018-12-03 12:40:13 -05:00
case CL_TYPE_CABSFX :
if ( type ! = CL_TYPE_MSCAB & & SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_CAB ) ) {
size_t csize = map - > len - fpt - > offset ; /* not precise */
cli_set_container ( ctx , CL_TYPE_MSCAB , csize ) ;
cli_dbgmsg ( " CAB/CAB-SFX signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = cli_scanmscab ( ctx , fpt - > offset ) ;
}
break ;
2013-10-23 16:21:46 -04:00
2018-12-03 12:40:13 -05:00
case CL_TYPE_ARJSFX :
if ( type ! = CL_TYPE_ARJ & & SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_ARJ ) ) {
size_t csize = map - > len - fpt - > offset ; /* not precise */
cli_set_container ( ctx , CL_TYPE_ARJ , csize ) ;
cli_dbgmsg ( " ARJ-SFX signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = cli_scanarj ( ctx , fpt - > offset ) ;
}
break ;
2013-10-23 16:21:46 -04:00
2018-12-03 12:40:13 -05:00
case CL_TYPE_7ZSFX :
if ( type ! = CL_TYPE_7Z & & SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_7Z ) ) {
size_t csize = map - > len - fpt - > offset ; /* not precise */
cli_set_container ( ctx , CL_TYPE_7Z , csize ) ;
cli_dbgmsg ( " 7Zip-SFX signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = cli_7unz ( ctx , fpt - > offset ) ;
}
break ;
2013-10-23 16:21:46 -04:00
2018-12-03 12:40:13 -05:00
case CL_TYPE_ISO9660 :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_ISO9660 ) ) {
size_t csize = map - > len - fpt - > offset ; /* not precise */
cli_set_container ( ctx , CL_TYPE_ISO9660 , csize ) ;
cli_dbgmsg ( " ISO9660 signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = cli_scaniso ( ctx , fpt - > offset ) ;
}
break ;
2013-10-23 16:21:46 -04:00
2018-12-03 12:40:13 -05:00
case CL_TYPE_NULSFT :
if ( SCAN_PARSE_ARCHIVE & & type = = CL_TYPE_MSEXE & & ( DCONF_ARCH & ARCH_CONF_NSIS ) & &
fpt - > offset > 4 ) {
size_t csize = map - > len - fpt - > offset ; /* not precise */
cli_set_container ( ctx , CL_TYPE_NULSFT , csize ) ;
cli_dbgmsg ( " NSIS signature found at %u \n " , ( unsigned int ) fpt - > offset - 4 ) ;
nret = cli_scannulsft ( ctx , fpt - > offset - 4 ) ;
}
break ;
2013-10-23 16:21:46 -04:00
2018-12-03 12:40:13 -05:00
case CL_TYPE_AUTOIT :
if ( SCAN_PARSE_ARCHIVE & & type = = CL_TYPE_MSEXE & & ( DCONF_ARCH & ARCH_CONF_AUTOIT ) ) {
size_t csize = map - > len - fpt - > offset ; /* not precise */
cli_set_container ( ctx , CL_TYPE_AUTOIT , csize ) ;
cli_dbgmsg ( " AUTOIT signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = cli_scanautoit ( ctx , fpt - > offset + 23 ) ;
}
break ;
2013-10-23 16:21:46 -04:00
2018-12-03 12:40:13 -05:00
case CL_TYPE_ISHIELD_MSI :
if ( SCAN_PARSE_ARCHIVE & & type = = CL_TYPE_MSEXE & & ( DCONF_ARCH & ARCH_CONF_ISHIELD ) ) {
size_t csize = map - > len - fpt - > offset ; /* not precise */
cli_set_container ( ctx , CL_TYPE_AUTOIT , csize ) ;
cli_dbgmsg ( " ISHIELD-MSI signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = cli_scanishield_msi ( ctx , fpt - > offset + 14 ) ;
2014-03-13 15:25:33 -04:00
}
2018-12-03 12:40:13 -05:00
break ;
case CL_TYPE_DMG :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_DMG ) ) {
cli_dbgmsg ( " DMG signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = cli_scandmg ( ctx ) ;
2014-03-13 15:25:33 -04:00
}
2018-12-03 12:40:13 -05:00
break ;
2014-03-13 15:25:33 -04:00
2018-12-03 12:40:13 -05:00
case CL_TYPE_MBR :
if ( SCAN_PARSE_ARCHIVE ) {
int iret = cli_mbr_check2 ( ctx , 0 ) ;
if ( ( iret = = CL_TYPE_GPT ) & & ( DCONF_ARCH & ARCH_CONF_GPT ) ) {
cli_dbgmsg ( " Recognized GUID Partition Table file \n " ) ;
cli_set_container ( ctx , CL_TYPE_GPT , map - > len ) ;
cli_dbgmsg ( " GPT signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = cli_scangpt ( ctx , 0 ) ;
} else if ( ( iret = = CL_CLEAN ) & & ( DCONF_ARCH & ARCH_CONF_MBR ) ) {
cli_dbgmsg ( " MBR signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = cli_scanmbr ( ctx , 0 ) ;
}
}
break ;
2013-10-23 16:21:46 -04:00
2018-12-03 12:40:13 -05:00
case CL_TYPE_PDF :
if ( type ! = CL_TYPE_PDF & & SCAN_PARSE_PDF & & ( DCONF_DOC & DOC_CONF_PDF ) ) {
size_t csize = map - > len - fpt - > offset ; /* not precise */
cli_set_container ( ctx , CL_TYPE_PDF , csize ) ;
cli_dbgmsg ( " PDF signature found at %u \n " , ( unsigned int ) fpt - > offset ) ;
nret = cli_scanpdf ( ctx , fpt - > offset ) ;
2013-10-23 16:21:46 -04:00
}
2018-12-03 12:40:13 -05:00
break ;
case CL_TYPE_MSEXE :
if ( SCAN_PARSE_PE & & ( type = = CL_TYPE_MSEXE | | type = = CL_TYPE_ZIP | | type = = CL_TYPE_MSOLE2 ) & & ctx - > dconf - > pe ) {
uint64_t curr_len = map - > len ;
size_t csize = map - > len - fpt - > offset ; /* not precise */
/* CL_ENGINE_MAX_EMBEDDED_PE */
if ( curr_len > ctx - > engine - > maxembeddedpe ) {
cli_dbgmsg ( " cli_scanraw: MaxEmbeddedPE exceeded \n " ) ;
break ;
}
cli_set_container ( ctx , CL_TYPE_MSEXE , csize ) ;
memset ( & peinfo , 0 , sizeof ( struct cli_exe_info ) ) ;
peinfo . offset = fpt - > offset ;
if ( cli_peheader ( map , & peinfo ) = = 0 ) {
cli_dbgmsg ( " *** Detected embedded PE file at %u *** \n " ,
( unsigned int ) fpt - > offset ) ;
if ( peinfo . section )
free ( peinfo . section ) ;
cli_hashset_destroy ( & peinfo . vinfo ) ;
nret = cli_scanembpe ( ctx , fpt - > offset ) ;
break_loop = 1 ; /* we can stop here and other
2013-10-23 16:21:46 -04:00
* embedded executables will
* be found recursively
* through the above call
*/
2018-12-03 12:40:13 -05:00
}
2013-10-23 16:21:46 -04:00
}
2018-12-03 12:40:13 -05:00
break ;
2013-10-23 16:21:46 -04:00
2018-12-03 12:40:13 -05:00
default :
cli_warnmsg ( " cli_scanraw: Type %u not handled in fpt loop \n " , fpt - > type ) ;
2017-08-08 17:38:17 -04:00
}
2007-03-23 15:11:45 +00:00
2017-08-08 17:38:17 -04:00
if ( nret = = CL_VIRUS | | break_loop )
2013-10-23 16:21:46 -04:00
break ;
2007-03-23 15:11:45 +00:00
2013-10-23 16:21:46 -04:00
fpt = fpt - > next ;
}
2017-08-08 17:38:17 -04:00
if ( nret ! = CL_VIRUS )
2018-12-03 12:40:13 -05:00
switch ( ret ) {
case CL_TYPE_HTML :
/* bb#11196 - autoit script file misclassified as HTML */
if ( cli_get_container_intermediate ( ctx , - 2 ) = = CL_TYPE_AUTOIT ) {
ret = CL_TYPE_TEXT_ASCII ;
} else if ( SCAN_PARSE_HTML & & ( type = = CL_TYPE_TEXT_ASCII | | type = = CL_TYPE_GRAPHICS ) & &
( DCONF_DOC & DOC_CONF_HTML ) ) {
* dettype = CL_TYPE_HTML ;
nret = cli_scanhtml ( ctx ) ;
}
break ;
2017-08-08 17:38:17 -04:00
2018-12-03 12:40:13 -05:00
case CL_TYPE_MAIL :
cli_set_container ( ctx , CL_TYPE_MAIL , map - > len ) ;
if ( SCAN_PARSE_MAIL & & type = = CL_TYPE_TEXT_ASCII & & ( DCONF_MAIL & MAIL_CONF_MBOX ) ) {
* dettype = CL_TYPE_MAIL ;
nret = cli_scanmail ( ctx ) ;
}
break ;
2017-08-08 17:38:17 -04:00
2018-12-03 12:40:13 -05:00
default :
break ;
2017-08-08 17:38:17 -04:00
}
perf_nested_stop ( ctx , PERFT_RAWTYPENO , PERFT_SCAN ) ;
ctx - > recursion - - ;
ret = nret ;
}
2018-12-03 12:40:13 -05:00
while ( ftoffset ) {
fpt = ftoffset ;
2017-08-08 17:38:17 -04:00
ftoffset = ftoffset - > next ;
free ( fpt ) ;
}
if ( ret = = CL_VIRUS )
cli_dbgmsg ( " %s found \n " , cli_get_last_virus ( ctx ) ) ;
2007-02-25 21:46:38 +00:00
2006-01-25 12:11:31 +00:00
return ret ;
}
2017-08-08 17:38:17 -04:00
static void emax_reached ( cli_ctx * ctx )
{
2010-03-05 18:09:00 +01:00
fmap_t * * ctx_fmap = ctx - > fmap ;
2010-03-10 14:58:18 +02:00
if ( ! ctx_fmap )
2017-08-08 17:38:17 -04:00
return ;
2018-12-03 12:40:13 -05:00
while ( * ctx_fmap ) {
fmap_t * map = * ctx_fmap ;
2017-08-08 17:38:17 -04:00
map - > dont_cache_flag = 1 ;
ctx_fmap - - ;
2010-03-05 18:09:00 +01:00
}
cli_dbgmsg ( " emax_reached: marked parents as non cacheable \n " ) ;
}
2010-03-05 17:11:45 +01:00
# define LINESTR(x) #x
# define LINESTR2(x) LINESTR(x)
2017-08-08 17:38:17 -04:00
# define __AT__ " at line " LINESTR2(__LINE__)
2011-07-04 17:00:55 +03:00
2017-08-08 17:38:17 -04:00
# define early_ret_from_magicscan(retcode) \
2018-12-03 12:40:13 -05:00
do { \
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_magic_scandesc: returning %d %s (no post, no cache) \n " , retcode , __AT__ ) ; \
return retcode ; \
} while ( 0 )
2011-07-04 17:00:55 +03:00
2014-04-30 15:01:05 -04:00
static int magic_scandesc_cleanup ( cli_ctx * ctx , cli_file_t type , unsigned char * hash , size_t hashed_size , int cache_clean , int retcode , void * parent_property )
{
2015-09-01 13:42:53 -04:00
int cb_retcode ;
2014-04-23 17:37:23 -04:00
# if HAVE_JSON
2014-04-30 15:01:05 -04:00
ctx - > wrkproperty = ( struct json_object * ) ( parent_property ) ;
2014-07-09 13:16:31 -04:00
# else
UNUSEDPARAM ( parent_property ) ;
2014-04-23 17:37:23 -04:00
# endif
2014-07-09 13:16:31 -04:00
UNUSEDPARAM ( type ) ;
2018-12-03 12:40:13 -05:00
if ( retcode = = CL_CLEAN & & ctx - > found_possibly_unwanted ) {
2017-04-18 12:03:36 -04:00
cli_virus_found_cb ( ctx ) ;
2015-08-24 15:17:02 -04:00
cb_retcode = CL_VIRUS ;
2018-12-03 12:40:13 -05:00
} else {
2017-04-18 12:03:36 -04:00
if ( retcode = = CL_CLEAN & & ctx - > num_viruses ! = 0 )
cb_retcode = CL_VIRUS ;
else
cb_retcode = retcode ;
}
2015-08-24 15:17:02 -04:00
2014-04-30 15:01:05 -04:00
cli_dbgmsg ( " cli_magic_scandesc: returning %d %s \n " , retcode , __AT__ ) ;
2018-12-03 12:40:13 -05:00
if ( ctx - > engine - > cb_post_scan ) {
2017-08-08 17:38:17 -04:00
const char * virusname = NULL ;
2014-04-30 15:01:05 -04:00
perf_start ( ctx , PERFT_POSTCB ) ;
2015-08-24 15:17:02 -04:00
if ( cb_retcode = = CL_VIRUS )
virusname = cli_get_last_virus ( ctx ) ;
2018-12-03 12:40:13 -05:00
switch ( ctx - > engine - > cb_post_scan ( fmap_fd ( * ctx - > fmap ) , cb_retcode , virusname , ctx - > cb_ctx ) ) {
case CL_BREAK :
cli_dbgmsg ( " cli_magic_scandesc: file whitelisted by post_scan callback \n " ) ;
perf_stop ( ctx , PERFT_POSTCB ) ;
return CL_CLEAN ;
case CL_VIRUS :
cli_dbgmsg ( " cli_magic_scandesc: file blacklisted by post_scan callback \n " ) ;
cli_append_virus ( ctx , " Detected.By.Callback " ) ;
perf_stop ( ctx , PERFT_POSTCB ) ;
if ( retcode ! = CL_VIRUS )
return cli_checkfp ( hash , hashed_size , ctx ) ;
return CL_VIRUS ;
case CL_CLEAN :
break ;
default :
cli_warnmsg ( " cli_magic_scandesc: ignoring bad return code from post_scan callback \n " ) ;
2014-04-30 15:01:05 -04:00
}
perf_stop ( ctx , PERFT_POSTCB ) ;
2011-03-04 18:27:32 +01:00
}
2018-12-03 12:40:13 -05:00
if ( cb_retcode = = CL_CLEAN & & cache_clean ) {
2014-04-30 15:01:05 -04:00
perf_start ( ctx , PERFT_CACHE ) ;
2018-07-20 22:28:48 -04:00
if ( ! ( SCAN_COLLECT_METADATA ) )
2015-11-04 14:46:46 -05:00
cache_add ( hash , hashed_size , ctx ) ;
2014-04-30 15:01:05 -04:00
perf_stop ( ctx , PERFT_CACHE ) ;
}
2018-07-20 22:28:48 -04:00
if ( retcode = = CL_VIRUS & & SCAN_ALLMATCHES )
2016-06-08 16:25:34 -04:00
return CL_CLEAN ;
2014-04-30 15:01:05 -04:00
return retcode ;
}
2011-03-04 18:27:32 +01:00
2014-04-30 15:01:05 -04:00
static int dispatch_prescan ( clcb_pre_scan cb , cli_ctx * ctx , const char * filetype , bitset_t * old_hook_lsig_matches , void * parent_property , unsigned char * hash , size_t hashed_size , int * run_cleanup )
{
2017-08-08 17:38:17 -04:00
int res = CL_CLEAN ;
2014-04-30 15:01:05 -04:00
2014-07-09 13:16:31 -04:00
UNUSEDPARAM ( parent_property ) ;
UNUSEDPARAM ( hash ) ;
UNUSEDPARAM ( hashed_size ) ;
2014-04-30 15:01:05 -04:00
* run_cleanup = 0 ;
2018-12-03 12:40:13 -05:00
if ( cb ) {
2014-04-30 15:01:05 -04:00
perf_start ( ctx , PERFT_PRECB ) ;
2018-12-03 12:40:13 -05:00
switch ( cb ( fmap_fd ( * ctx - > fmap ) , filetype , ctx - > cb_ctx ) ) {
case CL_BREAK :
cli_dbgmsg ( " cli_magic_scandesc: file whitelisted by callback \n " ) ;
perf_stop ( ctx , PERFT_PRECB ) ;
ctx - > hook_lsig_matches = old_hook_lsig_matches ;
/* returns CL_CLEAN */
* run_cleanup = 1 ;
break ;
case CL_VIRUS :
cli_dbgmsg ( " cli_magic_scandesc: file blacklisted by callback \n " ) ;
cli_append_virus ( ctx , " Detected.By.Callback " ) ;
perf_stop ( ctx , PERFT_PRECB ) ;
ctx - > hook_lsig_matches = old_hook_lsig_matches ;
* run_cleanup = 1 ;
res = CL_VIRUS ;
break ;
case CL_CLEAN :
break ;
default :
cli_warnmsg ( " cli_magic_scandesc: ignoring bad return code from callback \n " ) ;
2014-04-30 15:01:05 -04:00
}
2011-03-04 18:27:32 +01:00
2014-04-30 15:01:05 -04:00
perf_stop ( ctx , PERFT_PRECB ) ;
}
return res ;
}
2011-03-04 18:27:32 +01:00
2011-06-14 11:11:05 +03:00
static int magic_scandesc ( cli_ctx * ctx , cli_file_t type )
2003-07-29 15:48:06 +00:00
{
2018-12-03 12:40:13 -05:00
int ret = CL_CLEAN ;
2017-08-08 17:38:17 -04:00
cli_file_t dettype = 0 ;
2018-12-03 12:40:13 -05:00
uint8_t typercg = 1 ;
2017-08-08 17:38:17 -04:00
size_t hashed_size ;
unsigned char hash [ 16 ] = { ' \0 ' } ;
bitset_t * old_hook_lsig_matches ;
const char * filetype ;
int cache_clean = 0 , res ;
int run_cleanup = 0 ;
2014-04-23 17:37:23 -04:00
# if HAVE_JSON
2017-08-08 17:38:17 -04:00
struct json_object * parent_property = NULL ;
2014-04-30 15:01:05 -04:00
# else
2017-08-08 17:38:17 -04:00
void * parent_property = NULL ;
2014-04-23 11:47:30 -04:00
# endif
2005-03-22 21:26:27 +00:00
2018-12-03 12:40:13 -05:00
if ( ! ctx - > engine ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " CRITICAL: engine == NULL \n " ) ;
early_ret_from_magicscan ( CL_ENULLARG ) ;
2009-03-02 16:36:23 +00:00
}
2018-12-03 12:40:13 -05:00
if ( ! ( ctx - > engine - > dboptions & CL_DB_COMPILED ) ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " CRITICAL: engine not compiled \n " ) ;
early_ret_from_magicscan ( CL_EMALFDB ) ;
2003-07-29 15:48:06 +00:00
}
2018-12-03 12:40:13 -05:00
if ( ctx - > engine - > maxreclevel & & ctx - > recursion > ctx - > engine - > maxreclevel ) {
2012-11-27 17:15:02 -05:00
cli_dbgmsg ( " cli_magic_scandesc: Archive recursion limit exceeded (%u, max: %u) \n " , ctx - > recursion , ctx - > engine - > maxreclevel ) ;
2017-08-08 17:38:17 -04:00
emax_reached ( ctx ) ;
2016-08-24 17:39:20 -04:00
cli_check_blockmax ( ctx , CL_EMAXREC ) ;
2017-08-08 17:38:17 -04:00
early_ret_from_magicscan ( CL_CLEAN ) ;
2012-11-27 17:15:02 -05:00
}
2018-12-03 12:40:13 -05:00
if ( cli_updatelimits ( ctx , ( * ctx - > fmap ) - > len ) ! = CL_CLEAN ) {
2017-08-08 17:38:17 -04:00
emax_reached ( ctx ) ;
2011-07-04 17:00:55 +03:00
early_ret_from_magicscan ( CL_CLEAN ) ;
2009-08-30 19:14:49 +02:00
}
2013-03-05 11:21:29 -05:00
old_hook_lsig_matches = ctx - > hook_lsig_matches ;
2018-12-03 12:40:13 -05:00
if ( type = = CL_TYPE_PART_ANY ) {
2017-08-08 17:38:17 -04:00
typercg = 0 ;
2013-09-17 16:45:48 -04:00
}
2009-08-30 19:14:49 +02:00
2011-06-14 17:00:06 +02:00
perf_start ( ctx , PERFT_FT ) ;
2018-12-03 12:40:13 -05:00
if ( ( type = = CL_TYPE_ANY ) | | type = = CL_TYPE_PART_ANY ) {
2017-08-08 17:38:17 -04:00
type = cli_filetype2 ( * ctx - > fmap , ctx - > engine , type ) ;
2014-03-24 18:45:29 -04:00
}
2011-06-14 17:00:06 +02:00
perf_stop ( ctx , PERFT_FT ) ;
2018-12-03 12:40:13 -05:00
if ( type = = CL_TYPE_ERROR ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_magic_scandesc: cli_filetype2 returned CL_TYPE_ERROR \n " ) ;
early_ret_from_magicscan ( CL_EREAD ) ;
2011-06-14 03:26:30 +02:00
}
2011-06-14 17:00:06 +02:00
filetype = cli_ftname ( type ) ;
2014-04-16 16:40:56 -04:00
2014-04-23 17:37:23 -04:00
# if HAVE_JSON
2018-12-03 12:40:13 -05:00
if ( SCAN_COLLECT_METADATA ) {
2014-07-09 13:16:31 -04:00
json_object * arrobj ;
2014-04-23 11:47:30 -04:00
2018-12-03 12:40:13 -05:00
if ( NULL = = ctx - > properties ) {
2017-08-08 17:38:17 -04:00
if ( type = = CL_TYPE_PDF | | /* file types we collect properties about */
2014-04-28 16:37:05 -04:00
type = = CL_TYPE_MSOLE2 | |
type = = CL_TYPE_MSEXE | |
2014-10-16 18:38:29 -04:00
//type == CL_TYPE_ZIP ||
2014-04-28 16:37:05 -04:00
type = = CL_TYPE_OOXML_WORD | |
type = = CL_TYPE_OOXML_PPT | |
2015-03-12 13:46:59 -04:00
type = = CL_TYPE_OOXML_XL | |
type = = CL_TYPE_XML_WORD | |
2015-12-08 17:28:49 -05:00
type = = CL_TYPE_XML_XL | |
2015-12-15 13:01:40 -05:00
type = = CL_TYPE_HWP3 | |
2015-12-17 11:04:00 -05:00
type = = CL_TYPE_XML_HWP | |
2015-12-17 16:16:55 -05:00
type = = CL_TYPE_HWPOLE2 | |
2016-05-03 12:57:13 -04:00
type = = CL_TYPE_OOXML_HWP | |
2018-12-03 12:40:13 -05:00
type = = CL_TYPE_MHTML ) {
2014-04-28 16:37:05 -04:00
ctx - > properties = json_object_new_object ( ) ;
2018-12-03 12:40:13 -05:00
if ( NULL = = ctx - > properties ) {
2014-04-28 16:37:05 -04:00
cli_errmsg ( " magic_scandesc: no memory for json properties object \n " ) ;
2017-08-08 17:38:17 -04:00
early_ret_from_magicscan ( CL_EMEM ) ;
2014-04-28 16:37:05 -04:00
}
ctx - > wrkproperty = ctx - > properties ;
2018-12-03 12:40:13 -05:00
ret = cli_jsonstr ( ctx - > properties , " Magic " , " CLAMJSONv0 " ) ;
if ( ret ! = CL_SUCCESS ) {
2014-04-29 17:15:07 -04:00
early_ret_from_magicscan ( ret ) ;
}
2014-07-03 12:05:24 -04:00
ret = cli_jsonstr ( ctx - > properties , " RootFileType " , filetype ) ;
2018-12-03 12:40:13 -05:00
if ( ret ! = CL_SUCCESS ) {
2014-06-30 11:44:02 -04:00
early_ret_from_magicscan ( ret ) ;
}
2018-12-03 12:40:13 -05:00
} else { /* turn off property collection flag for file types we don't care about */
2018-07-20 22:28:48 -04:00
ctx - > options - > general & = ~ CL_SCAN_GENERAL_COLLECT_METADATA ;
2014-04-23 11:47:30 -04:00
}
2018-12-03 12:40:13 -05:00
} else {
2014-04-23 11:47:30 -04:00
parent_property = ctx - > wrkproperty ;
2018-12-03 12:40:13 -05:00
if ( ! json_object_object_get_ex ( parent_property , " ContainedObjects " , & arrobj ) ) {
2014-04-23 11:47:30 -04:00
arrobj = json_object_new_array ( ) ;
2018-12-03 12:40:13 -05:00
if ( NULL = = arrobj ) {
2014-04-23 11:47:30 -04:00
cli_errmsg ( " magic_scandesc: no memory for json properties object \n " ) ;
early_ret_from_magicscan ( CL_EMEM ) ;
}
2014-04-28 17:01:57 -04:00
json_object_object_add ( parent_property , " ContainedObjects " , arrobj ) ;
2014-04-23 11:47:30 -04:00
}
ctx - > wrkproperty = json_object_new_object ( ) ;
2018-12-03 12:40:13 -05:00
if ( NULL = = ctx - > wrkproperty ) {
2014-04-23 11:47:30 -04:00
cli_errmsg ( " magic_scandesc: no memory for json properties object \n " ) ;
early_ret_from_magicscan ( CL_EMEM ) ;
}
json_object_array_add ( arrobj , ctx - > wrkproperty ) ;
}
2014-04-28 17:25:14 -04:00
}
2014-04-23 11:47:30 -04:00
2018-12-03 12:40:13 -05:00
if ( SCAN_COLLECT_METADATA ) { /* separated for cases json is not tracked */
2014-04-30 15:01:05 -04:00
ret = cli_jsonstr ( ctx - > wrkproperty , " FileType " , filetype ) ;
2018-12-03 12:40:13 -05:00
if ( ret ! = CL_SUCCESS ) {
2014-04-24 14:22:00 -04:00
early_ret_from_magicscan ( ret ) ;
2014-04-16 16:40:56 -04:00
}
2014-04-30 15:01:05 -04:00
ret = cli_jsonint ( ctx - > wrkproperty , " FileSize " , ( * ctx - > fmap ) - > len ) ;
2018-12-03 12:40:13 -05:00
if ( ret ! = CL_SUCCESS ) {
2014-04-24 14:22:00 -04:00
early_ret_from_magicscan ( ret ) ;
2014-04-16 16:40:56 -04:00
}
}
# endif
2012-01-10 17:29:08 +02:00
hashed_size = 0 ;
2018-12-03 12:40:13 -05:00
ret = dispatch_prescan ( ctx - > engine - > cb_pre_cache , ctx , filetype , old_hook_lsig_matches , parent_property , hash , hashed_size , & run_cleanup ) ;
if ( run_cleanup ) {
2014-04-30 15:01:05 -04:00
if ( ret = = CL_VIRUS )
return magic_scandesc_cleanup ( ctx , type , hash , hashed_size , cache_clean , cli_checkfp ( hash , hashed_size , ctx ) , parent_property ) ;
else
return magic_scandesc_cleanup ( ctx , type , hash , hashed_size , cache_clean , CL_CLEAN , parent_property ) ;
}
2011-06-14 03:26:30 +02:00
2011-02-14 19:19:20 +02:00
perf_start ( ctx , PERFT_CACHE ) ;
2018-07-20 22:28:48 -04:00
if ( ! ( SCAN_COLLECT_METADATA ) )
2015-11-04 14:46:46 -05:00
res = cache_check ( hash , ctx ) ;
2017-01-04 13:20:29 -05:00
else
res = CL_VIRUS ;
2014-04-24 14:22:00 -04:00
# if HAVE_JSON
2018-12-03 12:40:13 -05:00
if ( SCAN_COLLECT_METADATA /* ctx.options->general & CL_SCAN_GENERAL_COLLECT_METADATA && ctx->wrkproperty != NULL */ ) {
2014-04-24 14:22:00 -04:00
char hashstr [ 33 ] ;
2015-11-04 14:46:46 -05:00
ret = cache_get_MD5 ( hash , ctx ) ;
2018-12-03 12:40:13 -05:00
if ( ret ! = CL_SUCCESS ) {
2015-11-04 14:46:46 -05:00
early_ret_from_magicscan ( ret ) ;
}
snprintf ( hashstr , 33 , " %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x " ,
hash [ 0 ] , hash [ 1 ] , hash [ 2 ] , hash [ 3 ] , hash [ 4 ] , hash [ 5 ] , hash [ 6 ] , hash [ 7 ] ,
hash [ 8 ] , hash [ 9 ] , hash [ 10 ] , hash [ 11 ] , hash [ 12 ] , hash [ 13 ] , hash [ 14 ] , hash [ 15 ] ) ;
2014-04-24 14:22:00 -04:00
2014-04-30 15:01:05 -04:00
ret = cli_jsonstr ( ctx - > wrkproperty , " FileMD5 " , hashstr ) ;
2015-11-04 14:46:46 -05:00
if ( ctx - > engine - > engine_options & ENGINE_OPTIONS_DISABLE_CACHE )
memset ( hash , 0 , sizeof ( hash ) ) ;
2018-12-03 12:40:13 -05:00
if ( ret ! = CL_SUCCESS ) {
2014-04-24 14:22:00 -04:00
early_ret_from_magicscan ( ret ) ;
}
}
# endif
2018-12-03 12:40:13 -05:00
if ( res ! = CL_VIRUS ) {
2017-08-08 17:38:17 -04:00
perf_stop ( ctx , PERFT_CACHE ) ;
2014-04-23 17:37:23 -04:00
# if HAVE_JSON
2014-04-23 11:47:30 -04:00
ctx - > wrkproperty = parent_property ;
2014-04-23 17:37:23 -04:00
# endif
2017-08-08 17:38:17 -04:00
early_ret_from_magicscan ( res ) ;
2010-01-05 18:15:59 +01:00
}
2012-05-08 15:34:27 +02:00
2011-02-14 19:19:20 +02:00
perf_stop ( ctx , PERFT_CACHE ) ;
2010-01-15 03:00:15 +01:00
hashed_size = ( * ctx - > fmap ) - > len ;
2017-04-18 12:03:36 -04:00
memcpy ( ( * ctx - > fmap ) - > maphash , hash , 16 ) ;
2010-01-19 16:38:12 +02:00
ctx - > hook_lsig_matches = NULL ;
2010-01-15 03:00:15 +01:00
2018-12-03 12:40:13 -05:00
if ( ! ( ( ctx - > options - > general & ~ CL_SCAN_GENERAL_ALLMATCHES ) | | ( ctx - > options - > parse ) | | ( ctx - > options - > heuristic ) | | ( ctx - > options - > mail ) | | ( ctx - > options - > dev ) ) | | ( ctx - > recursion = = ctx - > engine - > maxreclevel ) ) { /* raw mode (stdin, etc.) or last level of recursion */
if ( ctx - > recursion = = ctx - > engine - > maxreclevel ) {
2016-08-24 17:39:20 -04:00
cli_check_blockmax ( ctx , CL_EMAXREC ) ;
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_magic_scandesc: Hit recursion limit, only scanning raw file \n " ) ;
2018-12-03 12:40:13 -05:00
} else
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Raw mode: No support for special files \n " ) ;
2010-03-05 17:11:45 +01:00
2017-08-08 17:38:17 -04:00
ret = dispatch_prescan ( ctx - > engine - > cb_pre_scan , ctx , filetype , old_hook_lsig_matches , parent_property , hash , hashed_size , & run_cleanup ) ;
2018-12-03 12:40:13 -05:00
if ( run_cleanup ) {
2017-08-08 17:38:17 -04:00
if ( ret = = CL_VIRUS )
return magic_scandesc_cleanup ( ctx , type , hash , hashed_size , cache_clean , cli_checkfp ( hash , hashed_size , ctx ) , parent_property ) ;
else
return magic_scandesc_cleanup ( ctx , type , hash , hashed_size , cache_clean , ret , parent_property ) ;
}
/* ret_from_magicscan can be used below here*/
if ( ( ret = cli_fmap_scandesc ( ctx , 0 , 0 , NULL , AC_SCAN_VIR , NULL , hash ) ) = = CL_VIRUS )
cli_dbgmsg ( " %s found in descriptor %d \n " , cli_get_last_virus ( ctx ) , fmap_fd ( * ctx - > fmap ) ) ;
2018-12-03 12:40:13 -05:00
else if ( ret = = CL_CLEAN ) {
2017-08-08 17:38:17 -04:00
if ( ctx - > recursion ! = ctx - > engine - > maxreclevel )
cache_clean = 1 ; /* Only cache if limits are not reached */
else
emax_reached ( ctx ) ;
}
ctx - > hook_lsig_matches = old_hook_lsig_matches ;
return magic_scandesc_cleanup ( ctx , type , hash , hashed_size , cache_clean , ret , parent_property ) ;
2008-02-06 21:19:10 +00:00
}
2003-07-29 15:48:06 +00:00
2014-04-30 15:01:05 -04:00
ret = dispatch_prescan ( ctx - > engine - > cb_pre_scan , ctx , filetype , old_hook_lsig_matches , parent_property , hash , hashed_size , & run_cleanup ) ;
2018-12-03 12:40:13 -05:00
if ( run_cleanup ) {
2014-04-30 15:01:05 -04:00
if ( ret = = CL_VIRUS )
return magic_scandesc_cleanup ( ctx , type , hash , hashed_size , cache_clean , cli_checkfp ( hash , hashed_size , ctx ) , parent_property ) ;
else
return magic_scandesc_cleanup ( ctx , type , hash , hashed_size , cache_clean , ret , parent_property ) ;
}
2018-12-03 12:40:13 -05:00
/* ret_from_magicscan can be used below here*/
2011-03-04 18:27:32 +01:00
2010-05-07 19:47:11 +02:00
# ifdef HAVE__INTERNAL__SHA_COLLECT
2017-08-08 17:38:17 -04:00
if ( ! ctx - > sha_collect & & type = = CL_TYPE_MSEXE )
ctx - > sha_collect = 1 ;
2010-05-07 19:47:11 +02:00
# endif
2004-02-06 13:46:08 +00:00
2010-01-19 16:38:12 +02:00
ctx - > hook_lsig_matches = cli_bitset_init ( ) ;
2018-12-03 12:40:13 -05:00
if ( ! ctx - > hook_lsig_matches ) {
2017-08-08 17:38:17 -04:00
ctx - > hook_lsig_matches = old_hook_lsig_matches ;
return magic_scandesc_cleanup ( ctx , type , hash , hashed_size , cache_clean , CL_EMEM , parent_property ) ;
2010-03-05 19:56:43 +02:00
}
2010-01-19 16:38:12 +02:00
2018-12-03 12:40:13 -05:00
if ( type ! = CL_TYPE_IGNORED & & ctx - > engine - > sdb ) {
if ( ( ret = cli_scanraw ( ctx , type , 0 , & dettype , ( ctx - > engine - > engine_options & ENGINE_OPTIONS_DISABLE_CACHE ) ? NULL : hash ) ) = = CL_VIRUS ) {
2017-08-08 17:38:17 -04:00
ret = cli_checkfp ( hash , hashed_size , ctx ) ;
cli_bitset_free ( ctx - > hook_lsig_matches ) ;
ctx - > hook_lsig_matches = old_hook_lsig_matches ;
return magic_scandesc_cleanup ( ctx , type , hash , hashed_size , cache_clean , ret , parent_property ) ;
}
2006-01-25 12:11:31 +00:00
}
2008-02-06 21:19:10 +00:00
ctx - > recursion + + ;
2011-02-14 19:19:20 +02:00
perf_nested_start ( ctx , PERFT_CONTAINER , PERFT_SCAN ) ;
2017-01-19 12:24:46 -05:00
/* set current level as container AFTER recursing */
cli_set_container ( ctx , type , ( * ctx - > fmap ) - > len ) ;
2018-12-03 12:40:13 -05:00
switch ( type ) {
case CL_TYPE_IGNORED :
break ;
case CL_TYPE_HWP3 :
if ( SCAN_PARSE_HWP3 & & ( DCONF_DOC & DOC_CONF_HWP ) )
ret = cli_scanhwp3 ( ctx ) ;
break ;
case CL_TYPE_HWPOLE2 :
if ( SCAN_PARSE_OLE2 & & ( DCONF_ARCH & ARCH_CONF_OLE2 ) )
ret = cli_scanhwpole2 ( ctx ) ;
break ;
case CL_TYPE_XML_WORD :
if ( SCAN_PARSE_XMLDOCS & & ( DCONF_DOC & DOC_CONF_MSXML ) )
ret = cli_scanmsxml ( ctx ) ;
break ;
case CL_TYPE_XML_XL :
if ( SCAN_PARSE_XMLDOCS & & ( DCONF_DOC & DOC_CONF_MSXML ) )
ret = cli_scanmsxml ( ctx ) ;
break ;
case CL_TYPE_XML_HWP :
if ( SCAN_PARSE_XMLDOCS & & ( DCONF_DOC & DOC_CONF_HWP ) )
ret = cli_scanhwpml ( ctx ) ;
break ;
case CL_TYPE_XDP :
if ( SCAN_PARSE_PDF & & ( DCONF_DOC & DOC_CONF_PDF ) )
ret = cli_scanxdp ( ctx ) ;
break ;
case CL_TYPE_RAR :
if ( have_rar & & SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_RAR ) ) {
const char * filepath = NULL ;
int fd = - 1 ;
char * tmpname = NULL ;
int tmpfd = - 1 ;
if ( ctx - > sub_filepath = = NULL ) {
/* If map is not file-backed have to dump to file for scanrar. */
ret = fmap_dump_to_file ( * ctx - > fmap , ctx - > sub_filepath , ctx - > engine - > tmpdir , & tmpname , & tmpfd , 0 , SIZE_MAX ) ;
if ( ret ! = CL_SUCCESS ) {
cli_dbgmsg ( " magic_scandesc: failed to generate temporary file. \n " ) ;
break ;
}
filepath = tmpname ;
fd = tmpfd ;
} else {
/* Use the original file and file descriptor. */
filepath = ctx - > sub_filepath ;
fd = fmap_fd ( * ctx - > fmap ) ;
2017-08-08 17:38:17 -04:00
}
2018-07-30 20:19:28 -04:00
2018-12-03 12:40:13 -05:00
/* scan file */
ret = cli_scanrar ( filepath , fd , ctx ) ;
2018-07-30 20:19:28 -04:00
2018-12-03 12:40:13 -05:00
if ( tmpfd ! = - 1 ) {
/* If dumped tempfile, need to cleanup */
close ( tmpfd ) ;
if ( ! ctx - > engine - > keeptmp ) {
if ( cli_unlink ( tmpname ) ) {
ret = CL_EUNLINK ;
}
2018-07-30 20:19:28 -04:00
}
}
2018-12-03 12:40:13 -05:00
if ( tmpname ! = NULL ) {
free ( tmpname ) ;
}
2017-08-08 17:38:17 -04:00
}
2018-12-03 12:40:13 -05:00
break ;
2017-08-08 17:38:17 -04:00
2018-12-03 12:40:13 -05:00
case CL_TYPE_OOXML_WORD :
case CL_TYPE_OOXML_PPT :
case CL_TYPE_OOXML_XL :
case CL_TYPE_OOXML_HWP :
2014-04-24 14:22:00 -04:00
# if HAVE_JSON
2018-12-03 12:40:13 -05:00
if ( SCAN_PARSE_XMLDOCS & & ( DCONF_DOC & DOC_CONF_OOXML ) ) {
if ( SCAN_COLLECT_METADATA & & ( ctx - > wrkproperty ! = NULL ) ) {
ret = cli_process_ooxml ( ctx , type ) ;
if ( ret = = CL_EMEM | | ret = = CL_ENULLARG ) {
/* critical error */
break ;
} else if ( ret ! = CL_SUCCESS ) {
/*
2017-08-08 17:38:17 -04:00
* non - critical return = > allow for the CL_TYPE_ZIP scan to occur
* cli_process_ooxml other possible returns :
* CL_ETIMEOUT , CL_EMAXSIZE , CL_EMAXFILES , CL_EPARSE ,
* CL_EFORMAT , CL_BREAK , CL_ESTAT
*/
2018-12-03 12:40:13 -05:00
ret = CL_SUCCESS ;
}
2017-08-08 17:38:17 -04:00
}
}
2014-04-24 14:22:00 -04:00
# endif
2018-12-03 12:40:13 -05:00
case CL_TYPE_ZIP :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_ZIP ) )
ret = cli_unzip ( ctx ) ;
break ;
case CL_TYPE_GZ :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_GZ ) )
ret = cli_scangzip ( ctx ) ;
break ;
case CL_TYPE_BZ :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_BZ ) )
ret = cli_scanbzip ( ctx ) ;
break ;
case CL_TYPE_XZ :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_XZ ) )
ret = cli_scanxz ( ctx ) ;
break ;
case CL_TYPE_GPT :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_GPT ) )
ret = cli_scangpt ( ctx , 0 ) ;
break ;
case CL_TYPE_APM :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_APM ) )
ret = cli_scanapm ( ctx ) ;
break ;
case CL_TYPE_ARJ :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_ARJ ) )
ret = cli_scanarj ( ctx , 0 ) ;
break ;
case CL_TYPE_NULSFT :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_NSIS ) )
ret = cli_scannulsft ( ctx , 0 ) ;
break ;
case CL_TYPE_AUTOIT :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_AUTOIT ) )
ret = cli_scanautoit ( ctx , 23 ) ;
break ;
case CL_TYPE_MSSZDD :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_SZDD ) )
ret = cli_scanszdd ( ctx ) ;
break ;
case CL_TYPE_MSCAB :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_CAB ) )
ret = cli_scanmscab ( ctx , 0 ) ;
break ;
case CL_TYPE_HTML :
if ( SCAN_PARSE_HTML & & ( DCONF_DOC & DOC_CONF_HTML ) )
ret = cli_scanhtml ( ctx ) ;
break ;
case CL_TYPE_HTML_UTF16 :
if ( SCAN_PARSE_HTML & & ( DCONF_DOC & DOC_CONF_HTML ) )
ret = cli_scanhtml_utf16 ( ctx ) ;
break ;
case CL_TYPE_SCRIPT :
if ( ( DCONF_DOC & DOC_CONF_SCRIPT ) & & dettype ! = CL_TYPE_HTML )
ret = cli_scanscript ( ctx ) ;
break ;
case CL_TYPE_SWF :
if ( SCAN_PARSE_SWF & & ( DCONF_DOC & DOC_CONF_SWF ) )
ret = cli_scanswf ( ctx ) ;
break ;
case CL_TYPE_RTF :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_DOC & DOC_CONF_RTF ) )
ret = cli_scanrtf ( ctx ) ;
break ;
case CL_TYPE_MAIL :
if ( SCAN_PARSE_MAIL & & ( DCONF_MAIL & MAIL_CONF_MBOX ) )
ret = cli_scanmail ( ctx ) ;
break ;
case CL_TYPE_MHTML :
if ( SCAN_PARSE_MAIL & & ( DCONF_MAIL & MAIL_CONF_MBOX ) )
ret = cli_scanmail ( ctx ) ;
break ;
case CL_TYPE_TNEF :
if ( SCAN_PARSE_MAIL & & ( DCONF_MAIL & MAIL_CONF_TNEF ) )
ret = cli_scantnef ( ctx ) ;
break ;
case CL_TYPE_UUENCODED :
if ( DCONF_OTHER & OTHER_CONF_UUENC )
ret = cli_scanuuencoded ( ctx ) ;
break ;
case CL_TYPE_MSCHM :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_CHM ) )
ret = cli_scanmschm ( ctx ) ;
break ;
case CL_TYPE_MSOLE2 :
if ( SCAN_PARSE_OLE2 & & ( DCONF_ARCH & ARCH_CONF_OLE2 ) )
ret = cli_scanole2 ( ctx ) ;
break ;
case CL_TYPE_7Z :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_7Z ) )
ret = cli_7unz ( ctx , 0 ) ;
break ;
case CL_TYPE_POSIX_TAR :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_TAR ) )
ret = cli_scantar ( ctx , 1 ) ;
break ;
case CL_TYPE_OLD_TAR :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_TAR ) )
ret = cli_scantar ( ctx , 0 ) ;
break ;
case CL_TYPE_CPIO_OLD :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_CPIO ) )
ret = cli_scancpio_old ( ctx ) ;
break ;
case CL_TYPE_CPIO_ODC :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_CPIO ) )
ret = cli_scancpio_odc ( ctx ) ;
break ;
case CL_TYPE_CPIO_NEWC :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_CPIO ) )
ret = cli_scancpio_newc ( ctx , 0 ) ;
break ;
case CL_TYPE_CPIO_CRC :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_CPIO ) )
ret = cli_scancpio_newc ( ctx , 1 ) ;
break ;
case CL_TYPE_BINHEX :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_BINHEX ) )
ret = cli_binhex ( ctx ) ;
break ;
case CL_TYPE_SCRENC :
if ( DCONF_OTHER & OTHER_CONF_SCRENC )
ret = cli_scanscrenc ( ctx ) ;
break ;
case CL_TYPE_RIFF :
if ( SCAN_HEURISTICS & & ( DCONF_OTHER & OTHER_CONF_RIFF ) )
ret = cli_scanriff ( ctx ) ;
break ;
case CL_TYPE_GRAPHICS :
if ( SCAN_HEURISTICS & & ( DCONF_OTHER & OTHER_CONF_JPEG ) )
ret = cli_scanjpeg ( ctx ) ;
if ( ctx - > img_validate & & SCAN_HEURISTICS & & ret ! = CL_VIRUS )
ret = cli_parsejpeg ( ctx ) ;
if ( ctx - > img_validate & & SCAN_HEURISTICS & & ret ! = CL_VIRUS & & ret ! = CL_EPARSE )
ret = cli_parsepng ( ctx ) ;
if ( ctx - > img_validate & & SCAN_HEURISTICS & & ret ! = CL_VIRUS & & ret ! = CL_EPARSE )
ret = cli_parsegif ( ctx ) ;
if ( ctx - > img_validate & & SCAN_HEURISTICS & & ret ! = CL_VIRUS & & ret ! = CL_EPARSE )
ret = cli_parsetiff ( ctx ) ;
break ;
case CL_TYPE_PDF : /* FIXMELIMITS: pdf should be an archive! */
if ( SCAN_PARSE_PDF & & ( DCONF_DOC & DOC_CONF_PDF ) )
ret = cli_scanpdf ( ctx , 0 ) ;
break ;
case CL_TYPE_CRYPTFF :
if ( DCONF_OTHER & OTHER_CONF_CRYPTFF )
ret = cli_scancryptff ( ctx ) ;
break ;
case CL_TYPE_ELF :
if ( SCAN_PARSE_ELF & & ctx - > dconf - > elf )
ret = cli_scanelf ( ctx ) ;
break ;
case CL_TYPE_MACHO :
if ( ctx - > dconf - > macho )
ret = cli_scanmacho ( ctx , NULL ) ;
break ;
case CL_TYPE_MACHO_UNIBIN :
if ( ctx - > dconf - > macho )
ret = cli_scanmacho_unibin ( ctx ) ;
break ;
case CL_TYPE_SIS :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_SIS ) )
ret = cli_scansis ( ctx ) ;
break ;
case CL_TYPE_XAR :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_XAR ) )
ret = cli_scanxar ( ctx ) ;
break ;
case CL_TYPE_PART_HFSPLUS :
if ( SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_HFSPLUS ) )
ret = cli_scanhfsplus ( ctx ) ;
break ;
case CL_TYPE_BINARY_DATA :
case CL_TYPE_TEXT_UTF16BE :
if ( SCAN_HEURISTICS & & ( DCONF_OTHER & OTHER_CONF_MYDOOMLOG ) )
ret = cli_check_mydoom_log ( ctx ) ;
break ;
case CL_TYPE_TEXT_ASCII :
if ( SCAN_HEURISTIC_STRUCTURED & & ( DCONF_OTHER & OTHER_CONF_DLP ) )
/* TODO: consider calling this from cli_scanscript() for
2017-08-08 17:38:17 -04:00
* a normalised text
*/
2018-12-03 12:40:13 -05:00
ret = cli_scan_structured ( ctx ) ;
break ;
2017-08-08 17:38:17 -04:00
2018-12-03 12:40:13 -05:00
default :
break ;
2003-07-29 15:48:06 +00:00
}
2011-02-14 19:19:20 +02:00
perf_nested_stop ( ctx , PERFT_CONTAINER , PERFT_SCAN ) ;
2008-02-06 21:19:10 +00:00
ctx - > recursion - - ;
2004-04-20 22:33:42 +00:00
2018-12-03 12:40:13 -05:00
if ( ret = = CL_VIRUS & & ! SCAN_ALLMATCHES ) {
2017-08-08 17:38:17 -04:00
cli_bitset_free ( ctx - > hook_lsig_matches ) ;
ctx - > hook_lsig_matches = old_hook_lsig_matches ;
return magic_scandesc_cleanup ( ctx , type , hash , hashed_size , cache_clean , ret , parent_property ) ;
2009-08-30 19:14:49 +02:00
}
2008-04-16 18:47:42 +00:00
2018-12-03 12:40:13 -05:00
if ( type = = CL_TYPE_ZIP & & SCAN_PARSE_ARCHIVE & & ( DCONF_ARCH & ARCH_CONF_ZIP ) ) {
2017-08-08 17:38:17 -04:00
/* CL_ENGINE_MAX_ZIPTYPERCG */
uint64_t curr_len = ( * ctx - > fmap ) - > len ;
2018-12-03 12:40:13 -05:00
if ( curr_len > ctx - > engine - > maxziptypercg ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_magic_scandesc: Not checking for embedded PEs (zip file > MaxZipTypeRcg) \n " ) ;
typercg = 0 ;
}
2007-07-16 15:58:54 +00:00
}
2008-02-19 18:43:42 +00:00
/* CL_TYPE_HTML: raw HTML files are not scanned, unless safety measure activated via DCONF */
2018-12-03 12:40:13 -05:00
if ( type ! = CL_TYPE_IGNORED & & ( type ! = CL_TYPE_HTML | | ! ( SCAN_PARSE_HTML ) | | ! ( DCONF_DOC & DOC_CONF_HTML_SKIPRAW ) ) & & ! ctx - > engine - > sdb ) {
2017-08-08 17:38:17 -04:00
res = cli_scanraw ( ctx , type , typercg , & dettype , ( ctx - > engine - > engine_options & ENGINE_OPTIONS_DISABLE_CACHE ) ? NULL : hash ) ;
2018-12-03 12:40:13 -05:00
if ( res ! = CL_CLEAN ) {
switch ( res ) {
/* List of scan halts, runtime errors only! */
case CL_EUNLINK :
case CL_ESTAT :
case CL_ESEEK :
case CL_EWRITE :
case CL_EDUP :
case CL_ETMPFILE :
case CL_ETMPDIR :
case CL_EMEM :
case CL_ETIMEOUT :
cli_dbgmsg ( " Descriptor[%d]: cli_scanraw error %s \n " , fmap_fd ( * ctx - > fmap ) , cl_strerror ( res ) ) ;
cli_bitset_free ( ctx - > hook_lsig_matches ) ;
ctx - > hook_lsig_matches = old_hook_lsig_matches ;
return magic_scandesc_cleanup ( ctx , type , hash , hashed_size , cache_clean , res , parent_property ) ;
/* CL_VIRUS = malware found, check FP and report */
case CL_VIRUS :
ret = res ;
if ( SCAN_ALLMATCHES )
break ;
cli_bitset_free ( ctx - > hook_lsig_matches ) ;
ctx - > hook_lsig_matches = old_hook_lsig_matches ;
return magic_scandesc_cleanup ( ctx , type , hash , hashed_size , cache_clean , ret , parent_property ) ;
/* "MAX" conditions should still fully scan the current file */
case CL_EMAXREC :
case CL_EMAXSIZE :
case CL_EMAXFILES :
ret = res ;
cli_dbgmsg ( " Descriptor[%d]: Continuing after cli_scanraw reached %s \n " ,
fmap_fd ( * ctx - > fmap ) , cl_strerror ( res ) ) ;
2017-08-08 17:38:17 -04:00
break ;
2018-12-03 12:40:13 -05:00
/* Other errors must not block further scans below
2017-08-08 17:38:17 -04:00
* This specifically includes CL_EFORMAT & CL_EREAD & CL_EUNPACK
* Malformed / truncated files could report as any of these three .
*/
2018-12-03 12:40:13 -05:00
default :
ret = res ;
cli_dbgmsg ( " Descriptor[%d]: Continuing after cli_scanraw error %s \n " ,
fmap_fd ( * ctx - > fmap ) , cl_strerror ( res ) ) ;
2017-08-08 17:38:17 -04:00
}
}
2003-12-12 17:48:47 +00:00
}
2003-07-29 15:48:06 +00:00
2008-02-06 21:19:10 +00:00
ctx - > recursion + + ;
2018-12-03 12:40:13 -05:00
switch ( type ) {
/* bytecode hooks triggered by a lsig must be a hook
2017-08-08 17:38:17 -04:00
* called from one of the functions here */
2018-12-03 12:40:13 -05:00
case CL_TYPE_TEXT_ASCII :
case CL_TYPE_TEXT_UTF16BE :
case CL_TYPE_TEXT_UTF16LE :
case CL_TYPE_TEXT_UTF8 :
perf_nested_start ( ctx , PERFT_SCRIPT , PERFT_SCAN ) ;
if ( ( DCONF_DOC & DOC_CONF_SCRIPT ) & & dettype ! = CL_TYPE_HTML & & ( ret ! = CL_VIRUS | | SCAN_ALLMATCHES ) & & SCAN_PARSE_HTML )
ret = cli_scanscript ( ctx ) ;
if ( SCAN_PARSE_MAIL & & ( DCONF_MAIL & MAIL_CONF_MBOX ) & & ret ! = CL_VIRUS & & ( cli_get_container ( ctx , - 1 ) = = CL_TYPE_MAIL | | dettype = = CL_TYPE_MAIL ) ) {
ret = cli_fmap_scandesc ( ctx , CL_TYPE_MAIL , 0 , NULL , AC_SCAN_VIR , NULL , NULL ) ;
}
perf_nested_stop ( ctx , PERFT_SCRIPT , PERFT_SCAN ) ;
break ;
/* Due to performance reasons all executables were first scanned
2017-08-08 17:38:17 -04:00
* in raw mode . Now we will try to unpack them
*/
2018-12-03 12:40:13 -05:00
case CL_TYPE_MSEXE :
perf_nested_start ( ctx , PERFT_PE , PERFT_SCAN ) ;
if ( SCAN_PARSE_PE & & ctx - > dconf - > pe ) {
unsigned int corrupted_input = ctx - > corrupted_input ;
ret = cli_scanpe ( ctx ) ;
ctx - > corrupted_input = corrupted_input ;
}
perf_nested_stop ( ctx , PERFT_PE , PERFT_SCAN ) ;
break ;
case CL_TYPE_BINARY_DATA :
ret = cli_fmap_scandesc ( ctx , CL_TYPE_OTHER , 0 , NULL , AC_SCAN_VIR , NULL , NULL ) ;
break ;
default :
break ;
2004-07-11 14:50:25 +00:00
}
2010-02-15 02:02:54 +01:00
2008-02-06 21:19:10 +00:00
ctx - > recursion - - ;
2010-01-19 16:38:12 +02:00
cli_bitset_free ( ctx - > hook_lsig_matches ) ;
ctx - > hook_lsig_matches = old_hook_lsig_matches ;
2004-07-11 14:50:25 +00:00
2018-12-03 12:40:13 -05:00
switch ( ret ) {
/* Malformed file cases */
case CL_EFORMAT :
case CL_EREAD :
case CL_EUNPACK :
/* Limits exceeded */
case CL_EMAXREC :
case CL_EMAXSIZE :
case CL_EMAXFILES :
cli_dbgmsg ( " Descriptor[%d]: %s \n " , fmap_fd ( * ctx - > fmap ) , cl_strerror ( ret ) ) ;
2014-04-30 15:01:05 -04:00
# if HAVE_JSON
2018-12-03 12:40:13 -05:00
ctx - > wrkproperty = parent_property ;
2014-04-30 15:01:05 -04:00
# endif
2018-12-03 12:40:13 -05:00
return magic_scandesc_cleanup ( ctx , type , hash , hashed_size , cache_clean , CL_CLEAN , parent_property ) ;
case CL_CLEAN :
cache_clean = 1 ;
2014-04-30 15:01:05 -04:00
# if HAVE_JSON
2018-12-03 12:40:13 -05:00
ctx - > wrkproperty = parent_property ;
2014-04-30 15:01:05 -04:00
# endif
2018-12-03 12:40:13 -05:00
return magic_scandesc_cleanup ( ctx , type , hash , hashed_size , cache_clean , CL_CLEAN , parent_property ) ;
default :
return magic_scandesc_cleanup ( ctx , type , hash , hashed_size , cache_clean , ret , parent_property ) ;
2004-10-14 23:56:30 +00:00
}
2003-07-29 15:48:06 +00:00
}
2018-07-30 20:19:28 -04:00
static int cli_base_scandesc ( int desc , const char * filepath , cli_ctx * ctx , cli_file_t type )
2010-08-24 12:28:16 +02:00
{
2012-07-16 15:36:49 -04:00
STATBUF sb ;
2011-06-14 11:11:05 +03:00
int ret ;
2018-07-30 20:19:28 -04:00
const char * parent_filepath = ctx - > sub_filepath ;
2018-12-03 12:40:13 -05:00
ctx - > sub_filepath = filepath ;
2018-07-30 20:19:28 -04:00
2011-06-14 11:11:05 +03:00
# ifdef HAVE__INTERNAL__SHA_COLLECT
2017-08-08 17:38:17 -04:00
if ( ctx - > sha_collect > 0 )
ctx - > sha_collect = 0 ;
2011-06-14 11:11:05 +03:00
# endif
cli_dbgmsg ( " in cli_magic_scandesc (reclevel: %u/%u) \n " , ctx - > recursion , ctx - > engine - > maxreclevel ) ;
2018-12-03 12:40:13 -05:00
if ( FSTAT ( desc , & sb ) = = - 1 ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " magic_scandesc: Can't fstat descriptor %d \n " , desc ) ;
early_ret_from_magicscan ( CL_ESTAT ) ;
2011-06-14 11:11:05 +03:00
}
2018-12-03 12:40:13 -05:00
if ( sb . st_size < = 5 ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Small data (%u bytes) \n " , ( unsigned int ) sb . st_size ) ;
early_ret_from_magicscan ( CL_CLEAN ) ;
2011-06-14 11:11:05 +03:00
}
ctx - > fmap + + ;
perf_start ( ctx , PERFT_MAP ) ;
2018-12-03 12:40:13 -05:00
if ( ! ( * ctx - > fmap = fmap ( desc , 0 , sb . st_size ) ) ) {
2017-08-08 17:38:17 -04:00
cli_errmsg ( " CRITICAL: fmap() failed \n " ) ;
ctx - > fmap - - ;
perf_stop ( ctx , PERFT_MAP ) ;
early_ret_from_magicscan ( CL_EMEM ) ;
2011-06-14 11:11:05 +03:00
}
perf_stop ( ctx , PERFT_MAP ) ;
2013-09-17 16:45:48 -04:00
ret = magic_scandesc ( ctx , type ) ;
2011-06-14 11:11:05 +03:00
funmap ( * ctx - > fmap ) ;
ctx - > fmap - - ;
2018-07-30 20:19:28 -04:00
ctx - > sub_filepath = parent_filepath ;
2011-06-14 11:11:05 +03:00
return ret ;
2010-08-24 12:28:16 +02:00
}
2018-07-30 20:19:28 -04:00
int cli_magic_scandesc ( int desc , const char * filepath , cli_ctx * ctx )
2013-09-17 16:45:48 -04:00
{
2018-07-30 20:19:28 -04:00
return cli_base_scandesc ( desc , filepath , ctx , CL_TYPE_ANY ) ;
2013-09-17 16:45:48 -04:00
}
/* Have to keep partition typing separate */
2018-07-30 20:19:28 -04:00
int cli_partition_scandesc ( int desc , const char * filepath , cli_ctx * ctx )
2013-09-17 16:45:48 -04:00
{
2018-07-30 20:19:28 -04:00
return cli_base_scandesc ( desc , filepath , ctx , CL_TYPE_PART_ANY ) ;
2013-09-17 16:45:48 -04:00
}
2011-06-14 11:11:05 +03:00
int cli_magic_scandesc_type ( cli_ctx * ctx , cli_file_t type )
2010-08-24 12:28:16 +02:00
{
2011-06-14 11:11:05 +03:00
return magic_scandesc ( ctx , type ) ;
2010-08-24 12:28:16 +02:00
}
2018-12-03 12:40:13 -05:00
int cl_scandesc ( int desc , const char * filename , const char * * virname , unsigned long int * scanned , const struct cl_engine * engine , struct cl_scan_options * scanoptions )
2010-07-06 19:46:55 +02:00
{
2018-07-30 20:19:28 -04:00
return cl_scandesc_callback ( desc , filename , virname , scanned , engine , scanoptions , NULL ) ;
2010-07-06 19:46:55 +02:00
}
2013-11-08 17:10:43 -05:00
/* For map scans that may be forced to disk */
2014-01-23 17:03:47 -05:00
int cli_map_scan ( cl_fmap_t * map , off_t offset , size_t length , cli_ctx * ctx , cli_file_t type )
2013-11-08 17:10:43 -05:00
{
2018-12-03 12:40:13 -05:00
off_t old_off = map - > nested_offset ;
2013-11-08 17:10:43 -05:00
size_t old_len = map - > len ;
2018-12-03 12:40:13 -05:00
int ret = CL_CLEAN ;
2013-11-08 17:10:43 -05:00
cli_dbgmsg ( " cli_map_scan: [%ld, +%lu) \n " ,
2017-08-08 17:38:17 -04:00
( long ) offset , ( unsigned long ) length ) ;
2018-12-03 12:40:13 -05:00
if ( offset < 0 | | ( size_t ) offset > = old_len ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Invalid offset: %ld \n " , ( long ) offset ) ;
return CL_CLEAN ;
2013-11-08 17:10:43 -05:00
}
2018-12-03 12:40:13 -05:00
if ( ctx - > engine - > engine_options & ENGINE_OPTIONS_FORCE_TO_DISK ) {
2013-11-08 17:10:43 -05:00
/* if this is forced to disk, then need to write the nested map and scan it */
const uint8_t * mapdata = NULL ;
2018-12-03 12:40:13 -05:00
char * tempfile = NULL ;
int fd = - 1 ;
size_t nread = 0 ;
2013-11-08 17:10:43 -05:00
2013-12-11 15:30:40 -05:00
/* Then check length */
2017-08-08 17:38:17 -04:00
if ( ! length )
length = old_len - offset ;
2018-12-03 12:40:13 -05:00
if ( length > old_len - offset ) {
2013-12-11 15:30:40 -05:00
cli_dbgmsg ( " cli_map_scan: Data truncated: %lu -> %lu \n " ,
( unsigned long ) length , ( unsigned long ) ( old_len - offset ) ) ;
length = old_len - offset ;
}
2018-12-03 12:40:13 -05:00
if ( length < = 5 ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " cli_map_scan: Small data (%u bytes) \n " , ( unsigned int ) length ) ;
2013-12-11 15:30:40 -05:00
return CL_CLEAN ;
}
2018-12-03 12:40:13 -05:00
if ( ! CLI_ISCONTAINED ( old_off , old_len , old_off + offset , length ) ) {
2017-08-15 16:50:01 -04:00
cli_dbgmsg ( " cli_map_scan: map error occurred [%ld, %zu] \n " ,
( long ) old_off , old_len ) ;
2013-12-11 15:30:40 -05:00
return CL_CLEAN ;
}
/* Length checked, now get map */
2013-11-08 17:10:43 -05:00
mapdata = fmap_need_off_once_len ( map , offset , length , & nread ) ;
2018-12-03 12:40:13 -05:00
if ( ! mapdata | | ( nread ! = length ) ) {
2013-11-08 17:10:43 -05:00
cli_errmsg ( " cli_map_scan: could not map sub-file \n " ) ;
return CL_EMAP ;
}
ret = cli_gentempfd ( ctx - > engine - > tmpdir , & tempfile , & fd ) ;
2018-12-03 12:40:13 -05:00
if ( ret ! = CL_SUCCESS ) {
2013-11-08 17:10:43 -05:00
return ret ;
}
cli_dbgmsg ( " cli_map_scan: writing nested map content to temp file %s \n " , tempfile ) ;
2018-12-03 12:40:13 -05:00
if ( cli_writen ( fd , mapdata , length ) < 0 ) {
2013-11-08 17:10:43 -05:00
cli_errmsg ( " cli_map_scan: cli_writen error writing subdoc temporary file. \n " ) ;
ret = CL_EWRITE ;
}
/* scan the temp file */
2018-07-30 20:19:28 -04:00
ret = cli_base_scandesc ( fd , tempfile , ctx , type ) ;
2013-11-08 17:10:43 -05:00
/* remove the temp file, if needed */
2018-12-03 12:40:13 -05:00
if ( fd > = 0 ) {
2013-11-08 17:10:43 -05:00
close ( fd ) ;
}
2018-12-03 12:40:13 -05:00
if ( ! ctx - > engine - > keeptmp ) {
if ( cli_unlink ( tempfile ) ) {
2013-11-08 17:10:43 -05:00
cli_errmsg ( " cli_map_scan: error unlinking tempfile %s \n " , tempfile ) ;
ret = CL_EUNLINK ;
}
}
free ( tempfile ) ;
2018-12-03 12:40:13 -05:00
} else {
2013-11-08 17:10:43 -05:00
/* Not forced to disk, use nested map */
2014-01-23 17:03:47 -05:00
ret = cli_map_scandesc ( map , offset , length , ctx , type ) ;
2013-11-08 17:10:43 -05:00
}
return ret ;
}
/* For map scans that are not forced to disk */
2014-01-23 17:03:47 -05:00
int cli_map_scandesc ( cl_fmap_t * map , off_t offset , size_t length , cli_ctx * ctx , cli_file_t type )
2011-06-14 21:49:39 +03:00
{
2018-12-03 12:40:13 -05:00
off_t old_off = map - > nested_offset ;
size_t old_len = map - > len ;
2012-01-18 18:15:04 +02:00
size_t old_real_len = map - > real_len ;
2018-12-03 12:40:13 -05:00
int ret = CL_CLEAN ;
2011-06-14 21:49:39 +03:00
2013-02-19 15:56:26 -05:00
cli_dbgmsg ( " cli_map_scandesc: [%ld, +%lu), [%ld, +%lu) \n " ,
2017-08-08 17:38:17 -04:00
( long ) old_off , ( unsigned long ) old_len ,
( long ) offset , ( unsigned long ) length ) ;
2018-12-03 12:40:13 -05:00
if ( offset < 0 | | ( size_t ) offset > = old_len ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Invalid offset: %ld \n " , ( long ) offset ) ;
return CL_CLEAN ;
2011-06-17 23:08:31 +03:00
}
2017-08-08 17:38:17 -04:00
if ( ! length )
length = old_len - offset ;
2018-12-03 12:40:13 -05:00
if ( length > old_len - offset ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Data truncated: %zu -> %zu \n " ,
2018-12-03 12:40:13 -05:00
length , old_len - ( size_t ) offset ) ;
2017-08-08 17:38:17 -04:00
length = old_len - ( size_t ) offset ;
2011-06-17 23:08:31 +03:00
}
2018-12-03 12:40:13 -05:00
if ( length < = 5 ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " Small data (%u bytes) \n " , ( unsigned int ) length ) ;
return CL_CLEAN ;
2011-06-14 21:49:39 +03:00
}
ctx - > fmap + + ;
* ctx - > fmap = map ;
2011-06-17 23:08:31 +03:00
/* can't change offset because then we'd have to discard/move cached
* data , instead use another offset to reuse the already cached data */
map - > nested_offset + = offset ;
2018-12-03 12:40:13 -05:00
map - > len = length ;
2011-06-17 23:08:31 +03:00
map - > real_len = map - > nested_offset + length ;
2018-12-03 12:40:13 -05:00
if ( CLI_ISCONTAINED ( old_off , old_len , map - > nested_offset , map - > len ) ) {
2017-08-08 17:38:17 -04:00
ret = magic_scandesc ( ctx , type ) ;
2018-12-03 12:40:13 -05:00
} else {
2017-08-08 17:38:17 -04:00
long long len1 , len2 ;
len1 = old_off + old_len ;
2013-02-19 15:56:26 -05:00
len2 = map - > nested_offset + map - > len ;
2017-08-08 17:38:17 -04:00
cli_warnmsg ( " internal map error: %lu, %llu; %lu, %llu \n " , ( long unsigned ) old_off ,
( long long unsigned ) len1 , ( long unsigned ) map - > offset , ( long long unsigned ) len2 ) ;
2011-06-17 23:08:31 +03:00
}
2011-06-14 21:49:39 +03:00
2011-06-14 22:54:44 +03:00
ctx - > fmap - - ;
2011-06-17 23:08:31 +03:00
map - > nested_offset = old_off ;
2018-12-03 12:40:13 -05:00
map - > len = old_len ;
map - > real_len = old_real_len ;
2011-06-14 21:49:39 +03:00
return ret ;
}
2011-06-17 23:14:36 +03:00
int cli_mem_scandesc ( const void * buffer , size_t length , cli_ctx * ctx )
{
int ret ;
fmap_t * map = cl_fmap_open_memory ( buffer , length ) ;
2018-12-03 12:40:13 -05:00
if ( ! map ) {
2017-08-08 17:38:17 -04:00
return CL_EMAP ;
2011-06-17 23:14:36 +03:00
}
2014-01-23 17:03:47 -05:00
ret = cli_map_scan ( map , 0 , length , ctx , CL_TYPE_ANY ) ;
2011-06-17 23:14:36 +03:00
cl_fmap_close ( map ) ;
return ret ;
}
2018-07-30 20:19:28 -04:00
/**
* @ brief The main function to initiate a scan , that may be invoked with a file descriptor or a file map .
*
* @ param desc File descriptor of an open file . The caller must provide this or the map .
* @ param map File map . The caller must provide this or the desc .
* @ param filepath ( optional , recommended ) filepath of the open file descriptor or file map .
* @ param [ out ] virname Will be set to a statically allocated ( i . e . needs not be freed ) signature name if the scan matches against a signature .
* @ param [ out ] scanned The number of bytes scanned .
* @ param engine The scanning engine .
* @ param scanoptions Scanning options .
* @ param [ in / out ] context An opaque context structure allowing the caller to record details about the sample being scanned .
* @ return int CL_CLEAN , CL_VIRUS , or an error code if an error occured during the scan .
*/
2018-12-03 12:40:13 -05:00
static cl_error_t scan_common ( int desc , cl_fmap_t * map , const char * filepath , const char * * virname , unsigned long int * scanned , const struct cl_engine * engine , struct cl_scan_options * scanoptions , void * context )
2010-07-07 03:01:55 +02:00
{
cli_ctx ctx ;
int rc ;
2014-04-11 13:41:18 -04:00
STATBUF sb ;
2014-04-15 10:24:58 -04:00
/* We have a limit of around 2.17GB (INT_MAX - 2). Enforce it here. */
2018-12-03 12:40:13 -05:00
if ( map ! = NULL ) {
2014-04-15 10:24:58 -04:00
if ( ( size_t ) ( map - > real_len ) > ( size_t ) ( INT_MAX - 2 ) )
return CL_CLEAN ;
2018-12-03 12:40:13 -05:00
} else {
2014-04-11 13:41:18 -04:00
if ( FSTAT ( desc , & sb ) )
return CL_ESTAT ;
2014-04-15 10:24:58 -04:00
if ( ( size_t ) ( sb . st_size ) > ( size_t ) ( INT_MAX - 2 ) )
2014-04-11 13:41:18 -04:00
return CL_CLEAN ;
}
2010-07-07 03:01:55 +02:00
memset ( & ctx , ' \0 ' , sizeof ( cli_ctx ) ) ;
2018-12-03 12:40:13 -05:00
ctx . engine = engine ;
2010-07-07 03:01:55 +02:00
ctx . virname = virname ;
ctx . scanned = scanned ;
2018-07-20 22:28:48 -04:00
ctx . options = malloc ( sizeof ( struct cl_scan_options ) ) ;
memcpy ( ctx . options , scanoptions , sizeof ( struct cl_scan_options ) ) ;
2010-07-07 03:01:55 +02:00
ctx . found_possibly_unwanted = 0 ;
2018-12-03 12:40:13 -05:00
ctx . containers = cli_calloc ( sizeof ( cli_ctx_container ) , ctx . engine - > maxreclevel + 2 ) ;
2017-08-08 17:38:17 -04:00
if ( ! ctx . containers )
return CL_EMEM ;
2017-01-19 12:24:46 -05:00
cli_set_container ( & ctx , CL_TYPE_ANY , 0 ) ;
2018-12-03 12:40:13 -05:00
ctx . dconf = ( struct cli_dconf * ) engine - > dconf ;
2010-07-07 03:01:55 +02:00
ctx . cb_ctx = context ;
2018-12-03 12:40:13 -05:00
ctx . fmap = cli_calloc ( sizeof ( fmap_t * ) , ctx . engine - > maxreclevel + 2 ) ;
2017-08-08 17:38:17 -04:00
if ( ! ctx . fmap )
return CL_EMEM ;
2018-12-03 12:40:13 -05:00
if ( ! ( ctx . hook_lsig_matches = cli_bitset_init ( ) ) ) {
2017-08-08 17:38:17 -04:00
free ( ctx . fmap ) ;
return CL_EMEM ;
2010-07-07 03:01:55 +02:00
}
2011-02-14 19:19:20 +02:00
perf_init ( & ctx ) ;
2010-07-07 03:01:55 +02:00
2018-12-03 12:40:13 -05:00
if ( ctx . options - > general & CL_SCAN_GENERAL_COLLECT_METADATA & & ctx . engine - > time_limit ! = 0 ) {
if ( gettimeofday ( & ctx . time_limit , NULL ) = = 0 ) {
uint32_t secs = ctx . engine - > time_limit / 1000 ;
2014-06-13 16:11:15 -04:00
uint32_t usecs = ( ctx . engine - > time_limit % 1000 ) * 1000 ;
ctx . time_limit . tv_sec + = secs ;
ctx . time_limit . tv_usec + = usecs ;
2018-12-03 12:40:13 -05:00
if ( ctx . time_limit . tv_usec > = 1000000 ) {
2014-06-13 16:11:15 -04:00
ctx . time_limit . tv_usec - = 1000000 ;
ctx . time_limit . tv_sec + + ;
}
2018-12-03 12:40:13 -05:00
} else {
2014-06-13 16:11:15 -04:00
char buf [ 64 ] ;
cli_dbgmsg ( " scan_common; gettimeofday error: %s \n " , cli_strerror ( errno , buf , 64 ) ) ;
}
}
2018-07-30 20:19:28 -04:00
/* Best effort to determine the filename if not provided.
* May still be NULL if filename could not be determined . */
2018-12-03 12:40:13 -05:00
if ( filepath = = NULL ) {
2018-07-30 20:19:28 -04:00
char * fpath = NULL ;
2017-08-08 17:38:17 -04:00
2018-07-30 20:19:28 -04:00
if ( desc > = 0 ) {
2018-12-03 12:40:13 -05:00
( void ) cli_get_filepath_from_filedesc ( desc , & fpath ) ;
2017-08-08 17:38:17 -04:00
}
2018-07-30 20:19:28 -04:00
ctx . target_filepath = fpath ;
} else {
ctx . target_filepath = strdup ( filepath ) ;
2017-08-08 17:38:17 -04:00
}
2010-07-07 03:01:55 +02:00
2010-11-02 12:26:33 +02:00
cli_logg_setup ( & ctx ) ;
2018-12-03 12:40:13 -05:00
rc = map ? cli_map_scandesc ( map , 0 , map - > len , & ctx , CL_TYPE_ANY )
2018-07-30 20:19:28 -04:00
: cli_magic_scandesc ( desc , ctx . target_filepath , & ctx ) ;
2010-07-07 03:01:55 +02:00
2014-04-23 17:37:23 -04:00
# if HAVE_JSON
2018-12-03 12:40:13 -05:00
if ( ctx . options - > general & CL_SCAN_GENERAL_COLLECT_METADATA & & ( ctx . properties ! = NULL ) ) {
2014-06-30 11:44:02 -04:00
json_object * jobj ;
const char * jstring ;
/* set value of unique root object tag */
2018-12-03 12:40:13 -05:00
if ( json_object_object_get_ex ( ctx . properties , " FileType " , & jobj ) ) {
2014-06-30 11:44:02 -04:00
enum json_type type ;
const char * jstr ;
type = json_object_get_type ( jobj ) ;
2018-12-03 12:40:13 -05:00
if ( type = = json_type_string ) {
2014-06-30 11:44:02 -04:00
jstr = json_object_get_string ( jobj ) ;
cli_jsonstr ( ctx . properties , " RootFileType " , jstr ) ;
}
}
2014-06-03 13:31:50 -04:00
/* serialize json properties to string */
2014-06-30 11:44:02 -04:00
jstring = json_object_to_json_string ( ctx . properties ) ;
2018-12-03 12:40:13 -05:00
if ( NULL = = jstring ) {
2014-04-16 16:40:56 -04:00
cli_errmsg ( " scan_common: no memory for json serialization. \n " ) ;
2014-05-05 17:05:26 -04:00
rc = CL_EMEM ;
2018-12-03 12:40:13 -05:00
} else {
int ret = CL_SUCCESS ;
2016-05-17 16:44:21 -04:00
struct cli_matcher * iroot = ctx . engine - > root [ 13 ] ;
2014-06-03 13:31:50 -04:00
cli_dbgmsg ( " %s \n " , jstring ) ;
2015-01-15 15:15:01 -08:00
2018-12-03 12:40:13 -05:00
if ( rc ! = CL_VIRUS ) {
2015-03-04 12:08:34 -05:00
/* run bytecode preclass hook; generate fmap if needed for running hook */
2015-03-03 15:00:41 -05:00
struct cli_bc_ctx * bc_ctx = cli_bytecode_context_alloc ( ) ;
2018-12-03 12:40:13 -05:00
if ( ! bc_ctx ) {
2015-03-03 15:00:41 -05:00
cli_errmsg ( " scan_common: can't allocate memory for bc_ctx \n " ) ;
rc = CL_EMEM ;
2018-12-03 12:40:13 -05:00
} else {
2015-03-03 17:47:55 -05:00
fmap_t * pc_map = map ;
2018-12-03 12:40:13 -05:00
if ( ! pc_map ) {
2015-03-03 17:47:55 -05:00
perf_start ( & ctx , PERFT_MAP ) ;
2018-12-03 12:40:13 -05:00
if ( ! ( pc_map = fmap ( desc , 0 , sb . st_size ) ) ) {
2015-03-03 17:47:55 -05:00
perf_stop ( & ctx , PERFT_MAP ) ;
rc = CL_EMEM ;
}
perf_stop ( & ctx , PERFT_MAP ) ;
}
2018-12-03 12:40:13 -05:00
if ( pc_map ) {
2015-03-03 17:47:55 -05:00
cli_bytecode_context_setctx ( bc_ctx , & ctx ) ;
rc = cli_bytecode_runhook ( & ctx , ctx . engine , bc_ctx , BC_PRECLASS , pc_map ) ;
}
2018-11-14 16:58:30 -05:00
cli_bytecode_context_destroy ( bc_ctx ) ;
2015-03-03 15:00:41 -05:00
}
2015-03-04 12:08:34 -05:00
/* backwards compatibility: scan the json string unless a virus was detected */
2018-12-03 12:40:13 -05:00
if ( rc ! = CL_VIRUS & & ( iroot - > ac_lsigs | | iroot - > ac_patterns
2017-08-23 15:08:47 -04:00
# ifdef HAVE_PCRE
2018-12-03 12:40:13 -05:00
| | iroot - > pcre_metas
2017-08-23 15:08:47 -04:00
# endif
2018-12-03 12:40:13 -05:00
) ) {
2015-09-21 12:07:19 -04:00
cli_dbgmsg ( " scan_common: running deprecated preclass bytecodes for target type 13 \n " ) ;
2018-07-20 22:28:48 -04:00
ctx . options - > general & = ~ CL_SCAN_GENERAL_COLLECT_METADATA ;
2015-03-04 12:08:34 -05:00
rc = cli_mem_scandesc ( jstring , strlen ( jstring ) , & ctx ) ;
}
2014-06-03 13:31:50 -04:00
}
2014-05-05 17:05:26 -04:00
2014-06-03 13:31:50 -04:00
/* Invoke file props callback */
2018-12-03 12:40:13 -05:00
if ( ctx . engine - > cb_file_props ! = NULL ) {
2015-03-27 13:21:49 -04:00
ret = ctx . engine - > cb_file_props ( jstring , rc , ctx . cb_ctx ) ;
2014-06-03 13:31:50 -04:00
if ( ret ! = CL_SUCCESS )
rc = ret ;
}
/* keeptmp file processing for file properties json string */
2018-12-03 12:40:13 -05:00
if ( ctx . engine - > keeptmp ) {
int fd = - 1 ;
2017-08-08 17:38:17 -04:00
char * tmpname = NULL ;
2018-12-03 12:40:13 -05:00
if ( ( ret = cli_gentempfd ( ctx . engine - > tmpdir , & tmpname , & fd ) ) ! = CL_SUCCESS ) {
2014-06-03 13:31:50 -04:00
cli_dbgmsg ( " scan_common: Can't create json properties file, ret = %i. \n " , ret ) ;
2018-12-03 12:40:13 -05:00
} else {
2014-06-03 13:31:50 -04:00
if ( cli_writen ( fd , jstring , strlen ( jstring ) ) < 0 )
cli_dbgmsg ( " scan_common: cli_writen error writing json properties file. \n " ) ;
else
2014-06-13 11:21:59 -04:00
cli_dbgmsg ( " json written to: %s \n " , tmpname ) ;
2014-05-05 17:05:26 -04:00
}
2014-06-03 13:31:50 -04:00
if ( fd ! = - 1 )
close ( fd ) ;
if ( NULL ! = tmpname )
free ( tmpname ) ;
2014-05-05 17:05:26 -04:00
}
}
2016-05-10 18:43:42 -04:00
cli_json_delobj ( ctx . properties ) ; /* frees all json memory */
2014-06-13 16:11:15 -04:00
#if 0
// test code - to be deleted
if ( cli_checktimelimit ( & ctx ) ! = CL_SUCCESS ) {
cli_errmsg ( " scan_common: timeout! \n " ) ;
rc = CL_ETIMEOUT ;
}
# endif
2014-04-16 16:40:56 -04:00
}
# endif
2018-12-03 12:40:13 -05:00
if ( rc = = CL_CLEAN ) {
2018-07-20 22:28:48 -04:00
if ( ( ctx . found_possibly_unwanted ) | |
2018-12-03 12:40:13 -05:00
( ( ctx . num_viruses ! = 0 ) & &
( ( ctx . options - > general & CL_SCAN_GENERAL_ALLMATCHES ) | |
( ctx . options - > heuristic & CL_SCAN_HEURISTIC_EXCEEDS_MAX ) ) ) )
2017-08-08 17:38:17 -04:00
rc = CL_VIRUS ;
2015-10-01 17:47:37 -04:00
}
2018-07-20 22:28:48 -04:00
2018-07-30 20:19:28 -04:00
if ( NULL ! = ctx . target_filepath ) {
free ( ctx . target_filepath ) ;
}
2018-07-20 22:28:48 -04:00
free ( ctx . containers ) ;
cli_bitset_free ( ctx . hook_lsig_matches ) ;
free ( ctx . fmap ) ;
free ( ctx . options ) ;
2010-11-02 22:23:56 +02:00
cli_logg_unsetup ( ) ;
2011-02-14 19:19:20 +02:00
perf_done ( & ctx ) ;
2010-07-07 03:01:55 +02:00
return rc ;
}
2018-07-30 20:19:28 -04:00
int cl_scandesc_callback ( int desc , const char * filename , const char * * virname , unsigned long int * scanned , const struct cl_engine * engine , struct cl_scan_options * scanoptions , void * context )
2011-06-14 21:49:39 +03:00
{
2018-07-30 20:19:28 -04:00
return scan_common ( desc , NULL , filename , virname , scanned , engine , scanoptions , context ) ;
2011-06-14 21:49:39 +03:00
}
2018-07-30 20:19:28 -04:00
int cl_scanmap_callback ( cl_fmap_t * map , const char * filename , const char * * virname , unsigned long int * scanned , const struct cl_engine * engine , struct cl_scan_options * scanoptions , void * context )
2011-06-14 21:49:39 +03:00
{
2018-07-30 20:19:28 -04:00
return scan_common ( - 1 , map , filename , virname , scanned , engine , scanoptions , context ) ;
2011-06-14 21:49:39 +03:00
}
2017-08-08 17:38:17 -04:00
int cli_found_possibly_unwanted ( cli_ctx * ctx )
2008-07-31 10:51:46 +00:00
{
2018-12-03 12:40:13 -05:00
if ( cli_get_last_virus ( ctx ) ) {
2017-08-08 17:38:17 -04:00
cli_dbgmsg ( " found Possibly Unwanted: %s \n " , cli_get_last_virus ( ctx ) ) ;
2018-12-03 12:40:13 -05:00
if ( SCAN_HEURISTIC_PRECEDENCE ) {
2017-08-08 17:38:17 -04:00
/* we found a heuristic match, don't scan further,
* but consider it a virus . */
cli_dbgmsg ( " cli_found_possibly_unwanted: CL_VIRUS \n " ) ;
return CL_VIRUS ;
}
/* heuristic scan isn't taking precedence, keep scanning.
* If this is part of an archive , and
* we find a real malware we report that instead of the
* heuristic match */
ctx - > found_possibly_unwanted = 1 ;
2018-12-03 12:40:13 -05:00
} else {
2017-08-08 17:38:17 -04:00
cli_warnmsg ( " cli_found_possibly_unwanted called, but virname is not set \n " ) ;
2012-10-18 14:12:58 -07:00
}
emax_reached ( ctx ) ;
return CL_CLEAN ;
2008-07-31 10:51:46 +00:00
}
2006-02-15 00:41:40 +00:00
static int cli_scanfile ( const char * filename , cli_ctx * ctx )
2004-04-14 22:55:44 +00:00
{
2017-08-08 17:38:17 -04:00
int fd , ret ;
2004-04-14 22:55:44 +00:00
2004-07-04 14:56:48 +00:00
/* internal version of cl_scanfile with arec/mrec preserved */
2017-08-08 17:38:17 -04:00
if ( ( fd = safe_open ( filename , O_RDONLY | O_BINARY ) ) = = - 1 )
return CL_EOPEN ;
2004-04-14 22:55:44 +00:00
2018-07-30 20:19:28 -04:00
ret = cli_magic_scandesc ( fd , filename , ctx ) ;
2004-04-14 22:55:44 +00:00
close ( fd ) ;
return ret ;
}
2018-12-03 12:40:13 -05:00
int cl_scanfile ( const char * filename , const char * * virname , unsigned long int * scanned , const struct cl_engine * engine , struct cl_scan_options * scanoptions )
2003-07-29 15:48:06 +00:00
{
2010-11-02 12:26:33 +02:00
return cl_scanfile_callback ( filename , virname , scanned , engine , scanoptions , NULL ) ;
2003-07-29 15:48:06 +00:00
}
2008-05-27 16:30:47 +00:00
2018-12-03 12:40:13 -05:00
int cl_scanfile_callback ( const char * filename , const char * * virname , unsigned long int * scanned , const struct cl_engine * engine , struct cl_scan_options * scanoptions , void * context )
2010-07-06 19:46:55 +02:00
{
2017-08-08 17:38:17 -04:00
int fd , ret ;
const char * fname = cli_to_utf8_maybe_alloc ( filename ) ;
2010-07-06 19:46:55 +02:00
2017-08-08 17:38:17 -04:00
if ( ! fname )
return CL_EARG ;
2011-04-18 17:25:23 +02:00
2017-08-08 17:38:17 -04:00
if ( ( fd = safe_open ( fname , O_RDONLY | O_BINARY ) ) = = - 1 )
return CL_EOPEN ;
2010-07-06 19:46:55 +02:00
2017-08-08 17:38:17 -04:00
if ( fname ! = filename )
2018-07-30 20:19:28 -04:00
free ( ( char * ) fname ) ;
2011-04-18 17:25:23 +02:00
2018-07-30 20:19:28 -04:00
ret = cl_scandesc_callback ( fd , filename , virname , scanned , engine , scanoptions , context ) ;
2010-07-06 19:46:55 +02:00
close ( fd ) ;
return ret ;
}
2008-05-27 16:30:47 +00:00
/*
Local Variables :
c - basic - offset : 4
End :
*/