[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