diff --git a/clamav-devel/ChangeLog b/clamav-devel/ChangeLog index 1981078b6..21310aa78 100644 --- a/clamav-devel/ChangeLog +++ b/clamav-devel/ChangeLog @@ -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) diff --git a/clamav-devel/clamav-config b/clamav-devel/clamav-config index 60eeeb538..11b7a1e5b 100755 --- a/clamav-devel/clamav-config +++ b/clamav-devel/clamav-config @@ -46,7 +46,7 @@ while test $# -gt 0; do ;; --version) - echo devel-20040706 + echo devel-20040718 exit 0 ;; diff --git a/clamav-devel/clamd/clamd.c b/clamav-devel/clamd/clamd.c index 2eab690f4..19c73ddc8 100644 --- a/clamav-devel/clamd/clamd.c +++ b/clamav-devel/clamd/clamd.c @@ -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); diff --git a/clamav-devel/clamd/scanner.c b/clamav-devel/clamd/scanner.c index 02a031266..40262a0a4 100644 --- a/clamav-devel/clamd/scanner.c +++ b/clamav-devel/clamd/scanner.c @@ -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)); diff --git a/clamav-devel/clamd/server-th.c b/clamav-devel/clamd/server-th.c index c221121a6..e95527159 100644 --- a/clamav-devel/clamd/server-th.c +++ b/clamav-devel/clamd/server-th.c @@ -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); } diff --git a/clamav-devel/clamscan/manager.c b/clamav-devel/clamscan/manager.c index bc7b6e01f..19a4ac0c5 100644 --- a/clamav-devel/clamscan/manager.c +++ b/clamav-devel/clamscan/manager.c @@ -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 */ diff --git a/clamav-devel/examples/ex1.c b/clamav-devel/examples/ex1.c index 1576817e2..32388cc1a 100644 --- a/clamav-devel/examples/ex1.c +++ b/clamav-devel/examples/ex1.c @@ -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); diff --git a/clamav-devel/freshclam/freshclam.c b/clamav-devel/freshclam/freshclam.c index a71279789..7aa55acdf 100644 --- a/clamav-devel/freshclam/freshclam.c +++ b/clamav-devel/freshclam/freshclam.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/clamav-devel/freshclam/manager.c b/clamav-devel/freshclam/manager.c index aaaadd3ca..e73bb0a75 100644 --- a/clamav-devel/freshclam/manager.c +++ b/clamav-devel/freshclam/manager.c @@ -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); diff --git a/clamav-devel/freshclam/notify.c b/clamav-devel/freshclam/notify.c index d6e5ce5c6..852c84e6f 100644 --- a/clamav-devel/freshclam/notify.c +++ b/clamav-devel/freshclam/notify.c @@ -34,6 +34,7 @@ #include "others.h" #include "cfgparser.h" +#include "output.h" int notify(const char *cfgfile) { diff --git a/clamav-devel/libclamav/Makefile.am b/clamav-devel/libclamav/Makefile.am index 274d8f280..10d36fd31 100644 --- a/clamav-devel/libclamav/Makefile.am +++ b/clamav-devel/libclamav/Makefile.am @@ -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 \ diff --git a/clamav-devel/libclamav/Makefile.in b/clamav-devel/libclamav/Makefile.in index 9538785c4..4f375bb64 100644 --- a/clamav-devel/libclamav/Makefile.in +++ b/clamav-devel/libclamav/Makefile.in @@ -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@ diff --git a/clamav-devel/libclamav/clamav.h b/clamav-devel/libclamav/clamav.h index 1f2b3c59e..8e664f3e4 100644 --- a/clamav-devel/libclamav/clamav.h +++ b/clamav-devel/libclamav/clamav.h @@ -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 diff --git a/clamav-devel/libclamav/cvd.c b/clamav-devel/libclamav/cvd.c index 696d31372..9603c2b82 100644 --- a/clamav-devel/libclamav/cvd.c +++ b/clamav-devel/libclamav/cvd.c @@ -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); diff --git a/clamav-devel/libclamav/dsig.c b/clamav-devel/libclamav/dsig.c index 23ad36ce7..3577da685 100644 --- a/clamav-devel/libclamav/dsig.c +++ b/clamav-devel/libclamav/dsig.c @@ -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); diff --git a/clamav-devel/libclamav/filetypes.c b/clamav-devel/libclamav/filetypes.c index 72c460396..cdc0d07f6 100644 --- a/clamav-devel/libclamav/filetypes.c +++ b/clamav-devel/libclamav/filetypes.c @@ -27,6 +27,8 @@ #include "clamav.h" #include "filetypes.h" +#include "others.h" +#include "readdb.h" struct cli_magic_s { int offset; diff --git a/clamav-devel/libclamav/htmlnorm.c b/clamav-devel/libclamav/htmlnorm.c index ab9ea112d..582cb8dc1 100644 --- a/clamav-devel/libclamav/htmlnorm.c +++ b/clamav-devel/libclamav/htmlnorm.c @@ -21,6 +21,8 @@ #endif #include +#include +#include #include #include #include diff --git a/clamav-devel/libclamav/matcher-ac.c b/clamav-devel/libclamav/matcher-ac.c new file mode 100644 index 000000000..7600ac349 --- /dev/null +++ b/clamav-devel/libclamav/matcher-ac.c @@ -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 + * + * 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 +#include +#include +#include + +#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; +} diff --git a/clamav-devel/libclamav/matcher-ac.h b/clamav-devel/libclamav/matcher-ac.h new file mode 100644 index 000000000..a6ea0ee85 --- /dev/null +++ b/clamav-devel/libclamav/matcher-ac.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2002 - 2004 Tomasz Kojm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 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 diff --git a/clamav-devel/libclamav/matcher-bm.c b/clamav-devel/libclamav/matcher-bm.c new file mode 100644 index 000000000..cee49abb6 --- /dev/null +++ b/clamav-devel/libclamav/matcher-bm.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2004 Tomasz Kojm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 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; +} diff --git a/clamav-devel/libclamav/matcher-bm.h b/clamav-devel/libclamav/matcher-bm.h new file mode 100644 index 000000000..de8f48979 --- /dev/null +++ b/clamav-devel/libclamav/matcher-bm.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2004 Tomasz Kojm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 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 diff --git a/clamav-devel/libclamav/matcher.c b/clamav-devel/libclamav/matcher.c index 60376f6df..60f0e2396 100644 --- a/clamav-devel/libclamav/matcher.c +++ b/clamav-devel/libclamav/matcher.c @@ -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 * * This program is free software; you can redistribute it and/or modify @@ -25,345 +20,212 @@ #include "clamav-config.h" #endif -#include #include -#include -#include #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); } diff --git a/clamav-devel/libclamav/matcher.h b/clamav-devel/libclamav/matcher.h index cacfbd137..0ccaa34e2 100644 --- a/clamav-devel/libclamav/matcher.h +++ b/clamav-devel/libclamav/matcher.h @@ -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 diff --git a/clamav-devel/libclamav/mbox.c b/clamav-devel/libclamav/mbox.c index 3c6d837c7..acee8ba82 100644 --- a/clamav-devel/libclamav/mbox.c +++ b/clamav-devel/libclamav/mbox.c @@ -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; diff --git a/clamav-devel/libclamav/others.c b/clamav-devel/libclamav/others.c index 2623b9c65..1fef487e1 100644 --- a/clamav-devel/libclamav/others.c +++ b/clamav-devel/libclamav/others.c @@ -41,7 +41,7 @@ #ifdef CL_THREAD_SAFE # include -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; diff --git a/clamav-devel/libclamav/others.h b/clamav-devel/libclamav/others.h index 0e35757ea..1d5e8c30c 100644 --- a/clamav-devel/libclamav/others.h +++ b/clamav-devel/libclamav/others.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999-2002 Tomasz Kojm + * Copyright (C) 1999 - 2004 Tomasz Kojm * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -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 #include @@ -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 diff --git a/clamav-devel/libclamav/pe.c b/clamav-devel/libclamav/pe.c index c1ea0cc8e..cb75880d2 100644 --- a/clamav-devel/libclamav/pe.c +++ b/clamav-devel/libclamav/pe.c @@ -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 *) ×tamp)); + timestamp = (time_t) EC32(file_hdr.TimeDateStamp); + cli_dbgmsg("TimeDateStamp: %s", ctime(×tamp)); 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); diff --git a/clamav-devel/libclamav/readdb.c b/clamav-devel/libclamav/readdb.c index 7775501fd..ce674decc 100644 --- a/clamav-devel/libclamav/readdb.c +++ b/clamav-devel/libclamav/readdb.c @@ -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; } diff --git a/clamav-devel/libclamav/readdb.h b/clamav-devel/libclamav/readdb.h index 924efdc67..155985744 100644 --- a/clamav-devel/libclamav/readdb.h +++ b/clamav-devel/libclamav/readdb.h @@ -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 diff --git a/clamav-devel/libclamav/scanners.c b/clamav-devel/libclamav/scanners.c index e43d595ad..415359b8b 100644 --- a/clamav-devel/libclamav/scanners.c +++ b/clamav-devel/libclamav/scanners.c @@ -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 @@ -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)--; diff --git a/clamav-devel/libclamav/str.c b/clamav-devel/libclamav/str.c index 861ae1879..0f7cef056 100644 --- a/clamav-devel/libclamav/str.c +++ b/clamav-devel/libclamav/str.c @@ -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', diff --git a/clamav-devel/libclamav/str.h b/clamav-devel/libclamav/str.h index 5d1d9946b..f3aeeff14 100644 --- a/clamav-devel/libclamav/str.h +++ b/clamav-devel/libclamav/str.h @@ -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 diff --git a/clamav-devel/libclamav/vba_extract.c b/clamav-devel/libclamav/vba_extract.c index 157315809..adf040e0e 100644 --- a/clamav-devel/libclamav/vba_extract.c +++ b/clamav-devel/libclamav/vba_extract.c @@ -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); diff --git a/clamav-devel/sigtool/sigtool.c b/clamav-devel/sigtool/sigtool.c index 69d3b8639..61a4ea2b7 100644 --- a/clamav-devel/sigtool/sigtool.c +++ b/clamav-devel/sigtool/sigtool.c @@ -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);