[Pkg-clamav-commits] [SCM] Debian repository for ClamAV branch, debian/unstable, updated. debian/0.95+dfsg-1-6156-g094ec9b
Tomasz Kojm
tkojm at clamav.net
Sun Apr 4 01:16:05 UTC 2010
The following commit has been merged in the debian/unstable branch:
commit ace26bfe0889bc11e5a7538b7f70b431658eec56
Author: Tomasz Kojm <tkojm at clamav.net>
Date: Wed Jan 20 22:10:56 2010 +0100
libclamav: check .info files while loading CVD/CLD
diff --git a/ChangeLog b/ChangeLog
index 51427a5..ad4e77d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Wed Jan 20 22:10:12 CET 2010 (tk)
+---------------------------------
+ * libclamav: check .info files while loading CVD/CLD
+
Tue Jan 19 11:49:12 CET 2010 (acab)
-----------------------------------
* clamdscan/proto.c: don't stop scanning if a file is not found (bb#1760)
diff --git a/libclamav/cvd.c b/libclamav/cvd.c
index c46db68..68e8583 100644
--- a/libclamav/cvd.c
+++ b/libclamav/cvd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2009 Sourcefire, Inc.
+ * Copyright (C) 2007-2010 Sourcefire, Inc.
*
* Authors: Tomasz Kojm
*
@@ -42,6 +42,7 @@
#include "cvd.h"
#include "readdb.h"
#include "default.h"
+#include "md5.h"
#define TAR_BLOCKSIZE 512
@@ -179,20 +180,21 @@ static int cli_untgz(int fd, const char *destdir)
return 0;
}
-static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, unsigned int options)
+static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, struct cli_dbinfo *dbinfo)
{
char osize[13], name[101];
char block[TAR_BLOCKSIZE];
int nread, fdd, ret;
unsigned int type, size, pad, compr = 1;
off_t off;
- struct cli_dbio dbio;
+ struct cli_dbinfo *db;
+ unsigned char hash[16];
#define CLOSE_DBIO \
if(compr) \
- gzclose(dbio.gzs); \
+ gzclose(dbio->gzs); \
else \
- fclose(dbio.fs)
+ fclose(dbio->fs)
cli_dbgmsg("in cli_tgzload()\n");
@@ -211,43 +213,43 @@ static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, un
}
if(compr) {
- if((dbio.gzs = gzdopen(fdd, "rb")) == NULL) {
+ if((dbio->gzs = gzdopen(fdd, "rb")) == NULL) {
cli_errmsg("cli_tgzload: Can't gzdopen() descriptor %d, errno = %d\n", fdd, errno);
return CL_EOPEN;
}
- dbio.fs = NULL;
+ dbio->fs = NULL;
} else {
- if((dbio.fs = fdopen(fdd, "rb")) == NULL) {
+ if((dbio->fs = fdopen(fdd, "rb")) == NULL) {
cli_errmsg("cli_tgzload: Can't fdopen() descriptor %d, errno = %d\n", fdd, errno);
return CL_EOPEN;
}
- dbio.gzs = NULL;
+ dbio->gzs = NULL;
}
- dbio.bufsize = CLI_DEFAULT_DBIO_BUFSIZE;
- dbio.buf = cli_malloc(dbio.bufsize);
- if(!dbio.buf) {
- cli_errmsg("cli_tgzload: Can't allocate memory for dbio.buf\n");
+ dbio->bufsize = CLI_DEFAULT_DBIO_BUFSIZE;
+ dbio->buf = cli_malloc(dbio->bufsize);
+ if(!dbio->buf) {
+ cli_errmsg("cli_tgzload: Can't allocate memory for dbio->buf\n");
CLOSE_DBIO;
return CL_EMALFDB;
}
- dbio.bufpt = NULL;
- dbio.usebuf = 1;
- dbio.readpt = dbio.buf;
+ dbio->bufpt = NULL;
+ dbio->usebuf = 1;
+ dbio->readpt = dbio->buf;
while(1) {
if(compr)
- nread = gzread(dbio.gzs, block, TAR_BLOCKSIZE);
+ nread = gzread(dbio->gzs, block, TAR_BLOCKSIZE);
else
- nread = fread(block, 1, TAR_BLOCKSIZE, dbio.fs);
+ nread = fread(block, 1, TAR_BLOCKSIZE, dbio->fs);
if(!nread)
break;
if(nread != TAR_BLOCKSIZE) {
cli_errmsg("cli_tgzload: Incomplete block read\n");
- free(dbio.buf);
+ free(dbio->buf);
CLOSE_DBIO;
return CL_EMALFDB;
}
@@ -260,7 +262,7 @@ static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, un
if(strchr(name, '/')) {
cli_errmsg("cli_tgzload: Slash separators are not allowed in CVD\n");
- free(dbio.buf);
+ free(dbio->buf);
CLOSE_DBIO;
return CL_EMALFDB;
}
@@ -273,12 +275,12 @@ static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, un
break;
case '5':
cli_errmsg("cli_tgzload: Directories are not supported in CVD\n");
- free(dbio.buf);
+ free(dbio->buf);
CLOSE_DBIO;
return CL_EMALFDB;
default:
cli_errmsg("cli_tgzload: Unknown type flag '%c'\n", type);
- free(dbio.buf);
+ free(dbio->buf);
CLOSE_DBIO;
return CL_EMALFDB;
}
@@ -288,45 +290,72 @@ static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, un
if((sscanf(osize, "%o", &size)) == 0) {
cli_errmsg("cli_tgzload: Invalid size in header\n");
- free(dbio.buf);
+ free(dbio->buf);
CLOSE_DBIO;
return CL_EMALFDB;
}
- dbio.size = size;
- dbio.readsize = dbio.size < dbio.bufsize ? dbio.size : dbio.bufsize - 1;
- dbio.bufpt = NULL;
- dbio.readpt = dbio.buf;
+ dbio->size = size;
+ dbio->readsize = dbio->size < dbio->bufsize ? dbio->size : dbio->bufsize - 1;
+ dbio->bufpt = NULL;
+ dbio->readpt = dbio->buf;
+ cli_md5_init(&dbio->md5ctx);
+ dbio->bread = 0;
/* cli_dbgmsg("cli_tgzload: Loading %s, size: %u\n", name, size); */
if(compr)
- off = (off_t) gzseek(dbio.gzs, 0, SEEK_CUR);
+ off = (off_t) gzseek(dbio->gzs, 0, SEEK_CUR);
else
- off = ftell(dbio.fs);
+ off = ftell(dbio->fs);
- if(CLI_DBEXT(name)) {
- ret = cli_load(name, engine, signo, options, &dbio);
+ if((!dbinfo && cli_strbcasestr(name, ".info")) || (dbinfo && CLI_DBEXT(name))) {
+ ret = cli_load(name, engine, signo, options, dbio);
if(ret) {
cli_errmsg("cli_tgzload: Can't load %s\n", name);
- free(dbio.buf);
+ free(dbio->buf);
CLOSE_DBIO;
return CL_EMALFDB;
}
+ if(!dbinfo) {
+ free(dbio->buf);
+ CLOSE_DBIO;
+ return CL_SUCCESS;
+ } else {
+ db = dbinfo;
+ while(db && strcmp(db->name, name))
+ db = db->next;
+ if(!db) {
+ cli_errmsg("cli_tgzload: File %s not found in .info\n", name);
+ free(dbio->buf);
+ CLOSE_DBIO;
+ return CL_EMALFDB;
+ }
+ if(dbio->bread) {
+ /* TODO: compare sizes; replace with sha256 */
+ cli_md5_final(hash, &dbio->md5ctx);
+ if(memcmp(db->hash, hash, 16)) {
+ cli_errmsg("cli_tgzload: Invalid checksum for file %s\n", name);
+ free(dbio->buf);
+ CLOSE_DBIO;
+ return CL_EMALFDB;
+ }
+ }
+ }
}
pad = size % TAR_BLOCKSIZE ? (TAR_BLOCKSIZE - (size % TAR_BLOCKSIZE)) : 0;
if(compr) {
- if(off == gzseek(dbio.gzs, 0, SEEK_CUR))
- gzseek(dbio.gzs, size + pad, SEEK_CUR);
+ if(off == gzseek(dbio->gzs, 0, SEEK_CUR))
+ gzseek(dbio->gzs, size + pad, SEEK_CUR);
else if(pad)
- gzseek(dbio.gzs, pad, SEEK_CUR);
+ gzseek(dbio->gzs, pad, SEEK_CUR);
} else {
- if(off == ftell(dbio.fs))
- fseek(dbio.fs, size + pad, SEEK_CUR);
+ if(off == ftell(dbio->fs))
+ fseek(dbio->fs, size + pad, SEEK_CUR);
else if(pad)
- fseek(dbio.fs, pad, SEEK_CUR);
+ fseek(dbio->fs, pad, SEEK_CUR);
}
}
- free(dbio.buf);
+ free(dbio->buf);
CLOSE_DBIO;
return CL_SUCCESS;
}
@@ -520,22 +549,22 @@ int cl_cvdverify(const char *file)
return ret;
}
-int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int daily, unsigned int options, unsigned int cld)
+int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, unsigned int cld, const char *dbname)
{
- char *dir;
struct cl_cvd cvd;
int ret;
time_t s_time;
int cfd;
+ struct cli_dbio dbio;
+ struct cli_dbinfo *dbinfo = NULL;
cli_dbgmsg("in cli_cvdload()\n");
/* verify */
-
if((ret = cli_cvdverify(fs, &cvd, cld)))
return ret;
- if(cvd.stime && daily) {
+ if(strstr(dbname, "daily.")) {
time(&s_time);
if(cvd.stime > s_time) {
if(cvd.stime - (unsigned int ) s_time > 3600) {
@@ -550,6 +579,8 @@ int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigne
cli_warnmsg("*** Please update it as soon as possible. ***\n");
cli_warnmsg("**************************************************\n");
}
+ engine->dbversion[0] = cvd.version;
+ engine->dbversion[1] = cvd.stime;
}
if(cvd.fl > cl_retflevel()) {
@@ -570,12 +601,26 @@ int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigne
return CL_ESEEK;
}
- if(daily) {
- engine->dbversion[0] = cvd.version;
- engine->dbversion[1] = cvd.stime;
+ ret = cli_tgzload(cfd, engine, signo, options | CL_DB_OFFICIAL, &dbio, NULL);
+ if(ret != CL_SUCCESS)
+ return ret;
+ /* TODO: check CVD header */
+ dbinfo = engine->dbinfo ? engine->dbinfo->next : NULL;
+ if(!dbinfo)
+ return CL_EMALFDB;
+
+ ret = cli_tgzload(cfd, engine, signo, options | CL_DB_OFFICIAL, &dbio, dbinfo);
+
+ while(engine->dbinfo) {
+ dbinfo = engine->dbinfo;
+ engine->dbinfo = dbinfo->next;
+ mpool_free(engine->mempool, dbinfo->name);
+ mpool_free(engine->mempool, dbinfo->hash);
+ free(dbinfo->cvd);
+ mpool_free(engine->mempool, dbinfo);
}
- return cli_tgzload(cfd, engine, signo, options | CL_DB_OFFICIAL);
+ return ret;
}
int cli_cvdunpack(const char *file, const char *dir)
diff --git a/libclamav/cvd.h b/libclamav/cvd.h
index 53681e3..c5ca6c9 100644
--- a/libclamav/cvd.h
+++ b/libclamav/cvd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2009 Sourcefire, Inc.
+ * Copyright (C) 2007-2010 Sourcefire, Inc.
*
* Authors: Tomasz Kojm
*
@@ -25,16 +25,18 @@
#include <zlib.h>
#include "clamav.h"
+#include "md5.h"
+
struct cli_dbio {
gzFile *gzs;
FILE *fs;
- unsigned int size;
+ unsigned int size, bread;
char *buf, *bufpt, *readpt;
unsigned int usebuf, bufsize, readsize;
-
+ cli_md5_ctx md5ctx; /* TODO: replace with sha256 */
};
-int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int daily, unsigned int options, unsigned int cld);
+int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, unsigned int cld, const char *dbname);
int cli_cvdunpack(const char *file, const char *dir);
#endif
diff --git a/libclamav/others.h b/libclamav/others.h
index 47a8dc2..3ac787c 100644
--- a/libclamav/others.h
+++ b/libclamav/others.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2008 Sourcefire, Inc.
+ * Copyright (C) 2007-2010 Sourcefire, Inc.
*
* Authors: Tomasz Kojm
*
@@ -160,6 +160,14 @@ struct icon_matcher {
unsigned int icon_counts[3];
};
+struct cli_dbinfo {
+ char *name;
+ unsigned char *hash;
+ size_t size;
+ struct cl_cvd *cvd;
+ struct cli_dbinfo *next;
+};
+
struct cl_engine {
uint32_t refcount; /* reference counter */
uint32_t sdb;
@@ -227,6 +235,9 @@ struct cl_engine {
/* Negative cache storage */
struct CACHE *cache;
+ /* Database information from .info files */
+ struct cli_dbinfo *dbinfo;
+
/* Used for memory pools */
mpool_t *mempool;
diff --git a/libclamav/readdb.c b/libclamav/readdb.c
index 8d1013e..f01c143 100644
--- a/libclamav/readdb.c
+++ b/libclamav/readdb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2009 Sourcefire, Inc.
+ * Copyright (C) 2007-2010 Sourcefire, Inc.
*
* Authors: Tomasz Kojm
*
@@ -350,6 +350,8 @@ char *cli_dbgets(char *buff, unsigned int size, FILE *fs, struct cli_dbio *dbio)
dbio->readpt[bread] = 0;
dbio->bufpt = dbio->buf;
dbio->size -= bread;
+ dbio->bread += bread;
+ cli_md5_update(&dbio->md5ctx, dbio->readpt, bread);
}
nl = strchr(dbio->bufpt, '\n');
if(nl) {
@@ -394,9 +396,14 @@ char *cli_dbgets(char *buff, unsigned int size, FILE *fs, struct cli_dbio *dbio)
else
pt = fgets(buff, bs, dbio->fs);
- dbio->size -= strlen(buff);
- if(!pt)
+ if(!pt) {
cli_errmsg("cli_dbgets: Preliminary end of data\n");
+ return pt;
+ }
+ bs = strlen(buff);
+ dbio->size -= bs;
+ dbio->bread += bs;
+ cli_md5_update(&dbio->md5ctx, buff, bs);
return pt;
}
}
@@ -1494,6 +1501,85 @@ static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options,
return CL_SUCCESS;
}
+#define IGN_INFO_TOKENS 2
+static int cli_loadinfo(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio)
+{
+ const char *tokens[IGN_INFO_TOKENS + 1];
+ char buffer[FILEBUFF];
+ unsigned int line = 0, tokens_count;
+ struct cli_dbinfo *last = NULL, *new;
+ int ret = CL_SUCCESS;
+
+ while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
+ line++;
+ if(!strncmp(buffer, "DSIG:", 5))
+ continue; /* TODO */
+ cli_chomp(buffer);
+
+ if(!strncmp("ClamAV-VDB:", buffer, 11)) {
+ if(engine->dbinfo) { /* shouldn't be initialized at this point */
+ cli_errmsg("cli_loadinfo: engine->dbinfo already initialized\n");
+ ret = CL_EMALFDB;
+ break;
+ }
+ last = engine->dbinfo = (struct cli_dbinfo *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_bm_patt));
+ if(!engine->dbinfo) {
+ ret = CL_EMEM;
+ break;
+ }
+ engine->dbinfo->cvd = cl_cvdparse(buffer);
+ if(!engine->dbinfo->cvd) {
+ cli_errmsg("cli_loadinfo: Can't parse header entry\n");
+ ret = CL_EMALFDB;
+ break;
+ }
+ continue;
+ }
+
+ if(!last) {
+ cli_errmsg("cli_loadinfo: Incorrect file format\n");
+ ret = CL_EMALFDB;
+ break;
+ }
+ tokens_count = cli_strtokenize(buffer, ':', IGN_INFO_TOKENS + 1, tokens);
+ if(tokens_count > IGN_INFO_TOKENS) {
+ ret = CL_EMALFDB;
+ break;
+ }
+ new = (struct cli_dbinfo *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_dbinfo));
+ if(!new) {
+ ret = CL_EMEM;
+ break;
+ }
+ new->name = (unsigned char *) cli_mpool_strdup(engine->mempool, tokens[0]);
+ if(!new->name) {
+ mpool_free(engine->mempool, new);
+ ret = CL_EMEM;
+ break;
+ }
+
+ /* TODO: hash will be replaced with sha256 */
+ if(strlen(tokens[1]) != 32 || !(new->hash = cli_mpool_hex2str(engine->mempool, tokens[1]))) {
+ cli_errmsg("cli_loadinfo: Malformed MD5 string at line %u\n", line);
+ mpool_free(engine->mempool, new->name);
+ mpool_free(engine->mempool, new);
+ ret = CL_EMALFDB;
+ break;
+ }
+
+ new->size = 0; /* TODO */
+ last->next = new;
+ last = new;
+ }
+
+ if(ret) {
+ cli_errmsg("cli_loadinfo: Problem parsing database at line %u\n", line);
+ return ret;
+ }
+
+ return CL_SUCCESS;
+}
+
#define IGN_MAX_TOKENS 3
static int cli_loadign(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio)
{
@@ -2083,10 +2169,10 @@ int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo
ret = cli_loaddb(fs, engine, signo, options, dbio, dbname);
} else if(cli_strbcasestr(dbname, ".cvd")) {
- ret = cli_cvdload(fs, engine, signo, !strcmp(dbname, "daily.cvd"), options, 0);
+ ret = cli_cvdload(fs, engine, signo, options, 0, dbname);
} else if(cli_strbcasestr(dbname, ".cld")) {
- ret = cli_cvdload(fs, engine, signo, !strcmp(dbname, "daily.cld"), options, 1);
+ ret = cli_cvdload(fs, engine, signo, options, 1, dbname);
} else if(cli_strbcasestr(dbname, ".hdb")) {
ret = cli_loadmd5(fs, engine, signo, MD5_HDB, options, dbio, dbname);
@@ -2143,6 +2229,9 @@ int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo
} else if(cli_strbcasestr(dbname, ".cfg")) {
ret = cli_dconf_load(fs, engine, options, dbio);
+ } else if(cli_strbcasestr(dbname, ".info")) {
+ ret = cli_loadinfo(fs, engine, options, dbio);
+
} else if(cli_strbcasestr(dbname, ".wdb")) {
if(options & CL_DB_PHISHING_URLS) {
ret = cli_loadwdb(fs, engine, options, dbio);
@@ -2671,6 +2760,15 @@ int cl_engine_free(struct cl_engine *engine)
mpool_free(engine->mempool, pt);
}
+ while(engine->dbinfo) {
+ struct cli_dbinfo *pt = engine->dbinfo;
+ engine->dbinfo = pt->next;
+ mpool_free(engine->mempool, pt->name);
+ mpool_free(engine->mempool, pt->hash);
+ free(pt->cvd);
+ mpool_free(engine->mempool, pt);
+ }
+
if(engine->dconf->bytecode & BYTECODE_ENGINE_MASK) {
if (engine->bcs.all_bcs)
for(i=0;i<engine->bcs.count;i++)
--
Debian repository for ClamAV
More information about the Pkg-clamav-commits
mailing list