[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:22 UTC 2010


The following commit has been merged in the debian/unstable branch:
commit de351ee1bc741f5b06a7007904efd1164e9e414b
Author: Tomasz Kojm <tkojm at clamav.net>
Date:   Mon Jan 25 13:28:19 2010 +0100

    libclamav: handle digitally signed .info files

diff --git a/ChangeLog b/ChangeLog
index d865865..2f211de 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Mon Jan 25 13:27:44 CET 2010 (tk)
+---------------------------------
+ * libclamav: handle digitally signed .info files
+
 Fri Jan 22 11:49:07 CET 2010 (acab)
 -----------------------------------
  * libclamav: fix shifts >= width (bb#1778)
diff --git a/libclamav/clamav.h b/libclamav/clamav.h
index b81672a..6bb1f1c 100644
--- a/libclamav/clamav.h
+++ b/libclamav/clamav.h
@@ -82,6 +82,7 @@ typedef enum {
 #define CL_DB_DIRECTORY	    0x800   /* internal */
 #define CL_DB_OFFICIAL_ONLY 0x1000
 #define CL_DB_BYTECODE      0x2000
+#define CL_DB_SIGNED	    0x4000
 
 /* recommended db settings */
 #define CL_DB_STDOPT	    (CL_DB_PHISHING | CL_DB_PHISHING_URLS | CL_DB_BYTECODE)
diff --git a/libclamav/cvd.c b/libclamav/cvd.c
index b5bf583..bfbece7 100644
--- a/libclamav/cvd.c
+++ b/libclamav/cvd.c
@@ -42,10 +42,12 @@
 #include "cvd.h"
 #include "readdb.h"
 #include "default.h"
-#include "md5.h"
+#include "sha256.h"
 
 #define TAR_BLOCKSIZE 512
 
+#define DB_NOCHECK 0x80000 /* FIXME: temporary */
+
 static int cli_untgz(int fd, const char *destdir)
 {
 	char *path, osize[13], name[101], type;
@@ -188,7 +190,7 @@ static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, un
 	unsigned int type, size, pad, compr = 1;
 	off_t off;
 	struct cli_dbinfo *db;
-	unsigned char hash[16];
+	unsigned char hash[32];
 
 #define CLOSE_DBIO	    \
     if(compr)		    \
@@ -298,9 +300,8 @@ static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, un
 	dbio->readsize = dbio->size < dbio->bufsize ? dbio->size : dbio->bufsize - 1;
 	dbio->bufpt = NULL;
 	dbio->readpt = dbio->buf;
-	cli_md5_init(&dbio->md5ctx);
+	sha256_init(&dbio->sha256ctx);
 	dbio->bread = 0;
-	dbio->secure = 0;
 
 	/* cli_dbgmsg("cli_tgzload: Loading %s, size: %u\n", name, size); */
 	if(compr)
@@ -308,8 +309,7 @@ static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, un
 	else
 	    off = ftell(dbio->fs);
 
-	/*if((!dbinfo && cli_strbcasestr(name, ".info")) || (dbinfo && CLI_DBEXT(name))) {*/
-	if(CLI_DBEXT(name)) {
+	if((!dbinfo && !(options & DB_NOCHECK) && cli_strbcasestr(name, ".info")) || ((dbinfo || (options & DB_NOCHECK)) && CLI_DBEXT(name))) {
 	    ret = cli_load(name, engine, signo, options, dbio);
 	    if(ret) {
 		cli_errmsg("cli_tgzload: Can't load %s\n", name);
@@ -317,11 +317,12 @@ static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, un
 		CLOSE_DBIO;
 		return CL_EMALFDB;
 	    }
-	    /*
 	    if(!dbinfo) {
-		free(dbio->buf);
-		CLOSE_DBIO;
-		return CL_SUCCESS;
+		if(!(options & DB_NOCHECK)) { /* FIXME: temporary */
+		    free(dbio->buf);
+		    CLOSE_DBIO;
+		    return CL_SUCCESS;
+		}
 	    } else {
 		db = dbinfo;
 		while(db && strcmp(db->name, name))
@@ -333,8 +334,14 @@ static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, un
 		    return CL_EMALFDB;
 		}
 		if(dbio->bread) {
-		    cli_md5_final(hash, &dbio->md5ctx);
-		    if(memcmp(db->hash, hash, 16)) {
+		    if(db->size != dbio->bread) {
+			cli_errmsg("cli_tgzload: File %s not correctly loaded\n", name);
+			free(dbio->buf);
+			CLOSE_DBIO;
+			return CL_EMALFDB;
+		    }
+		    sha256_final(&dbio->sha256ctx, hash);
+		    if(memcmp(db->hash, hash, 32)) {
 			cli_errmsg("cli_tgzload: Invalid checksum for file %s\n", name);
 			free(dbio->buf);
 			CLOSE_DBIO;
@@ -342,7 +349,6 @@ static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, un
 		    }
 		}
 	    }
-	    */
 	}
 	pad = size % TAR_BLOCKSIZE ? (TAR_BLOCKSIZE - (size % TAR_BLOCKSIZE)) : 0;
 	if(compr) {
@@ -594,27 +600,30 @@ int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigne
     }
 
     cfd = fileno(fs);
-    /* use only operations on file descriptors, and not on the FILE* from here on 
-     * if we seek the FILE*, the underlying descriptor may not seek as expected
-     * (for example on OpenBSD, cygwin, etc.).
-     * So seek the descriptor directly.
-     */ 
-    if(lseek(cfd, 512, SEEK_SET) == -1) {
-	cli_errmsg("cli_cvdload(): lseek(fs, 512, SEEK_SET) failed\n");
-	return CL_ESEEK;
-    }
 
+    if(strstr(dbname, "main.")) /* FIXME: temporary */
+	options |= DB_NOCHECK;
+    else
+	ret = cli_tgzload(cfd, engine, signo, options | CL_DB_OFFICIAL, &dbio, NULL);
     /*
-    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;
+    options |= CL_DB_SIGNED;
     */
+    if(ret != CL_SUCCESS)
+	options |= DB_NOCHECK;
 
+    if(!(options & DB_NOCHECK)) { /* FIXME: temporary */
+	dbinfo = engine->dbinfo;
+	if(!dbinfo || !dbinfo->cvd || (dbinfo->cvd->version != cvd.version) || (dbinfo->cvd->sigs != cvd.sigs) || (dbinfo->cvd->fl != cvd.fl) || (dbinfo->cvd->stime != cvd.stime)) {
+	    cli_errmsg("cli_cvdload: Corrupted CVD header\n");
+	    return CL_EMALFDB;
+	}
+	dbinfo = engine->dbinfo ? engine->dbinfo->next : NULL;
+	if(!dbinfo)
+	    return CL_EMALFDB;
+	options |= CL_DB_SIGNED;
+    }
     ret = cli_tgzload(cfd, engine, signo, options | CL_DB_OFFICIAL, &dbio, dbinfo);
 
     while(engine->dbinfo) {
diff --git a/libclamav/cvd.h b/libclamav/cvd.h
index d3701ca..9b0c09c 100644
--- a/libclamav/cvd.h
+++ b/libclamav/cvd.h
@@ -25,7 +25,7 @@
 #include <zlib.h>
 #include "clamav.h"
 
-#include "md5.h"
+#include "sha256.h"
 
 struct cli_dbio {
     gzFile *gzs;
@@ -33,8 +33,7 @@ struct cli_dbio {
     unsigned int size, bread;
     char *buf, *bufpt, *readpt;
     unsigned int usebuf, bufsize, readsize;
-    unsigned secure;
-    cli_md5_ctx md5ctx; /* TODO: replace with sha256 */
+    SHA256_CTX sha256ctx;
 };
 
 int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, unsigned int cld, const char *dbname);
diff --git a/libclamav/readdb.c b/libclamav/readdb.c
index 887c28a..2a2e6ea 100644
--- a/libclamav/readdb.c
+++ b/libclamav/readdb.c
@@ -56,6 +56,8 @@
 #include "cltypes.h"
 #include "default.h"
 #include "md5.h"
+#include "sha256.h"
+#include "dsig.h"
 
 #include "phishcheck.h"
 #include "phish_whitelist.h"
@@ -351,7 +353,7 @@ char *cli_dbgets(char *buff, unsigned int size, FILE *fs, struct cli_dbio *dbio)
 		dbio->bufpt = dbio->buf;
 		dbio->size -= bread;
 		dbio->bread += bread;
-		cli_md5_update(&dbio->md5ctx, dbio->readpt, bread);
+		sha256_update(&dbio->sha256ctx, dbio->readpt, bread);
 	    }
 	    nl = strchr(dbio->bufpt, '\n');
 	    if(nl) {
@@ -403,7 +405,7 @@ char *cli_dbgets(char *buff, unsigned int size, FILE *fs, struct cli_dbio *dbio)
 	bs = strlen(buff);
 	dbio->size -= bs;
 	dbio->bread += bs;
-        cli_md5_update(&dbio->md5ctx, buff, bs);
+	sha256_update(&dbio->sha256ctx, buff, bs);
 	return pt;
     }
 }
@@ -1341,12 +1343,7 @@ static int cli_loadcbc(FILE *fs, struct cl_engine *engine, unsigned int *signo,
 	    cli_dbgmsg("bytecode: trusting all bytecode!\n");
 	    break;
 	case CL_BYTECODE_TRUST_SIGNED:
-	    if (dbio && (!engine->dbinfo || !engine->dbinfo->cvd
-			 || !engine->dbinfo->cvd->dsig)) {
-		cli_errmsg("CVD without signed .info?\n");
-		return CL_EMALFDB;
-	    }
-	    security_trust = dbio ? 1 : 0;
+	    security_trust = !!(options & CL_DB_SIGNED);
 	    break;
 	default:
 	    security_trust = 0;
@@ -1522,21 +1519,39 @@ static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options,
     return CL_SUCCESS;
 }
 
-#define IGN_INFO_TOKENS 2
+#define INFO_NSTR "11088894983048545473659556106627194923928941791795047620591658697413581043322715912172496806525381055880964520618400224333320534660299233983755341740679502866829909679955734391392668378361221524205396631090105151641270857277080310734320951653700508941717419168723942507890702904702707587451621691050754307850383399865346487203798464178537392211402786481359824461197231102895415093770394216666324484593935762408468516826633192140826667923494822045805347809932848454845886971706424360558667862775876072059437703365380209101697738577515476935085469455279994113145977994084618328482151013142393373316337519977244732747977"
+#define INFO_ESTR "100002049"
+#define INFO_TOKENS 3
 static int cli_loadinfo(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio)
 {
-	const char *tokens[IGN_INFO_TOKENS + 1];
+	const char *tokens[INFO_TOKENS + 1];
 	char buffer[FILEBUFF];
-	unsigned int line = 0, tokens_count;
+	unsigned int line = 0, tokens_count, len;
+	unsigned char hash[32];
         struct cli_dbinfo *last = NULL, *new;
-	int ret = CL_SUCCESS;
+	int ret = CL_SUCCESS, dsig = 0;
+	SHA256_CTX ctx;
 
+    sha256_init(&ctx);
     while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
 	line++;
-	if(!strncmp(buffer, "DSIG:", 5))
-	    continue; /* TODO */
+	if(!strncmp(buffer, "DSIG:", 5)) {
+	    dsig = 1;
+	    sha256_final(&ctx, hash);
+	    if(cli_versig2(hash, buffer + 5, INFO_NSTR, INFO_ESTR) != CL_SUCCESS) {
+		cli_errmsg("cli_loadinfo: Incorrect digital signature\n");
+		ret = CL_EMALFDB;
+	    }
+	    break;
+	}
+	len = strlen(buffer);
+	if(dbio->usebuf && buffer[len - 1] != '\n' && len + 1 < FILEBUFF) {
+	    /* cli_dbgets in buffered mode strips \n */
+	    buffer[len] = '\n';
+	    buffer[len + 1] = 0;
+	}
+	sha256_update(&ctx, buffer, strlen(buffer));
 	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");
@@ -1562,8 +1577,8 @@ static int cli_loadinfo(FILE *fs, struct cl_engine *engine, unsigned int options
 	    ret = CL_EMALFDB;
 	    break;
 	}
-	tokens_count = cli_strtokenize(buffer, ':', IGN_INFO_TOKENS + 1, tokens);
-	if(tokens_count > IGN_INFO_TOKENS) {
+	tokens_count = cli_strtokenize(buffer, ':', INFO_TOKENS + 1, tokens);
+	if(tokens_count != INFO_TOKENS) {
 	    ret = CL_EMALFDB;
 	    break;
 	}
@@ -1579,20 +1594,31 @@ static int cli_loadinfo(FILE *fs, struct cl_engine *engine, unsigned int options
 	    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);
+	if(!cli_isnumber(tokens[1])) {
+	    cli_errmsg("cli_loadinfo: Invalid value in the size field\n");
 	    mpool_free(engine->mempool, new->name);
 	    mpool_free(engine->mempool, new);
 	    ret = CL_EMALFDB;
 	    break;
 	}
+	new->size = atoi(tokens[1]);
 
-	new->size = 0; /* TODO */
+	if(strlen(tokens[2]) != 64 || !(new->hash = cli_mpool_hex2str(engine->mempool, tokens[2]))) {
+	    cli_errmsg("cli_loadinfo: Malformed SHA256 string at line %u\n", line);
+	    mpool_free(engine->mempool, new->name);
+	    mpool_free(engine->mempool, new);
+	    ret = CL_EMALFDB;
+	    break;
+	}
 	last->next = new;
 	last = new;
     }
 
+    if(!dsig) {
+	cli_errmsg("cli_loadinfo: Digital signature not found\n");
+	return CL_EMALFDB;
+    }
+
     if(ret) {
 	cli_errmsg("cli_loadinfo: Problem parsing database at line %u\n", line);
 	return ret;
diff --git a/unit_tests/check_bytecode.c b/unit_tests/check_bytecode.c
index 6c7968e..09acda0 100644
--- a/unit_tests/check_bytecode.c
+++ b/unit_tests/check_bytecode.c
@@ -60,7 +60,7 @@ static void runtest(const char *file, uint64_t expected, int fail, int nojit)
     bcs.all_bcs = &bc;
     bcs.count = 1;
 
-    rc = cli_bytecode_load(&bc, f, NULL);
+    rc = cli_bytecode_load(&bc, f, NULL, 1);
     fail_unless(rc == CL_SUCCESS, "cli_bytecode_load failed");
     fclose(f);
 

-- 
Debian repository for ClamAV



More information about the Pkg-clamav-commits mailing list