[Pkg-clamav-commits] [SCM] Debian repository for ClamAV branch, debian/unstable, updated. debian/0.95+dfsg-1-6156-g094ec9b

aCaB acab at clamav.net
Sun Apr 4 00:58:45 UTC 2010


The following commit has been merged in the debian/unstable branch:
commit f0b36be445ff6539197b75b84fb598b6a597ae8c
Author: aCaB <acab at clamav.net>
Date:   Tue Jul 14 19:42:27 2009 +0200

    add is_extract_cab

diff --git a/libclamav/ishield.c b/libclamav/ishield.c
index 1adc715..6b65f8a 100644
--- a/libclamav/ishield.c
+++ b/libclamav/ishield.c
@@ -250,11 +250,11 @@ int cli_scanishield_msi(int desc, cli_ctx *ctx, off_t off) {
 	    csize -= z.avail_in;
 	    z.next_in = buf;
 	    do {
-		int def;
+		int inf;
 		z.avail_out = sizeof(obuf);
 		z.next_out = obuf;
-		def = inflate(&z, 0);
-		if(def != Z_OK && def != Z_STREAM_END && def != Z_BUF_ERROR) {
+		inf = inflate(&z, 0);
+		if(inf != Z_OK && inf != Z_STREAM_END && inf != Z_BUF_ERROR) {
 		    cli_dbgmsg("ishield-msi: bad stream\n");
 		    csize = 0;
 		    lseek(desc, csize, SEEK_CUR);
@@ -307,8 +307,8 @@ struct IS_CABSTUFF {
 };
 
 static void md5str(uint8_t *sum);
-static int is_parse_hdr(int desc, struct IS_CABSTUFF *c);
-
+static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c);
+static int is_extract_cab(int desc, cli_ctx *ctx, uint64_t off, uint64_t size, uint64_t csize);
 
 /* Extract the content of older (non-MSI) IS */
 int cli_scanishield(int desc, cli_ctx *ctx, off_t off, size_t sz) {
@@ -392,7 +392,7 @@ int cli_scanishield(int desc, cli_ctx *ctx, off_t off, size_t sz) {
     }
 
     if(ret == CL_CLEAN && (c.cabcnt || c.hdr != -1)) {
-	if(is_parse_hdr(desc, &c) == CL_CLEAN /* FIXMEISHIELD */) {
+	if(is_parse_hdr(desc, ctx, &c) == CL_CLEAN /* FIXMEISHIELD */) {
 	    unsigned int i;
 	    if(c.hdr != -1) ret = is_dump_and_scan(desc, ctx, c.hdr, c.hdrsz);
 	    for(i=0; i<c.cabcnt && ret == CL_CLEAN; i++) {
@@ -461,7 +461,7 @@ struct IS_HDR {
 };
 
 
-static int is_parse_hdr(int desc, struct IS_CABSTUFF *c) { /* FIXMEISHIELD: tell parent whether we completed the task or not */
+static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c) { /* FIXMEISHIELD: tell parent whether we completed the task or not */
     uint32_t h1_data_off, objs_files_cnt, objs_dirs_off;
     unsigned int off, i;
     char hash[33], *hdr;
@@ -472,10 +472,10 @@ static int is_parse_hdr(int desc, struct IS_CABSTUFF *c) { /* FIXMEISHIELD: tell
 
     /* FIXMEISHIELD: sanitize c here */
 
-    if(!(hdr = (char *)cli_malloc(c->hdrsz)))
+    if(!(hdr = (char *)cli_malloc(c->hdrsz))) /* FIXMEISHIELD: mmap if large */
 	return CL_EMEM;
 
-    if(pread(desc, hdr, c->hdrsz, c->hdr) < c->hdrsz) {
+    if(pread(desc, hdr, c->hdrsz, c->hdr) < (ssize_t)c->hdrsz) {
 	cli_errmsg("is_parse_hdr: short read for header\n");
 	free(hdr);
 	return CL_EREAD;
@@ -574,7 +574,11 @@ static int is_parse_hdr(int desc, struct IS_CABSTUFF *c) { /* FIXMEISHIELD: tell
 		    cli_errmsg("is_parse_hdr: not scanned (dup)\n");
 		else {
 		    if(file->size) { /* FIXMEISHIELD: limits */
-			//is_extract(inhash, hash, file->stream_off, file->size, file->csize);
+			int ret = is_extract_cab(desc, ctx, le64_to_host(file->stream_off), le64_to_host(file->size), le64_to_host(file->csize));
+			if(ret != CL_CLEAN) {
+			    free(hdr);
+			    return ret;
+			}
 		    }
 		}
 		break;
@@ -585,7 +589,8 @@ static int is_parse_hdr(int desc, struct IS_CABSTUFF *c) { /* FIXMEISHIELD: tell
 	    cli_errmsg("is_parse_hdr: FILEITEM out of bounds\n");
 	off+=sizeof(*file);
     }
-    return 0;
+    free(hdr);
+    return CL_CLEAN;
 }
 
 
@@ -601,3 +606,115 @@ static void md5str(uint8_t *sum) {
     }
     sum[32] = '\0';
 }
+
+
+#define IS_CABBUFSZ 65536
+
+static int is_extract_cab(int desc, cli_ctx *ctx, uint64_t off, uint64_t size, uint64_t csize) {
+    uint8_t *inbuf, *outbuf;
+    char *tempfile;
+    FILE *in;
+    int ofd, ret = CL_CLEAN;
+    z_stream z;
+    uint64_t outsz = 0;
+    int success = 0;
+
+    if((ofd=dup(desc)) < 0) {
+	cli_errmsg("is_extract_cab: dup failed\n");
+	return CL_EDUP;
+    }
+    if(!(in = fdopen(ofd, "rb"))) {
+	cli_errmsg("is_extract_cab: fdopen failed\n");
+	close(ofd);
+	return CL_EOPEN;
+    }
+    if(fseeko(in, off, SEEK_SET)) {
+	cli_errmsg("is_extract_cab: fseek failed\n");
+	fclose(in);
+	return CL_ESEEK;
+    }
+    if(!(inbuf = cli_malloc(IS_CABBUFSZ))) {
+	fclose(in);
+	return CL_EMEM;
+    }
+    if(!(outbuf = cli_malloc(IS_CABBUFSZ))) {
+	free(inbuf);
+	fclose(in);
+	return CL_EMEM;
+    }
+    if(!(tempfile = cli_gentemp(ctx->engine->tmpdir))) return CL_EMEM;
+    if((ofd = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRUSR|S_IWUSR)) < 0) {
+	cli_errmsg("is_extract_cab: failed to create file %s\n", tempfile);
+	free(tempfile);
+	fclose(in);
+	return CL_ECREAT;
+    }
+
+    while(csize) {
+	uint16_t chunksz;
+	success = 0;
+	if(csize<2) {
+	    cli_errmsg("is_extract_cab: no room for chunk size\n");
+	    break;
+	}
+	csize -= 2;
+	if(!fread(outbuf, 2, 1, in)) {
+	    cli_dbgmsg("is_extract_cab: short read for chunk size\n");
+	    break;
+	}
+	chunksz = outbuf[0] | (outbuf[1] << 8);
+	if(!chunksz) {
+	    cli_dbgmsg("is_extract_cab: zero sized chunk\n");
+	    continue;
+	}
+	if(csize < chunksz) {
+	    cli_dbgmsg("is_extract_cab: chunk is bigger than csize\n");
+	    break;
+	}
+	csize -= chunksz;
+	if(!fread(inbuf, chunksz, 1, in)) {
+	    cli_dbgmsg("is_extract_cab: short read for chunk\n");
+	    break;
+	}
+	memset(&z, 0, sizeof(z));
+	inflateInit2(&z, -MAX_WBITS);
+	z.next_in = (uint8_t *)inbuf;
+	z.avail_in = chunksz;
+	while(1) {
+	    int zret;
+	    z.next_out = outbuf;
+	    z.avail_out = IS_CABBUFSZ;
+	    zret = inflate(&z, 0);
+	    if(zret == Z_OK || zret == Z_STREAM_END || zret == Z_BUF_ERROR) {
+		unsigned int umpd = IS_CABBUFSZ - z.avail_out;
+		if(cli_writen(ofd, outbuf, umpd) < (ssize_t)umpd)
+		    break;
+		outsz += umpd;
+		if(zret == Z_STREAM_END || z.avail_out == IS_CABBUFSZ /* FIXMEISHIELD: is the latter ok? */) {
+		    success = 1;
+		    break;
+		}
+		continue;
+	    }
+	    cli_dbgmsg("is_extract_cab: file decompression failed with %d\n", zret);
+	    break;
+	}
+	inflateEnd(&z);
+	if(!success) break;
+    }
+    fclose(in);
+    if(success) {
+	if (outsz != size)
+	    cli_dbgmsg("is_extract_cab: extracted %llu bytes to %s, expected %llu, scanning anyway.\n", outsz, tempfile, size);
+	else
+	    cli_dbgmsg("is_extract_cab: extracted to %s\n", tempfile);
+	lseek(ofd, 0, SEEK_SET);
+	ret = cli_magic_scandesc(ofd, ctx);
+    }
+
+    close(ofd);
+    if(!ctx->engine->keeptmp)
+	if(cli_unlink(tempfile)) ret = CL_EUNLINK;
+    free(tempfile);
+    return success ? ret : CL_CLEAN;
+}

-- 
Debian repository for ClamAV



More information about the Pkg-clamav-commits mailing list