Use new patter matching algorithm. Cleanup.

git-svn: trunk@674
remotes/push_mirror/metadata
Tomasz Kojm 21 years ago
parent 3ba813bb6b
commit 8000d0786b
  1. 9
      clamav-devel/ChangeLog
  2. 2
      clamav-devel/clamav-config
  3. 3
      clamav-devel/clamd/clamd.c
  4. 4
      clamav-devel/clamd/scanner.c
  5. 6
      clamav-devel/clamd/server-th.c
  6. 16
      clamav-devel/clamscan/manager.c
  7. 8
      clamav-devel/examples/ex1.c
  8. 1
      clamav-devel/freshclam/freshclam.c
  9. 4
      clamav-devel/freshclam/manager.c
  10. 1
      clamav-devel/freshclam/notify.c
  11. 4
      clamav-devel/libclamav/Makefile.am
  12. 23
      clamav-devel/libclamav/Makefile.in
  13. 52
      clamav-devel/libclamav/clamav.h
  14. 4
      clamav-devel/libclamav/cvd.c
  15. 3
      clamav-devel/libclamav/dsig.c
  16. 2
      clamav-devel/libclamav/filetypes.c
  17. 2
      clamav-devel/libclamav/htmlnorm.c
  18. 352
      clamav-devel/libclamav/matcher-ac.c
  19. 29
      clamav-devel/libclamav/matcher-ac.h
  20. 149
      clamav-devel/libclamav/matcher-bm.c
  21. 29
      clamav-devel/libclamav/matcher-bm.h
  22. 412
      clamav-devel/libclamav/matcher.c
  23. 12
      clamav-devel/libclamav/matcher.h
  24. 7
      clamav-devel/libclamav/mbox.c
  25. 41
      clamav-devel/libclamav/others.c
  26. 9
      clamav-devel/libclamav/others.h
  27. 14
      clamav-devel/libclamav/pe.c
  28. 112
      clamav-devel/libclamav/readdb.c
  29. 2
      clamav-devel/libclamav/readdb.h
  30. 140
      clamav-devel/libclamav/scanners.c
  31. 6
      clamav-devel/libclamav/str.c
  32. 1
      clamav-devel/libclamav/str.h
  33. 2
      clamav-devel/libclamav/vba_extract.c
  34. 27
      clamav-devel/sigtool/sigtool.c

@ -1,3 +1,12 @@
Mon Jul 19 19:46:03 CEST 2004 (tk)
----------------------------------
* libclamav: use new, faster and memory efficient algorithm (multipattern
variant of Boyer-Moore) for static signature matching (not
yet fully optimised)
* libclamav: API: cl_build, cl_free succeed cl_buildtrie, cl_freetrie
(old functions still supported)
* all: minor cleanup; fix compilation warnings
Fri Jul 16 17:32:40 CEST 2004 (tk)
----------------------------------
* libclamav: scanners: fix memory leak in new code (thanks to Trog)

@ -46,7 +46,7 @@ while test $# -gt 0; do
;;
--version)
echo devel-20040706
echo devel-20040718
exit 0
;;

@ -68,7 +68,6 @@ void clamd(struct optstruct *opt)
struct cl_node *root = NULL;
const char *dbdir, *cfgfile;
int ret, virnum = 0, tcpsock;
char *var;
#ifdef C_LINUX
struct stat sb;
#endif
@ -269,7 +268,7 @@ void clamd(struct optstruct *opt)
}
logg("Protecting against %d viruses.\n", virnum);
if((ret = cl_buildtrie(root)) != 0) {
if((ret = cl_build(root)) != 0) {
fprintf(stderr, "ERROR: Database initialization error: %s\n", cl_strerror(ret));;
logg("!Database initialization error: %s\n", cl_strerror(ret));;
exit(1);

@ -43,6 +43,8 @@
#include "shared.h"
#include "output.h"
#include "../libclamav/others.h"
#ifdef C_LINUX
dev_t procdev; /* /proc device */
#endif
@ -229,7 +231,7 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root
while(!bound && portscan--) {
if((port = cl_rndnum(60000)) < 1024)
if((port = cli_rndnum(60000)) < 1024)
port += 2139;
memset((char *) &server, 0, sizeof(server));

@ -144,7 +144,7 @@ static struct cl_node *reload_db(struct cl_node *root, const struct cfgstruct *c
/* release old structure */
if(root) {
cl_freetrie(root);
cl_free(root);
root = NULL;
}
@ -173,8 +173,8 @@ static struct cl_node *reload_db(struct cl_node *root, const struct cfgstruct *c
exit(-1);
}
if((retval = cl_buildtrie(root)) != 0) {
logg("!Database initialization error: can't build the trie: %s\n",
if((retval = cl_build(root)) != 0) {
logg("!Database initialization error: can't build engine: %s\n",
cl_strerror(retval));
exit(-1);
}

@ -54,11 +54,14 @@
#include "memory.h"
#include "output.h"
#include "cfgparser.h"
#include "../libclamav/others.h"
#ifdef C_LINUX
dev_t procdev;
#endif
extern int cli_mbox(const char *dir, int desc); /* FIXME */
int scanmanager(const struct optstruct *opt)
{
mode_t fmode;
@ -154,8 +157,7 @@ int scanmanager(const struct optstruct *opt)
return 50;
}
/* build the proper trie */
if((ret=cl_buildtrie(trie)) != 0) {
if((ret = cl_build(trie)) != 0) {
mprintf("@Database initialization error: %s\n", cl_strerror(ret));;
return 50;
}
@ -243,7 +245,7 @@ int scanmanager(const struct optstruct *opt)
}
/* generate the temporary directory */
dir = cl_gentemp(tmpdir);
dir = cli_gentemp(tmpdir);
if(mkdir(dir, 0700)) {
mprintf("@Can't create the temporary directory %s\n", dir);
exit(63); /* critical */
@ -255,7 +257,7 @@ int scanmanager(const struct optstruct *opt)
/*
* Extract the attachments into the temporary directory
*/
ret = cl_mbox(dir, 0);
ret = cli_mbox(dir, 0);
if(ret == 0) {
/* fix permissions of extracted files */
@ -325,7 +327,7 @@ int scanmanager(const struct optstruct *opt)
}
/* free the trie */
cl_freetrie(trie);
cl_free(trie);
free(limits);
@ -566,7 +568,7 @@ int scancompressed(const char *filename, struct cl_node *root, const struct pass
/* generate the temporary directory */
gendir = cl_gentemp(tmpdir);
gendir = cli_gentemp(tmpdir);
if(mkdir(gendir, 0700)) {
mprintf("@Can't create the temporary directory %s\n", gendir);
exit(63); /* critical */
@ -759,7 +761,7 @@ int scandenied(const char *filename, struct cl_node *root, const struct passwd *
}
/* generate the temporary directory */
gendir = cl_gentemp(tmpdir);
gendir = cli_gentemp(tmpdir);
if(mkdir(gendir, 0700)) {
mprintf("@Can't create the temporary directory %s\n", gendir);
exit(63); /* critical */

@ -57,10 +57,10 @@ int main(int argc, char **argv)
printf("Loaded %d signatures.\n", no);
/* build the final trie */
if((ret = cl_buildtrie(root))) {
/* build engine */
if((ret = cl_build(root))) {
printf("Database initialization error: %s\n", cl_strerror(ret));;
cl_freetrie(root); /* free the partial trie */
cl_free(root);
close(fd);
exit(2);
}
@ -85,7 +85,7 @@ int main(int argc, char **argv)
mb = size * (CL_COUNT_PRECISION / 1024) / 1024.0;
printf("Data scanned: %2.2Lf Mb\n", mb);
cl_freetrie(root);
cl_free(root);
close(fd);
exit(ret == CL_VIRUS ? 1 : 0);

@ -28,6 +28,7 @@
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

@ -44,6 +44,8 @@
#include "manager.h"
#include "notify.h"
#include "memory.h"
#include "output.h"
#include "../libclamav/others.h"
int downloadmanager(const struct cfgstruct *copt, const struct optstruct *opt, const char *hostname)
{
@ -213,7 +215,7 @@ int downloaddb(const char *localname, const char *remotename, const char *hostna
/* temporary file is created in clamav's directory thus we don't need
* to create it immediately because race condition is not possible here
*/
tempname = cl_gentemp(".");
tempname = cli_gentemp(".");
if((ret = get_database(remotename, hostfd, tempname, hostname, proxy, user, pass))) {
mprintf("@Can't download %s from %s\n", remotename, ipaddr);

@ -34,6 +34,7 @@
#include "others.h"
#include "cfgparser.h"
#include "output.h"
int notify(const char *cfgfile)
{

@ -26,6 +26,10 @@ include_HEADERS = clamav.h
libclamav_la_SOURCES = \
clamav.h \
matcher-ac.c \
matcher-ac.h \
matcher-bm.c \
matcher-bm.h \
matcher.c \
matcher.h \
md5.c \

@ -72,13 +72,13 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"
libLTLIBRARIES_INSTALL = $(INSTALL)
LTLIBRARIES = $(lib_LTLIBRARIES)
libclamav_la_DEPENDENCIES =
am_libclamav_la_OBJECTS = matcher.lo md5.lo others.lo readdb.lo cvd.lo \
dsig.lo str.lo scanners.lo filetypes.lo unrarlib.lo \
zzip-dir.lo zzip-err.lo zzip-file.lo zzip-info.lo zzip-io.lo \
zzip-stat.lo zzip-zip.lo strc.lo blob.lo mbox.lo message.lo \
snprintf.lo strrcpy.lo table.lo text.lo ole2_extract.lo \
vba_extract.lo msexpand.lo pe.lo cabd.lo lzxd.lo mszipd.lo \
qtmd.lo system.lo upx.lo htmlnorm.lo
am_libclamav_la_OBJECTS = matcher-ac.lo matcher-bm.lo matcher.lo \
md5.lo others.lo readdb.lo cvd.lo dsig.lo str.lo scanners.lo \
filetypes.lo unrarlib.lo zzip-dir.lo zzip-err.lo zzip-file.lo \
zzip-info.lo zzip-io.lo zzip-stat.lo zzip-zip.lo strc.lo \
blob.lo mbox.lo message.lo snprintf.lo strrcpy.lo table.lo \
text.lo ole2_extract.lo vba_extract.lo msexpand.lo pe.lo \
cabd.lo lzxd.lo mszipd.lo qtmd.lo system.lo upx.lo htmlnorm.lo
libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
@ -86,7 +86,8 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/blob.Plo ./$(DEPDIR)/cabd.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/cvd.Plo ./$(DEPDIR)/dsig.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/filetypes.Plo ./$(DEPDIR)/htmlnorm.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/lzxd.Plo ./$(DEPDIR)/matcher.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/lzxd.Plo ./$(DEPDIR)/matcher-ac.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/matcher-bm.Plo ./$(DEPDIR)/matcher.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/mbox.Plo ./$(DEPDIR)/md5.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/message.Plo ./$(DEPDIR)/msexpand.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/mszipd.Plo \
@ -231,6 +232,10 @@ libclamav_la_LDFLAGS = @TH_SAFE@ -version-info @LIBCLAMAV_VERSION@
include_HEADERS = clamav.h
libclamav_la_SOURCES = \
clamav.h \
matcher-ac.c \
matcher-ac.h \
matcher-bm.c \
matcher-bm.h \
matcher.c \
matcher.h \
md5.c \
@ -382,6 +387,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filetypes.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htmlnorm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lzxd.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/matcher-ac.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/matcher-bm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/matcher.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbox.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Plo@am__quote@

@ -29,8 +29,6 @@ extern "C"
#endif
#define CL_NUM_CHILDS 256
#define CL_MIN_LENGTH 2
#define CL_COUNT_PRECISION 4096
@ -76,19 +74,27 @@ extern "C"
#define CL_HTML 32
#define CL_PE 64
struct cli_patt {
struct cli_bm_patt {
const char *pattern;
char *virname;
int length;
struct cli_bm_patt *next;
};
struct cli_ac_patt {
short int *pattern;
unsigned int length, mindist, maxdist;
char *virname;
unsigned short int sigid, parts, partno, type, alt, *altn;
char **altc;
struct cli_patt *next;
struct cli_ac_patt *next;
};
struct cli_ac_node {
char islast;
struct cli_patt *list;
struct cli_ac_node *trans[CL_NUM_CHILDS], *fail;
struct cli_ac_patt *list;
struct cli_ac_node *trans[256], *fail;
};
struct cli_md5_node {
@ -97,13 +103,18 @@ struct cli_md5_node {
};
struct cl_node {
/* Aho-Corasick */
struct cli_ac_node *ac_root, **nodetable;
unsigned int maxpatlen, partsigs;
unsigned int nodes;
unsigned int maxpatlen; /* maximal length of pattern in db */
/* Extended Boyer-Moore */
int *bm_shift;
struct cli_bm_patt **bm_suffix;
/* Extended Aho-Corasick */
struct cli_ac_node *ac_root, **ac_nodetable;
unsigned int ac_partsigs, ac_nodes;
/* MD5 */
struct cli_md5_node *hlist[256];
struct cli_md5_node **md5_hlist;
};
struct cl_limits {
@ -141,12 +152,13 @@ extern int cl_scandesc(int desc, const char **virname, unsigned long int *scanne
extern int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options);
/* database loading */
/* database */
extern int cl_loaddb(const char *filename, struct cl_node **root, int *virnum);
extern int cl_loaddbdir(const char *dirname, struct cl_node **root, int *virnum);
extern const char *cl_retdbdir(void);
extern int cl_retflevel(void);
/* CVD */
extern struct cl_cvd *cl_cvdhead(const char *file);
extern struct cl_cvd *cl_cvdparse(const char *head);
extern int cl_cvdverify(const char *file);
@ -162,24 +174,12 @@ extern void cl_debug(void);
extern void cl_settempdir(const char *dir, short leavetemps);
/* build a trie */
extern int cl_buildtrie(struct cl_node *root);
extern void cl_freetrie(struct cl_node *root);
extern int cl_build(struct cl_node *root);
extern void cl_free(struct cl_node *root);
extern const char *cl_strerror(int clerror);
extern const char *cl_perror(int clerror); /* deprecated */
extern char *cl_md5buff(const char *buffer, unsigned int length);
extern int cl_mbox(const char *dir, int desc);
/* compute MD5 message digest from file (compatible with md5sum(1)) */
extern char *cl_md5file(const char *filename);
/* generate unique file name in temporary directory */
char *cl_gentemp(const char *dir);
#ifdef __cplusplus
};
#endif

@ -342,7 +342,7 @@ int cli_cvdload(FILE *fd, struct cl_node **root, int *virnum)
tmpdir = "/tmp";
#endif
dir = cl_gentemp(tmpdir);
dir = cli_gentemp(tmpdir);
if(mkdir(dir, 0700)) {
cli_errmsg("cli_cvdload(): Can't create temporary directory %s\n", dir);
return CL_ETMPDIR;
@ -361,7 +361,7 @@ int cli_cvdload(FILE *fd, struct cl_node **root, int *virnum)
/* start */
tmp = cl_gentemp(tmpdir);
tmp = cli_gentemp(tmpdir);
if((tmpd = fopen(tmp, "wb+")) == NULL) {
cli_errmsg("Can't create temporary file %s\n", tmp);
free(dir);

@ -33,6 +33,7 @@
#include "clamav.h"
#include "others.h"
#include "dsig.h"
#include "str.h"
static const char *cli_nstr = "118640995551645342603070001658453189751527774412027743746599405743243142607464144767361060640655844749760788890022283424922762488917565551002467771109669598189410434699034532232228621591089508178591428456220796841621637175567590476666928698770143328137383952820383197532047771780196576957695822641224262693037"; /* 1024 bits */
@ -118,7 +119,7 @@ int cli_versig(const char *md5, const char *dsig)
return CL_EDSIG;
}
pt2 = cl_str2hex(pt, 16);
pt2 = cli_str2hex(pt, 16);
free(pt);
cli_dbgmsg("Decoded signature: %s\n", pt2);

@ -27,6 +27,8 @@
#include "clamav.h"
#include "filetypes.h"
#include "others.h"
#include "readdb.h"
struct cli_magic_s {
int offset;

@ -21,6 +21,8 @@
#endif
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

@ -0,0 +1,352 @@
/*
* C implementation of the Aho-Corasick pattern matching algorithm. It's based
* on ScannerDaemon's Java version by Kurt Huwig and
* http://www-sr.informatik.uni-tuebingen.de/~buehler/AC/AC.html
* Thanks to Kurt Huwig for pointing me to this page.
*
* Copyright (C) 2002 - 2004 Tomasz Kojm <tkojm@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "clamav.h"
#include "others.h"
#include "matcher-ac.h"
#include "unrarlib.h"
#include "defaults.h"
#include "filetypes.h"
#define AC_MIN_LENGTH 2
struct nodelist {
struct cli_ac_node *node;
struct nodelist *next;
};
int cli_ac_addpatt(struct cl_node *root, struct cli_ac_patt *pattern)
{
struct cli_ac_node *pos, *next;
int i;
if(pattern->length < AC_MIN_LENGTH)
return CL_EPATSHORT;
pos = root->ac_root;
for(i = 0; i < AC_MIN_LENGTH; i++) {
next = pos->trans[((unsigned char) pattern->pattern[i]) & 0xff];
if(!next) {
next = (struct cli_ac_node *) cli_calloc(1, sizeof(struct cli_ac_node));
if(!next) {
cli_dbgmsg("Unable to allocate pattern node (%d)\n", sizeof(struct cl_node));
return CL_EMEM;
}
root->ac_nodes++;
root->ac_nodetable = (struct cli_ac_node **) cli_realloc(root->ac_nodetable, (root->ac_nodes) * sizeof(struct cli_ac_node *));
if(root->ac_nodetable == NULL) {
cli_dbgmsg("Unable to realloc nodetable (%d)\n", (root->ac_nodes) * sizeof(struct cl_node *));
return CL_EMEM;
}
root->ac_nodetable[root->ac_nodes - 1] = next;
pos->trans[((unsigned char) pattern->pattern[i]) & 0xff] = next;
}
pos = next;
}
pos->islast = 1;
pattern->next = pos->list;
pos->list = pattern;
return 0;
}
static int cli_enqueue(struct nodelist **bfs, struct cli_ac_node *n)
{
struct nodelist *new;
new = (struct nodelist *) cli_calloc(1, sizeof(struct nodelist));
if (new == NULL) {
cli_dbgmsg("Unable to allocate node list (%d)\n", sizeof(struct nodelist));
return CL_EMEM;
}
new->next = *bfs;
new->node = n;
*bfs = new;
return 0;
}
static struct cli_ac_node *cli_dequeue(struct nodelist **bfs)
{
struct nodelist *handler, *prev = NULL;
struct cli_ac_node *pt;
handler = *bfs;
while(handler && handler->next) {
prev = handler;
handler = handler->next;
}
if(!handler) {
return NULL;
} else {
pt = handler->node;
free(handler);
if(prev)
prev->next = NULL;
else
*bfs = NULL;
return pt;
}
}
static int cli_maketrans(struct cl_node *root)
{
struct nodelist *bfs = NULL;
struct cli_ac_node *ac_root = root->ac_root, *child, *node;
int i, ret;
ac_root->fail = NULL;
if((ret = cli_enqueue(&bfs, ac_root)) != 0) {
return ret;
}
while((node = cli_dequeue(&bfs))) {
if(node->islast)
continue;
for(i = 0; i < 256; i++) {
child = node->trans[i];
if(!child) {
if(node->fail)
node->trans[i] = (node->fail)->trans[i];
else
node->trans[i] = ac_root;
} else {
if(node->fail)
child->fail = (node->fail)->trans[i];
else
child->fail = ac_root;
if((ret = cli_enqueue(&bfs, child)) != 0) {
return ret;
}
}
}
}
return 0;
}
int cli_ac_buildtrie(struct cl_node *root)
{
int ret;
if(!root)
return CL_EMALFDB;
if(!root->ac_root) {
cli_dbgmsg("Pattern matcher not initialised\n");
return 0;
}
if((ret = cli_addtypesigs(root)))
return ret;
return cli_maketrans(root);
}
static void cli_freepatt(struct cli_ac_patt *list)
{
struct cli_ac_patt *handler, *prev;
int i;
handler = list;
while(handler) {
free(handler->pattern);
free(handler->virname);
if(handler->alt) {
free(handler->altn);
for(i = 0; i < handler->alt; i++)
free(handler->altc[i]);
free(handler->altc);
}
prev = handler;
handler = handler->next;
free(prev);
}
}
void cli_ac_free(struct cl_node *root)
{
unsigned int i;
for(i = 0; i < root->ac_nodes; i++) {
cli_freepatt(root->ac_nodetable[i]->list);
free(root->ac_nodetable[i]);
}
if(root->ac_nodetable)
free(root->ac_nodetable);
if(root->ac_root)
free(root->ac_root);
}
static int inline cli_findpos(const char *buffer, int offset, int length, const struct cli_ac_patt *pattern)
{
int bufferpos = offset + AC_MIN_LENGTH;
int postfixend = offset + length;
unsigned int i, j, alt = 0, found = 0;
if(bufferpos >= length)
bufferpos %= length;
for(i = AC_MIN_LENGTH; i < pattern->length; i++) {
if(bufferpos == postfixend)
return 0;
if(pattern->pattern[i] == CLI_ALT) {
for(j = 0; j < pattern->altn[alt]; j++) {
if(pattern->altc[alt][j] == buffer[bufferpos])
found = 1;
}
if(!found)
return 0;
alt++;
} else if(pattern->pattern[i] != CLI_IGN && (char) pattern->pattern[i] != buffer[bufferpos])
return 0;
bufferpos++;
if(bufferpos == length)
bufferpos = 0;
}
return 1;
}
int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root, int *partcnt, int typerec, unsigned long int offset, unsigned long int *partoff)
{
struct cli_ac_node *current;
struct cli_ac_patt *pt;
int position, type = CL_CLEAN, dist;
unsigned int i;
if(!root->ac_root) {
cli_dbgmsg("cli_ac_scanbuff: Pattern matcher not initialised\n");
return CL_CLEAN;
}
if(!partcnt || !partoff) {
cli_dbgmsg("cli_ac_scanbuff(): partcnt == NULL || partoff == NULL\n");
return CL_ENULLARG;
}
current = root->ac_root;
for(i = 0; i < length; i++) {
current = current->trans[(unsigned char) buffer[i] & 0xff];
if(current->islast) {
position = i - AC_MIN_LENGTH + 1;
pt = current->list;
while(pt) {
if(cli_findpos(buffer, position, length, pt)) {
if(pt->sigid) { /* it's a partial signature */
if(partcnt[pt->sigid] + 1 == pt->partno) {
dist = 1;
if(pt->maxdist)
if(offset + i - partoff[pt->sigid] > pt->maxdist)
dist = 0;
if(dist && pt->mindist)
if(offset + i - partoff[pt->sigid] < pt->mindist)
dist = 0;
if(dist) {
partoff[pt->sigid] = offset + i + pt->length;
if(++partcnt[pt->sigid] == pt->parts) { /* the last one */
if(pt->type) {
if(typerec) {
if(pt->type > type) {
cli_dbgmsg("Matched signature for file type: %s\n", pt->virname);
type = pt->type;
}
}
} else {
if(virname)
*virname = pt->virname;
return CL_VIRUS;
}
}
}
}
} else { /* old type signature */
if(pt->type) {
if(typerec) {
if(pt->type > type) {
cli_dbgmsg("Matched signature for file type: %s\n", pt->virname);
type = pt->type;
}
}
} else {
if(virname)
*virname = pt->virname;
return CL_VIRUS;
}
}
}
pt = pt->next;
}
current = current->fail;
}
}
return typerec ? type : CL_CLEAN;
}

@ -0,0 +1,29 @@
/*
* Copyright (C) 2002 - 2004 Tomasz Kojm <tkojm@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MATCHER_AC_H
#define __MATCHER_AC_H
#include "clamav.h"
int cli_ac_addpatt(struct cl_node *root, struct cli_ac_patt *pattern);
int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root, int *partcnt, int typerec, unsigned long int offset, unsigned long int *partoff);
int cli_ac_buildtrie(struct cl_node *root);
void cli_ac_free(struct cl_node *root);
#endif

@ -0,0 +1,149 @@
/*
* Copyright (C) 2004 Tomasz Kojm <tkojm@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "clamav.h"
#include "memory.h"
#include "others.h"
#include "cltypes.h"
#define BM_MIN_LENGTH 10
#define BM_BLOCK_SIZE 3
#define MIN(a,b) (a < b) ? a : b
int cli_bm_addpatt(struct cl_node *root, struct cli_bm_patt *pattern)
{
int i;
uint16_t idx;
const char *pt = pattern->pattern;
struct cli_bm_patt *prev, *next = NULL;
if(pattern->length < BM_MIN_LENGTH) {
cli_dbgmsg("Ignoring signature for %s (too short)\n", pattern->virname);
/* return CL_EPATSHORT; */
}
for(i = BM_MIN_LENGTH - BM_BLOCK_SIZE; i >= 0; i--) {
idx = 211 * ((unsigned char) pt[i]) + 37 * ((unsigned char) pt[i + 1]) + (unsigned char) pt[i + 2];
root->bm_shift[idx] = MIN(root->bm_shift[idx], BM_MIN_LENGTH - BM_BLOCK_SIZE - i);
}
i = BM_MIN_LENGTH - BM_BLOCK_SIZE;
idx = 211 * ((unsigned char) pt[i]) + 37 * ((unsigned char) pt[i + 1]) + (unsigned char) pt[i + 2];
prev = next = root->bm_suffix[idx];
while(next) {
if(next->pattern[0] >= pt[0])
break;
prev = next;
next = next->next;
}
if(prev == root->bm_suffix[idx]) {
pattern->next = root->bm_suffix[idx];
root->bm_suffix[idx] = pattern;
} else {
pattern->next = prev->next;
prev->next = pattern;
}
return 0;
}
int cli_bm_init(struct cl_node *root)
{
int i;
cli_dbgmsg("in cli_bm_init()\n");
if(!(root->bm_shift = (int *) cli_malloc(65536 * sizeof(int))))
return CL_EMEM;
if(!(root->bm_suffix = (struct cli_bm_patt **) cli_calloc(65536, sizeof(struct cli_bm_patt *)))) {
free(root->bm_shift);
return CL_EMEM;
}
for(i = 0; i < 65536; i++)
root->bm_shift[i] = BM_MIN_LENGTH - BM_BLOCK_SIZE + 1;
return 0;
}
void cli_bm_free(struct cl_node *root)
{
if(root->bm_shift)
free(root->bm_shift);
if(root->bm_suffix)
free(root->bm_suffix);
}
int cli_bm_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root)
{
int i, j, shift, off, found;
uint16_t idx;
struct cli_bm_patt *p;
const char *bp;
char prefix;
for(i = BM_MIN_LENGTH - BM_BLOCK_SIZE; i < length; ) {
idx = 211 * ((unsigned char) buffer[i]) + 37 * ((unsigned char) buffer[i + 1]) + (unsigned char) buffer[i + 2];
shift = root->bm_shift[idx];
if(shift == 0) {
prefix = buffer[i - BM_MIN_LENGTH + BM_BLOCK_SIZE];
p = root->bm_suffix[idx];
while(p && p->pattern[0] != prefix)
p = p->next;
while(p && p->pattern[0] == prefix) {
off = i - BM_MIN_LENGTH + BM_BLOCK_SIZE;
bp = buffer + off;
found = 1;
for(j = 0; j < p->length && off < length; j++, off++) {
if(bp[j] != p->pattern[j]) {
found = 0;
break;
}
}
if(found && p->length == j) {
if(virname)
*virname = p->virname;
return CL_VIRUS;
}
p = p->next;
}
shift = 1;
}
i += shift;
}
return 0;
}

@ -0,0 +1,29 @@
/*
* Copyright (C) 2004 Tomasz Kojm <tkojm@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MATCHER_BM_H
#define __MATCHER_BM_H
#include "clamav.h"
int cli_bm_addpatt(struct cl_node *root, struct cli_bm_patt *pattern);
int cli_bm_init(struct cl_node *root);
int cli_bm_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root);
void cli_bm_free(struct cl_node *root);
#endif

@ -1,9 +1,4 @@
/*
* C implementation of the Aho-Corasick pattern matching algorithm. It's based
* on ScannerDaemon's Java version by Kurt Huwig and
* http://www-sr.informatik.uni-tuebingen.de/~buehler/AC/AC.html
* Thanks to Kurt Huwig for pointing me to this page.
*
* Copyright (C) 2002 - 2004 Tomasz Kojm <tkojm@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
@ -25,345 +20,212 @@
#include "clamav-config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "clamav.h"
#include "others.h"
#include "matcher.h"
#include "unrarlib.h"
#include "defaults.h"
#include "matcher-ac.h"
#include "matcher-bm.h"
#include "md5.h"
#include "filetypes.h"
int cli_addpatt(struct cl_node *root, struct cli_patt *pattern)
{
struct cli_ac_node *pos, *next;
int i;
if(pattern->length < CL_MIN_LENGTH) {
return CL_EPATSHORT;
}
pos = root->ac_root;
#define MD5_BLOCKSIZE 4096
for(i = 0; i < CL_MIN_LENGTH; i++) {
next = pos->trans[((unsigned char) pattern->pattern[i]) & 0xff];
if(!next) {
next = (struct cli_ac_node *) cli_calloc(1, sizeof(struct cli_ac_node));
if(!next) {
cli_dbgmsg("Unable to allocate pattern node (%d)\n", sizeof(struct cl_node));
return CL_EMEM;
}
root->nodes++;
root->nodetable = (struct cli_ac_node **) realloc(root->nodetable, (root->nodes) * sizeof(struct cli_ac_node *));
if (root->nodetable == NULL) {
cli_dbgmsg("Unable to realloc nodetable (%d)\n", (root->nodes) * sizeof(struct cl_node *));
return CL_EMEM;
}
root->nodetable[root->nodes - 1] = next;
int cl_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root)
{
int ret, *partcnt;
unsigned long int *partoff;
pos->trans[((unsigned char) pattern->pattern[i]) & 0xff] = next;
}
pos = next;
if((partcnt = (int *) cli_calloc(root->ac_partsigs + 1, sizeof(int))) == NULL) {
cli_dbgmsg("cl_scanbuff(): unable to cli_calloc(%d, %d)\n", root->ac_partsigs + 1, sizeof(int));
return CL_EMEM;
}
pos->islast = 1;
pattern->next = pos->list;
pos->list = pattern;
return 0;
}
static int cli_enqueue(struct nodelist **bfs, struct cli_ac_node *n)
{
struct nodelist *new;
new = (struct nodelist *) cli_calloc(1, sizeof(struct nodelist));
if (new == NULL) {
cli_dbgmsg("Unable to allocate node list (%d)\n", sizeof(struct nodelist));
if((partoff = (unsigned long int *) cli_calloc(root->ac_partsigs + 1, sizeof(unsigned long int))) == NULL) {
cli_dbgmsg("cl_scanbuff(): unable to cli_calloc(%d, %d)\n", root->ac_partsigs + 1, sizeof(unsigned long int));
free(partcnt);
return CL_EMEM;
}
new->next = *bfs;
new->node = n;
*bfs = new;
return 0;
if((ret = cli_bm_scanbuff(buffer, length, virname, root)) != CL_VIRUS)
ret = cli_ac_scanbuff(buffer, length, virname, root, partcnt, 0, 0, partoff);
free(partcnt);
free(partoff);
return ret;
}
static struct cli_ac_node *cli_dequeue(struct nodelist **bfs)
static struct cli_md5_node *cli_vermd5(const char *md5, const struct cl_node *root)
{
struct nodelist *handler, *prev = NULL;
struct cli_ac_node *pt;
handler = *bfs;
struct cli_md5_node *pt;
while(handler && handler->next) {
prev = handler;
handler = handler->next;
}
if(!handler) {
if(!(pt = root->md5_hlist[md5[0] & 0xff]))
return NULL;
} else {
pt = handler->node;
free(handler);
if(prev)
prev->next = NULL;
else
*bfs = NULL;
return pt;
}
}
static int cli_maketrans(struct cl_node *root)
{
struct nodelist *bfs = NULL;
struct cli_ac_node *ac_root = root->ac_root, *child, *node;
int i, ret;
while(pt) {
if(!memcmp(pt->md5, md5, 16))
return pt;
ac_root->fail = NULL;
if((ret = cli_enqueue(&bfs, ac_root)) != 0) {
return ret;
pt = pt->next;
}
while((node = cli_dequeue(&bfs))) {
if(node->islast)
continue;
for(i = 0; i < CL_NUM_CHILDS; i++) {
child = node->trans[i];
if(!child) {
if(node->fail)
node->trans[i] = (node->fail)->trans[i];
else
node->trans[i] = ac_root;
} else {
if(node->fail)
child->fail = (node->fail)->trans[i];
else
child->fail = ac_root;
if((ret = cli_enqueue(&bfs, child)) != 0) {
return ret;
}
}
}
}
return 0;
return NULL;
}
int cl_buildtrie(struct cl_node *root)
int cli_scandesc(int desc, const char **virname, long int *scanned, const struct cl_node *root, int typerec)
{
int ret;
char *buffer, *buff, *endbl, *pt;
int bytes, buffsize, length, ret, *partcnt, type = CL_CLEAN;
unsigned long int *partoff, offset = 0;
struct md5_ctx ctx;
unsigned char md5buff[16];
struct cli_md5_node *md5_node;
if(!root)
return CL_EMALFDB;
if(!root->ac_root) {
cli_dbgmsg("Pattern matcher not initialised\n");
return 0;
if(!root) {
cli_errmsg("cli_scandesc: root == NULL\n");
return CL_ENULLARG;
}
if((ret = cli_addtypesigs(root)))
return ret;
/* prepare the buffer */
buffsize = root->maxpatlen + SCANBUFF;
if(!(buffer = (char *) cli_calloc(buffsize, sizeof(char)))) {
cli_dbgmsg("cli_scandesc(): unable to cli_malloc(%d)\n", buffsize);
return CL_EMEM;
}
return cli_maketrans(root);
}
if((partcnt = (int *) cli_calloc(root->ac_partsigs + 1, sizeof(int))) == NULL) {
cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%d, %d)\n", root->ac_partsigs + 1, sizeof(int));
free(buffer);
return CL_EMEM;
}
static void cli_freepatt(struct cli_patt *list)
{
struct cli_patt *handler, *prev;
int i;
if((partoff = (unsigned long int *) cli_calloc(root->ac_partsigs + 1, sizeof(unsigned long int))) == NULL) {
cli_dbgmsg("cli_scanbuff(): unable to cli_calloc(%d, %d)\n", root->ac_partsigs + 1, sizeof(unsigned long int));
free(buffer);
free(partcnt);
return CL_EMEM;
}
if(root->md5_hlist)
md5_init_ctx (&ctx);
handler = list;
buff = buffer;
buff += root->maxpatlen; /* pointer to read data block */
endbl = buff + SCANBUFF - root->maxpatlen; /* pointer to the last block
* length of root->maxpatlen
*/
while(handler) {
free(handler->pattern);
free(handler->virname);
if(handler->alt) {
free(handler->altn);
for(i = 0; i < handler->alt; i++)
free(handler->altc[i]);
free(handler->altc);
}
prev = handler;
handler = handler->next;
free(prev);
}
}
pt= buff;
length = SCANBUFF;
while((bytes = read(desc, buff, SCANBUFF)) > 0) {
void cl_freetrie(struct cl_node *root)
{
unsigned int i;
if(scanned)
*scanned += bytes / CL_COUNT_PRECISION;
if(bytes < SCANBUFF)
length -= SCANBUFF - bytes;
for(i = 0; i < root->nodes; i++) {
cli_freepatt(root->nodetable[i]->list);
free(root->nodetable[i]);
}
if(cli_bm_scanbuff(pt, length, virname, root) == CL_VIRUS ||
(ret = cli_ac_scanbuff(pt, length, virname, root, partcnt, typerec, offset, partoff)) == CL_VIRUS) {
free(buffer);
free(partcnt);
free(partoff);
return CL_VIRUS;
free(root->nodetable);
free(root->ac_root);
free(root);
}
} else if(typerec && ret >= CL_TYPENO) {
if(ret >= type)
type = ret;
}
int inline cli_findpos(const char *buffer, int offset, int length, const struct cli_patt *pattern)
{
int bufferpos = offset + CL_MIN_LENGTH;
int postfixend = offset + length;
unsigned int i, j, alt = 0, found = 0;
if(bytes == SCANBUFF) {
memmove(buffer, endbl, root->maxpatlen);
offset += bytes - root->maxpatlen;
}
pt = buffer;
length = buffsize;
if(bufferpos >= length)
bufferpos %= length;
/* compute MD5 */
for(i = CL_MIN_LENGTH; i < pattern->length; i++) {
if(root->md5_hlist) {
if(bytes % 64 == 0) {
md5_process_block(buff, bytes, &ctx);
} else {
int block = bytes;
char *mpt = buff;
if(bufferpos == postfixend)
return 0;
while(block >= MD5_BLOCKSIZE) {
md5_process_block(mpt, MD5_BLOCKSIZE, &ctx);
mpt += MD5_BLOCKSIZE;
block -= MD5_BLOCKSIZE;
}
if(pattern->pattern[i] == CLI_ALT) {
for(j = 0; j < pattern->altn[alt]; j++) {
if(pattern->altc[alt][j] == buffer[bufferpos])
found = 1;
if(block)
md5_process_bytes(mpt, block, &ctx);
}
}
}
if(!found)
return 0;
alt++;
} else if(pattern->pattern[i] != CLI_IGN && (char) pattern->pattern[i] != buffer[bufferpos])
return 0;
free(buffer);
free(partcnt);
free(partoff);
bufferpos++;
if(root->md5_hlist) {
md5_finish_ctx(&ctx, &md5buff);
if(bufferpos == length)
bufferpos = 0;
if((md5_node = cli_vermd5(md5buff, root))) {
if(virname)
*virname = md5_node->virname;
return CL_VIRUS;
}
}
return 1;
return typerec ? type : CL_CLEAN;
}
int cli_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root, int *partcnt, int typerec, unsigned long int offset, unsigned long int *partoff)
int cl_build(struct cl_node *root)
{
struct cli_ac_node *current;
struct cli_patt *pt;
int position, type = CL_CLEAN, dist;
unsigned int i;
return cli_ac_buildtrie(root);
}
void cl_free(struct cl_node *root)
{
int i;
struct cli_md5_node *pt, *h;
if(!root->ac_root) {
cli_dbgmsg("cli_scanbuff: Pattern matcher not initialised\n");
return CL_CLEAN;
}
if(!partcnt || !partoff) {
cli_dbgmsg("cli_scanbuff(): partcnt == NULL || partoff == NULL\n");
return CL_EMEM;
if(!root) {
cli_errmsg("cl_free: root == NULL\n");
return;
}
current = root->ac_root;
for(i = 0; i < length; i++) {
current = current->trans[(unsigned char) buffer[i] & 0xff];
if(current->islast) {
position = i - CL_MIN_LENGTH + 1;
pt = current->list;
while(pt) {
if(cli_findpos(buffer, position, length, pt)) {
if(pt->sigid) { /* it's a partial signature */
if(partcnt[pt->sigid] + 1 == pt->partno) {
dist = 1;
if(pt->maxdist)
if(offset + i - partoff[pt->sigid] > pt->maxdist)
dist = 0;
if(dist && pt->mindist)
if(offset + i - partoff[pt->sigid] < pt->mindist)
dist = 0;
if(dist) {
partoff[pt->sigid] = offset + i + pt->length;
if(++partcnt[pt->sigid] == pt->parts) { /* the last one */
if(pt->type) {
if(typerec) {
if(pt->type > type) {
cli_dbgmsg("Matched signature for file type: %s\n", pt->virname);
type = pt->type;
}
}
} else {
if(virname)
*virname = pt->virname;
return CL_VIRUS;
}
}
}
}
} else { /* old type signature */
if(pt->type) {
if(typerec) {
if(pt->type > type) {
cli_dbgmsg("Matched signature for file type: %s\n", pt->virname);
type = pt->type;
}
}
} else {
if(virname)
*virname = pt->virname;
return CL_VIRUS;
}
}
}
cli_ac_free(root);
cli_bm_free(root);
if(root->md5_hlist) {
for(i = 0; i < 256; i++) {
while((pt = root->md5_hlist[i])) {
h = pt;
pt = pt->next;
free(h);
}
current = current->fail;
}
free(root->md5_hlist);
}
return typerec ? type : CL_CLEAN;
free(root);
}
int cl_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root)
int cl_buildtrie(struct cl_node *root) /* for backward compatibility */
{
int ret, *partcnt;
unsigned long int *partoff;
if((partcnt = (int *) cli_calloc(root->partsigs + 1, sizeof(int))) == NULL) {
cli_dbgmsg("cli_scanbuff(): unable to cli_calloc(%d, %d)\n", root->partsigs + 1, sizeof(int));
return CL_EMEM;
}
if((partoff = (unsigned long int *) cli_calloc(root->partsigs + 1, sizeof(unsigned long int))) == NULL) {
cli_dbgmsg("cli_scanbuff(): unable to cli_calloc(%d, %d)\n", root->partsigs + 1, sizeof(unsigned long int));
free(partcnt);
return CL_EMEM;
}
ret = cli_scanbuff(buffer, length, virname, root, partcnt, 0, 0, partoff);
return cl_build(root);
}
free(partcnt);
free(partoff);
return ret;
void cl_freetrie(struct cl_node *root) /* for backward compatibility */
{
return cl_free(root);
}

@ -21,16 +21,6 @@
#include "clamav.h"
struct nodelist {
struct cli_ac_node *node;
struct nodelist *next;
};
int cli_addpatt(struct cl_node *root, struct cli_patt *pattern);
struct nodelist *cli_bfsadd(struct nodelist *bfs, struct cl_node *n);
void cli_failtrans(struct cl_node *root);
void cli_fasttrie(struct cl_node *n, struct cl_node *root);
int cli_findpos(const char *buffer, int offset, int length, const struct cli_patt *pattern);
int cli_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root, int *partcnt, int typerec, unsigned long int offset, unsigned long int *partoff);
int cli_scandesc(int desc, const char **virname, long int *scanned, const struct cl_node *root, int typerec);
#endif

@ -17,6 +17,9 @@
*
* Change History:
* $Log: mbox.c,v $
* Revision 1.87 2004/07/19 17:54:40 kojm
* Use new patter matching algorithm. Cleanup.
*
* Revision 1.86 2004/07/06 09:32:45 nigelhorne
* Better handling of Gibe.3 boundary exploit
*
@ -246,7 +249,7 @@
* Compilable under SCO; removed duplicate code with message.c
*
*/
static char const rcsid[] = "$Id: mbox.c,v 1.86 2004/07/06 09:32:45 nigelhorne Exp $";
static char const rcsid[] = "$Id: mbox.c,v 1.87 2004/07/19 17:54:40 kojm Exp $";
#if HAVE_CONFIG_H
#include "clamav-config.h"
@ -428,7 +431,7 @@ static table_t *rfc821Table, *subtypeTable;
* TODO: create parseEmail which calls parseEmailHeaders then parseEmailBody
*/
int
cl_mbox(const char *dir, int desc)
cli_mbox(const char *dir, int desc)
{
int retcode, i;
message *m, *body;

@ -41,7 +41,7 @@
#ifdef CL_THREAD_SAFE
# include <pthread.h>
pthread_mutex_t cl_gentemp_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t cli_gentemp_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
#include "clamav.h"
@ -163,20 +163,13 @@ const char *cl_perror(int clerror)
return cl_strerror(clerror);
}
char *cl_md5file(const char *filename)
char *cli_md5stream(FILE *fd)
{
FILE *fd;
unsigned char buffer[16];
char *md5str;
int i, cnt=0;
if((fd = fopen(filename, "rb")) == NULL) {
cli_errmsg("md5_file(): Can't read file %s\n", filename);
return NULL;
}
md5_stream(fd, &buffer);
fclose(fd);
md5str = (char*) calloc(32 + 1, sizeof(char));
@ -186,13 +179,21 @@ char *cl_md5file(const char *filename)
return(md5str);
}
char *cli_md5stream(FILE *fd)
char *cli_md5file(const char *filename)
{
FILE *fd;
unsigned char buffer[16];
char *md5str;
int i, cnt=0;
if((fd = fopen(filename, "rb")) == NULL) {
cli_errmsg("cli_md5file(): Can't read file %s\n", filename);
return NULL;
}
md5_stream(fd, &buffer);
fclose(fd);
md5str = (char*) calloc(32 + 1, sizeof(char));
@ -202,7 +203,7 @@ char *cli_md5stream(FILE *fd)
return(md5str);
}
char *cl_md5buff(const char *buffer, unsigned int len)
static char *cli_md5buff(const char *buffer, unsigned int len)
{
unsigned char md5buff[16];
char *md5str;
@ -264,7 +265,7 @@ void *cli_realloc(void *ptr, size_t size)
} else return alloc;
}
unsigned int cl_rndnum(unsigned int max)
unsigned int cli_rndnum(unsigned int max)
{
struct timeval tv;
@ -292,7 +293,7 @@ void cl_settempdir(const char *dir, short leavetemps)
cli_leavetemps_flag = leavetemps;
}
char *cl_gentemp(const char *dir)
char *cli_gentemp(const char *dir)
{
char *name, *tmp;
const char *mdir;
@ -308,28 +309,28 @@ char *cl_gentemp(const char *dir)
name = (char*) cli_calloc(strlen(mdir) + 1 + 16 + 1 + 7, sizeof(char));
if(name == NULL) {
cli_dbgmsg("cl_gentemp('%s'): out of memory\n", dir);
cli_dbgmsg("cli_gentemp('%s'): out of memory\n", dir);
return NULL;
}
#ifdef CL_THREAD_SAFE
pthread_mutex_lock(&cl_gentemp_mutex);
pthread_mutex_lock(&cli_gentemp_mutex);
#endif
memcpy(salt, oldmd5buff, 16);
do {
for(i = 16; i < 48; i++)
salt[i] = cl_rndnum(255);
salt[i] = cli_rndnum(255);
tmp = cl_md5buff(( char* ) salt, 48);
tmp = cli_md5buff(( char* ) salt, 48);
sprintf(name, "%s/clamav-", mdir);
strncat(name, tmp, 16);
free(tmp);
} while(stat(name, &foo) != -1);
#ifdef CL_THREAD_SAFE
pthread_mutex_unlock(&cl_gentemp_mutex);
pthread_mutex_unlock(&cli_gentemp_mutex);
#endif
return(name);
@ -456,11 +457,13 @@ int cli_writen(int fd, void *buff, unsigned int count)
int32_t cli_readint32(const char *buff)
{
int32_t ret, shift, i = 0;
int32_t ret;
#if WORDS_BIGENDIAN == 0
ret = *(int32_t *) buff;
#else
int32_t shift, i = 0;
ret = 0;
for(shift = 0; shift < 32; shift += 8) {
ret |= (buff[i] & 0xff ) << shift;

@ -1,5 +1,5 @@
/*
* Copyright (C) 1999-2002 Tomasz Kojm <zolw@konarski.edu.pl>
* Copyright (C) 1999 - 2004 Tomasz Kojm <tk@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,8 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __OTHERS_H
#define __OTHERS_H
#ifndef __OTHERS_H_LC
#define __OTHERS_H_LC
#include <stdio.h>
#include <stdlib.h>
@ -34,5 +34,8 @@ char *cli_md5stream(FILE *fd);
int cli_readn(int fd, void *buff, unsigned int count);
int cli_writen(int fd, void *buff, unsigned int count);
int32_t cli_readint32(const char *buff);
char *cli_gentemp(const char *dir);
unsigned int cli_rndnum(unsigned int max);
char *cli_md5file(const char *filename);
#endif

@ -229,7 +229,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
uint16_t nsections;
uint32_t e_lfanew; /* address of new exe header */
uint32_t ep; /* entry point (raw) */
uint32_t timestamp;
time_t timestamp;
struct pe_image_file_hdr file_hdr;
struct pe_image_optional_hdr optional_hdr;
struct pe_image_section_hdr *section_hdr;
@ -313,8 +313,8 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
nsections = EC16(file_hdr.NumberOfSections);
cli_dbgmsg("NumberOfSections: %d\n", nsections);
timestamp = EC32(file_hdr.TimeDateStamp);
cli_dbgmsg("TimeDateStamp: %s", ctime((time_t *) &timestamp));
timestamp = (time_t) EC32(file_hdr.TimeDateStamp);
cli_dbgmsg("TimeDateStamp: %s", ctime(&timestamp));
cli_dbgmsg("SizeOfOptionalHeader: %d\n", EC16(file_hdr.SizeOfOptionalHeader));
@ -396,7 +396,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
cli_dbgmsg("Section contains free space\n");
/*
cli_dbgmsg("Dumping %d bytes\n", section_hdr.SizeOfRawData - section_hdr.VirtualSize);
ddump(desc, section_hdr.PointerToRawData + section_hdr.VirtualSize, section_hdr.SizeOfRawData - section_hdr.VirtualSize, cl_gentemp(NULL));
ddump(desc, section_hdr.PointerToRawData + section_hdr.VirtualSize, section_hdr.SizeOfRawData - section_hdr.VirtualSize, cli_gentemp(NULL));
*/
}
@ -410,7 +410,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
int ptrd = section_hdr.PointerToRawData & ~(optional_hdr.FileAlignment - 1);
cli_dbgmsg("WinZip section\n");
ddump(desc, ptrd, section_hdr.SizeOfRawData, cl_gentemp(NULL));
ddump(desc, ptrd, section_hdr.SizeOfRawData, cli_gentemp(NULL));
}
*/
@ -528,7 +528,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
}
if(upxfn) {
int ret, skew = cli_readint32(buff + 2) - EC32(optional_hdr.ImageBase) - EC32(section_hdr[i+1].VirtualAddress);
int skew = cli_readint32(buff + 2) - EC32(optional_hdr.ImageBase) - EC32(section_hdr[i+1].VirtualAddress);
if(buff[1] != '\xbe' || skew <= 0 || skew > 0x2e ) { /* FIXME: legit skews?? */
skew = 0;
@ -580,7 +580,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
int ndesc;
if(cli_leavetemps_flag) {
tempfile = cl_gentemp(NULL);
tempfile = cli_gentemp(NULL);
if((ndesc = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
cli_dbgmsg("UPX: Can't create file %s\n", tempfile);
free(section_hdr);

@ -33,20 +33,22 @@
#include "clamav.h"
#include "cvd.h"
#include "strings.h"
#include "matcher.h"
#include "matcher-ac.h"
#include "matcher-bm.h"
#include "others.h"
#include "str.h"
#include "defaults.h"
/* TODO: clean up the code */
static int cli_addsig(struct cl_node *root, const char *virname, const char *hexsig, int sigid, int parts, int partno, int type, unsigned int mindist, unsigned int maxdist)
{
struct cli_patt *new;
struct cli_ac_patt *new;
char *pt, *hex;
int virlen, ret, i, error = 0;
if((new = (struct cli_patt *) cli_calloc(1, sizeof(struct cli_patt))) == NULL)
if((new = (struct cli_ac_patt *) cli_calloc(1, sizeof(struct cli_ac_patt))) == NULL)
return CL_EMEM;
new->type = type;
@ -200,7 +202,7 @@ static int cli_addsig(struct cl_node *root, const char *virname, const char *hex
strncpy(new->virname, virname, virlen);
if((ret = cli_addpatt(root, new))) {
if((ret = cli_ac_addpatt(root, new))) {
free(new->virname);
if(new->alt) {
free(new->altn);
@ -219,9 +221,9 @@ static int cli_addsig(struct cl_node *root, const char *virname, const char *hex
return 0;
}
int cli_parse_add(struct cl_node *root, char *virname, const char *hexsig, int type)
int cli_parse_add(struct cl_node *root, const char *virname, const char *hexsig, int type)
{
struct cli_patt *new;
struct cli_bm_patt *bm_new;
char *pt, *hexcpy, *start, *n;
int ret, virlen, parts = 0, i, len;
int mindist = 0, maxdist = 0, error = 0;
@ -229,12 +231,11 @@ int cli_parse_add(struct cl_node *root, char *virname, const char *hexsig, int t
if(strchr(hexsig, '{')) {
root->partsigs++;
root->ac_partsigs++;
if(!(hexcpy = strdup(hexsig)))
return CL_EMEM;
len = strlen(hexsig);
for(i = 0; i < len; i++)
if(hexsig[i] == '{')
@ -251,7 +252,7 @@ int cli_parse_add(struct cl_node *root, char *virname, const char *hexsig, int t
*pt++ = 0;
}
if((ret = cli_addsig(root, virname, start, root->partsigs, parts, i, type, mindist, maxdist))) {
if((ret = cli_addsig(root, virname, start, root->ac_partsigs, parts, i, type, mindist, maxdist))) {
cli_errmsg("cli_parse_add(): Problem adding signature.\n");
error = 1;
break;
@ -303,14 +304,14 @@ int cli_parse_add(struct cl_node *root, char *virname, const char *hexsig, int t
return CL_EMALFDB;
} else if(strchr(hexsig, '*')) {
root->partsigs++;
root->ac_partsigs++;
len = strlen(hexsig);
for(i = 0; i < len; i++)
if(hexsig[i] == '*')
parts++;
if(parts) /* there's always one part more */
if(parts)
parts++;
for(i = 1; i <= parts; i++) {
@ -319,7 +320,7 @@ int cli_parse_add(struct cl_node *root, char *virname, const char *hexsig, int t
return CL_EMALFDB;
}
if((ret = cli_addsig(root, virname, pt, root->partsigs, parts, i, type, 0, 0))) {
if((ret = cli_addsig(root, virname, pt, root->ac_partsigs, parts, i, type, 0, 0))) {
cli_errmsg("cli_parse_add(): Problem adding signature.\n");
free(pt);
return ret;
@ -328,9 +329,44 @@ int cli_parse_add(struct cl_node *root, char *virname, const char *hexsig, int t
free(pt);
}
} else { /* static */
} else if(strpbrk(hexsig, "?(") || type) {
if((ret = cli_addsig(root, virname, hexsig, 0, 0, 0, type, 0, 0))) {
cli_errmsg("cli_parse_add(): Problem adding signature.\n");
cli_errmsg("cli_parse_add(): Problem adding signature\n");
return ret;
}
} else {
bm_new = (struct cli_bm_patt *) calloc(1, sizeof(struct cli_bm_patt));
if(!bm_new)
return CL_EMEM;
if(!(bm_new->pattern = cli_hex2str(hexsig)))
return CL_EMALFDB;
bm_new->length = strlen(hexsig) / 2;
if((pt = strstr(virname, "(Clam)")))
virlen = strlen(virname) - strlen(pt) - 1;
else
virlen = strlen(virname);
if(virlen <= 0) {
free(bm_new);
return CL_EMALFDB;
}
if((bm_new->virname = cli_calloc(virlen + 1, sizeof(char))) == NULL) {
free(bm_new);
return CL_EMEM;
}
strncpy(bm_new->virname, virname, virlen);
if(bm_new->length > root->maxpatlen)
root->maxpatlen = bm_new->length;
if((ret = cli_bm_addpatt(root, bm_new))) {
cli_errmsg("cli_parse_add(): Problem adding signature\n");
return ret;
}
}
@ -356,10 +392,19 @@ static int cli_loaddb(FILE *fd, struct cl_node **root, int *virnum)
(*root)->ac_root = (struct cli_ac_node *) cli_calloc(1, sizeof(struct cli_ac_node));
if(!(*root)->ac_root) {
free(*root);
cli_errmsg("Can't initialise AC pattern matcher\n");
return CL_EMEM;
}
}
if(!(*root)->bm_shift) {
cli_dbgmsg("Initializing BM tables\n");
if((ret = cli_bm_init(*root))) {
cli_errmsg("Can't initialise BM pattern matcher\n");
return ret;
}
}
while(fgets(buffer, FILEBUFF, fd)) {
line++;
cli_chomp(buffer);
@ -385,12 +430,12 @@ static int cli_loaddb(FILE *fd, struct cl_node **root, int *virnum)
if(!line) {
cli_errmsg("Empty database file\n");
/* FIXME: release memory */
cl_free(*root);
return CL_EMALFDB;
}
if(ret) {
/* FIXME: release memory */
cl_free(*root);
return ret;
}
@ -402,7 +447,7 @@ static int cli_loaddb(FILE *fd, struct cl_node **root, int *virnum)
static int cli_loadhdb(FILE *fd, struct cl_node **root, int *virnum)
{
char buffer[FILEBUFF], *pt, *start;
char buffer[FILEBUFF], *pt;
int line = 0, ret = 0;
struct cli_md5_node *new;
@ -448,18 +493,27 @@ static int cli_loadhdb(FILE *fd, struct cl_node **root, int *virnum)
new->viralias = cli_strtok(buffer, 1, ":"); /* aliases are optional */
new->next = (*root)->hlist[new->md5[0] & 0xff];
(*root)->hlist[new->md5[0] & 0xff] = new;
if(!(*root)->md5_hlist) {
cli_dbgmsg("Initializing md5 list structure\n");
(*root)->md5_hlist = (struct cli_md5_node **) cli_calloc(256, sizeof(struct cli_md5_node *));
if(!(*root)->md5_hlist) {
ret = CL_EMEM;
break;
}
}
new->next = (*root)->md5_hlist[new->md5[0] & 0xff];
(*root)->md5_hlist[new->md5[0] & 0xff] = new;
}
if(!line) {
cli_errmsg("Empty database file\n");
/* FIXME: release memory */
cl_free(*root);
return CL_EMALFDB;
}
if(ret) {
/* FIXME: release memory */
cl_free(*root);
return ret;
}
@ -583,7 +637,12 @@ int cl_statinidir(const char *dirname, struct cl_stat *dbstat)
if(dent->d_ino)
#endif
{
if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") && (cli_strbcasestr(dent->d_name, ".db") || cli_strbcasestr(dent->d_name, ".db2") || cli_strbcasestr(dent->d_name, ".db3") || cli_strbcasestr(dent->d_name, ".hdb") || cli_strbcasestr(dent->d_name, ".cvd"))) {
if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") &&
(cli_strbcasestr(dent->d_name, ".db") ||
cli_strbcasestr(dent->d_name, ".db2") ||
cli_strbcasestr(dent->d_name, ".db3") ||
cli_strbcasestr(dent->d_name, ".hdb") ||
cli_strbcasestr(dent->d_name, ".cvd"))) {
dbstat->no++;
dbstat->stattab = (struct stat *) realloc(dbstat->stattab, dbstat->no * sizeof(struct stat));
@ -625,7 +684,12 @@ int cl_statchkdir(const struct cl_stat *dbstat)
if(dent->d_ino)
#endif
{
if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") && (cli_strbcasestr(dent->d_name, ".db") || cli_strbcasestr(dent->d_name, ".db2") || cli_strbcasestr(dent->d_name, ".db3") || cli_strbcasestr(dent->d_name, ".hdb") || cli_strbcasestr(dent->d_name, ".cvd"))) {
if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") &&
(cli_strbcasestr(dent->d_name, ".db") ||
cli_strbcasestr(dent->d_name, ".db2") ||
cli_strbcasestr(dent->d_name, ".db3") ||
cli_strbcasestr(dent->d_name, ".hdb") ||
cli_strbcasestr(dent->d_name, ".cvd"))) {
fname = cli_calloc(strlen(dbstat->dir) + strlen(dent->d_name) + 2, sizeof(char));
sprintf(fname, "%s/%s", dbstat->dir, dent->d_name);
@ -666,7 +730,7 @@ int cl_statfree(struct cl_stat *dbstat)
dbstat->dir = NULL;
}
} else {
cli_errmsg("cl_statfree(): Null argument passed.\n");
cli_errmsg("cl_statfree(): Null argument passed\n");
return CL_ENULLARG;
}

@ -19,6 +19,6 @@
#ifndef __READDB_H
#define __READDB_H
int cli_parse_add(struct cl_node *root, char *virname, const char *hexsig, int type);
int cli_parse_add(struct cl_node *root, const char *virname, const char *hexsig, int type);
#endif

@ -47,8 +47,12 @@ int cli_scanrar_inuse = 0;
extern short cli_leavetemps_flag;
extern int cli_mbox(const char *dir, int desc); /* FIXME */
#include "clamav.h"
#include "others.h"
#include "matcher-ac.h"
#include "matcher-bm.h"
#include "matcher.h"
#include "unrarlib.h"
#include "ole2_extract.h"
@ -57,7 +61,6 @@ extern short cli_leavetemps_flag;
#include "pe.h"
#include "filetypes.h"
#include "htmlnorm.h"
#include "md5.h"
#ifdef HAVE_ZLIB_H
#include <zlib.h>
@ -78,131 +81,11 @@ extern short cli_leavetemps_flag;
#define MAX_MAIL_RECURSION 15
#define MD5_BLOCKSIZE 4096
static int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *arec, int *mrec);
static int cli_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *arec, int *mrec);
struct cli_md5_node *cli_vermd5(const char *md5, const struct cl_node *root)
{
struct cli_md5_node *pt;
if(!(pt = root->hlist[md5[0] & 0xff]))
return NULL;
while(pt) {
if(!memcmp(pt->md5, md5, 16))
return pt;
pt = pt->next;
}
return NULL;
}
static int cli_scandesc(int desc, const char **virname, long int *scanned, const struct cl_node *root, int typerec)
{
char *buffer, *buff, *endbl, *pt;
int bytes, buffsize, length, ret, *partcnt, type = CL_CLEAN;
unsigned long int *partoff, offset = 0;
struct md5_ctx ctx;
unsigned char md5buff[16];
struct cli_md5_node *md5_node;
/* prepare the buffer */
buffsize = root->maxpatlen + SCANBUFF;
if(!(buffer = (char *) cli_calloc(buffsize, sizeof(char)))) {
cli_dbgmsg("cli_scandesc(): unable to cli_malloc(%d)\n", buffsize);
return CL_EMEM;
}
if((partcnt = (int *) cli_calloc(root->partsigs + 1, sizeof(int))) == NULL) {
cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%d, %d)\n", root->partsigs + 1, sizeof(int));
free(buffer);
return CL_EMEM;
}
if((partoff = (unsigned long int *) cli_calloc(root->partsigs + 1, sizeof(unsigned long int))) == NULL) {
cli_dbgmsg("cli_scanbuff(): unable to cli_calloc(%d, %d)\n", root->partsigs + 1, sizeof(unsigned long int));
free(buffer);
free(partcnt);
return CL_EMEM;
}
md5_init_ctx (&ctx);
buff = buffer;
buff += root->maxpatlen; /* pointer to read data block */
endbl = buff + SCANBUFF - root->maxpatlen; /* pointer to the last block
* length of root->maxpatlen
*/
pt= buff;
length = SCANBUFF;
while((bytes = read(desc, buff, SCANBUFF)) > 0) {
if(scanned != NULL)
*scanned += bytes / CL_COUNT_PRECISION;
if(bytes < SCANBUFF)
length -= SCANBUFF - bytes;
if((ret = cli_scanbuff(pt, length, virname, root, partcnt, typerec, offset, partoff)) == CL_VIRUS) {
free(buffer);
free(partcnt);
free(partoff);
return ret;
} else if(typerec && ret >= CL_TYPENO) {
if(ret >= type)
type = ret;
}
if(bytes == SCANBUFF) {
memmove(buffer, endbl, root->maxpatlen);
offset += bytes - root->maxpatlen;
}
pt = buffer;
length = buffsize;
/* compute MD5 */
if(bytes % 64 == 0) {
md5_process_block(buff, bytes, &ctx);
} else {
int block = bytes;
char *mpt = buff;
while(block >= MD5_BLOCKSIZE) {
md5_process_block(mpt, MD5_BLOCKSIZE, &ctx);
mpt += MD5_BLOCKSIZE;
block -= MD5_BLOCKSIZE;
}
if(block)
md5_process_bytes(mpt, block, &ctx);
}
}
free(buffer);
free(partcnt);
free(partoff);
md5_finish_ctx(&ctx, &md5buff);
if((md5_node = cli_vermd5(md5buff, root))) {
if(virname)
*virname = md5_node->virname;
return CL_VIRUS;
}
return typerec ? type : CL_CLEAN;
}
#ifdef CL_THREAD_SAFE
static void cli_unlock_mutex(void *mtx)
{
@ -738,7 +621,7 @@ static int cli_scanmscab(int desc, const char **virname, long int *scanned, cons
for(cab = base; cab; cab = cab->next) {
for(file = cab->files; file; file = file->next) {
tempname = cl_gentemp(tmpdir);
tempname = cli_gentemp(tmpdir);
cli_dbgmsg("Extracting data to %s\n", tempname);
if(cabd->extract(cabd, file, tempname)) {
cli_dbgmsg("libmscab error code: %d\n", cabd->last_error(cabd));
@ -781,7 +664,6 @@ static int cli_scanhtml(int desc, const char **virname, long int *scanned, const
return CL_CLEAN;
#endif
#ifdef HAVE_MMAP
/* TODO: do file operations if mmap fails */
if(membuff == MAP_FAILED) {
cli_dbgmsg("mmap failed\n");
@ -807,7 +689,6 @@ static int cli_scanhtml(int desc, const char **virname, long int *scanned, const
free(newbuff);
return ret;
#endif
}
static int cli_scandir(const char *dirname, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *arec, int *mrec)
@ -1001,7 +882,7 @@ static int cli_scanole2(int desc, const char **virname, long int *scanned, const
#endif
/* generate the temporary directory */
dir = cl_gentemp(tmpdir);
dir = cli_gentemp(tmpdir);
if(mkdir(dir, 0700)) {
cli_dbgmsg("ScanOLE2 -> Can't create temporary directory %s\n", dir);
return CL_ETMPDIR;
@ -1042,7 +923,7 @@ static int cli_scanmail(int desc, const char **virname, long int *scanned, const
#endif
/* generate the temporary directory */
dir = cl_gentemp(tmpdir);
dir = cli_gentemp(tmpdir);
if(mkdir(dir, 0700)) {
cli_dbgmsg("ScanMail -> Can't create temporary directory %s\n", dir);
return CL_ETMPDIR;
@ -1051,7 +932,7 @@ static int cli_scanmail(int desc, const char **virname, long int *scanned, const
/*
* Extract the attachments into the temporary directory
*/
ret = cl_mbox(dir, desc);
ret = cli_mbox(dir, desc);
/* FIXME: check mbox return code */
ret = cli_scandir(dir, virname, scanned, root, limits, options, arec, mrec);
@ -1164,7 +1045,7 @@ static int cli_magic_scandesc(int desc, const char **virname, long int *scanned,
type = CL_UNKNOWN_TYPE;
}
case CL_UNKNOWN_TYPE:
default:
break;
}
@ -1209,6 +1090,9 @@ static int cli_magic_scandesc(int desc, const char **virname, long int *scanned,
if(SCAN_PE)
ret = cli_scanpe(desc, virname, scanned, root, limits, options, arec, mrec);
break;
default:
break;
}
(*arec)--;

@ -55,7 +55,7 @@ short int *cli_hex2si(const char *hex)
len = strlen(hex);
if(len % 2 != 0) {
cli_errmsg("cl_hex2si(): Malformed hexstring: %s (length: %d)\n", hex, len);
cli_errmsg("cli_hex2si(): Malformed hexstring: %s (length: %d)\n", hex, len);
return NULL;
}
@ -99,7 +99,7 @@ char *cli_hex2str(const char *hex)
len = strlen(hex);
if(len % 2 != 0) {
cli_errmsg("cl_hex2str(): Malformed hexstring: %s (length: %d)\n", hex, len);
cli_errmsg("cli_hex2str(): Malformed hexstring: %s (length: %d)\n", hex, len);
return NULL;
}
@ -129,7 +129,7 @@ char *cli_hex2str(const char *hex)
return str;
}
char *cl_str2hex(const char *string, unsigned int len)
char *cli_str2hex(const char *string, unsigned int len)
{
char *hexstr;
char HEX[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',

@ -24,5 +24,6 @@ int cli_chomp(char *string);
char *cli_strtok(const char *line, int field, const char *delim);
short int *cli_hex2si(const char *hex);
char *cli_hex2str(const char *hex);
char *cli_str2hex(const char *string, unsigned int len);
#endif

@ -813,7 +813,7 @@ static char *ppt_stream_iter(int fd)
#endif
/* generate the temporary directory */
out_dir = cl_gentemp(tmpdir);
out_dir = cli_gentemp(tmpdir);
if(mkdir(out_dir, 0700)) {
printf("ScanOLE2 -> Can't create temporary directory %s\n", out_dir);
close(fd);

@ -48,6 +48,9 @@
#include "memory.h"
#include "output.h"
#include "cfgparser.h"
#include "../clamscan/others.h"
#include "../libclamav/others.h"
#include "../libclamav/str.h"
#define LINE 1024
@ -104,7 +107,7 @@ char *cut(const char *file, long int start, long int end)
exit(13);
}
if((fname = cl_gentemp(".")) == NULL) {
if((fname = cli_gentemp(".")) == NULL) {
mprintf("!Can't generate temporary file name.\n");
exit(1);
}
@ -147,7 +150,7 @@ char *change(const char *file, long int x)
exit(13);
}
if((fname = cl_gentemp(".")) == NULL) {
if((fname = cli_gentemp(".")) == NULL) {
mprintf("!Can't generate temporary file name.\n");
exit(1);
}
@ -203,7 +206,7 @@ void sigtool(struct optstruct *opt)
if(optl(opt, "hex-dump")) {
while((bytes = read(0, buffer, FILEBUFF)) > 0) {
pt = cl_str2hex(buffer, bytes);
pt = cli_str2hex(buffer, bytes);
write(1, pt, 2 * bytes);
free(pt);
}
@ -423,7 +426,7 @@ void sigtool(struct optstruct *opt)
if(fileinfo(signame, 1) != -1) {
mprintf("File %s exists.\n", signame);
free(signame);
signame = cl_gentemp(".");
signame = cli_gentemp(".");
}
bsigname = (char *) mcalloc(strlen(f) + 10, sizeof(char));
@ -431,7 +434,7 @@ void sigtool(struct optstruct *opt)
if(fileinfo(bsigname, 1) != -1) {
mprintf("File %s exists.\n", bsigname);
free(bsigname);
bsigname = cl_gentemp(".");
bsigname = cli_gentemp(".");
}
if((wd = fopen(signame, "wb")) == NULL) {
@ -444,7 +447,7 @@ void sigtool(struct optstruct *opt)
mprintf("Saving signature in %s file.\n", signame);
while((bytes = fread(buffer, 1, FILEBUFF, fd)) > 0) {
pt = cl_str2hex(buffer, bytes);
pt = cli_str2hex(buffer, bytes);
fwrite(pt, 1, 2 * bytes, wd);
free(pt);
}
@ -551,7 +554,7 @@ int build(struct optstruct *opt)
exit(1);
}
cl_freetrie(root);
cl_free(root);
mprintf("Database properly parsed.\n");
@ -569,7 +572,7 @@ int build(struct optstruct *opt)
}
}
tarfile = cl_gentemp(".");
tarfile = cli_gentemp(".");
switch(fork()) {
case -1:
@ -597,7 +600,7 @@ int build(struct optstruct *opt)
exit(1);
}
gzfile = cl_gentemp(".");
gzfile = cli_gentemp(".");
if((gz = gzopen(gzfile, "wb")) == NULL) {
mprintf("!Can't open file %s to write.\n", gzfile);
exit(1);
@ -655,7 +658,7 @@ int build(struct optstruct *opt)
strcat(header, smbuff);
/* MD5 */
pt = cl_md5file(gzfile);
pt = cli_md5file(gzfile);
strcat(header, pt);
free(pt);
strcat(header, ":");
@ -880,7 +883,7 @@ int listdb(const char *filename)
tmpdir = "/tmp";
#endif
dir = cl_gentemp(tmpdir);
dir = cli_gentemp(tmpdir);
if(mkdir(dir, 0700)) {
mprintf("!listdb(): Can't create temporary directory %s\n", dir);
free(buffer);
@ -894,7 +897,7 @@ int listdb(const char *filename)
/* start */
tmp = cl_gentemp(tmpdir);
tmp = cli_gentemp(tmpdir);
if((tmpd = fopen(tmp, "wb+")) == NULL) {
mprintf("!listdb(): Can't create temporary file %s\n", tmp);
free(dir);

Loading…
Cancel
Save