Beispiel #1
0
static int chm_decompress_stream(int fd, chm_metadata_t *metadata, const char *dirname, cli_ctx *ctx)
{
	lzx_content_t lzx_content;
	lzx_reset_table_t lzx_reset_table;
	lzx_control_t lzx_control;
	int window_bits, length, tmpfd, retval=-1;
	struct lzx_stream * stream;
	char filename[1024];
	struct cab_file file;
	
	snprintf(filename, 1024, "%s"PATHSEP"clamav-unchm.bin", dirname);
	tmpfd = open(filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU);
	if (tmpfd<0) {
		cli_dbgmsg("open failed for %s\n", filename);
		return -1;
	}

	if (!metadata->sys_control.length || !metadata->sys_content.length ||!metadata->sys_reset.length) {
		cli_dbgmsg("Control file missing\n");
		goto abort;
	}

	if (!read_sys_control(metadata, &lzx_control)) {
		goto abort;
	}
	if (!read_sys_content(metadata, &lzx_content)) {
		goto abort;
	}
	if (!read_sys_reset_table(metadata, &lzx_reset_table)) {
		goto abort;
	}
	
	switch (lzx_control.window_size) {
		case 0x008000:
			window_bits = 15;
			break;
		case 0x010000:
			window_bits = 16;
			break;
		case 0x020000:
			window_bits = 17;
			break;
		case 0x040000:
			window_bits = 18;
			break;
		case 0x080000:
			window_bits = 19;
			break;
		case 0x100000:
			window_bits = 20;
			break;
		case 0x200000:
			window_bits = 21;
			break;
		default:
			cli_dbgmsg("bad control window size: 0x%x\n", lzx_control.window_size);
			goto abort;
	}
	
	if (lzx_control.reset_interval % LZX_FRAME_SIZE) {
		cli_dbgmsg("bad reset_interval: 0x%x\n", lzx_control.window_size);
		goto abort;
	}
	
	length = lzx_reset_table.uncom_len;
	length += lzx_control.reset_interval;
	length &= -lzx_control.reset_interval;
	
	cli_dbgmsg("Compressed offset: %lu\n", (unsigned long int) lzx_content.offset);
	if ((uint64_t) lseek(fd, lzx_content.offset, SEEK_SET) != lzx_content.offset) {
		goto abort;
	}

	memset(&file, 0, sizeof(struct cab_file));
	file.max_size = ctx->engine->maxfilesize;
	stream = lzx_init(fd, tmpfd, window_bits,
			lzx_control.reset_interval / LZX_FRAME_SIZE,
			4096, length, &file, NULL);
	if (!stream) {
		cli_dbgmsg("lzx_init failed\n");
		goto abort;
	}
	
	lzx_decompress(stream, length);
	lzx_free(stream);
	
#ifndef _WIN32
	/* Delete the file */
	if(cli_unlink(filename))
		retval = -1;
	else
#endif
		retval = tmpfd;
	
abort:
	if ((retval == -1) && (tmpfd >= 0)) {
		close(tmpfd);
	}
	return retval;
}
Beispiel #2
0
int cab_extract(struct cab_file *file, const char *name)
{
	int ret;


    if(!file || !name) {
	cli_errmsg("cab_extract: !file || !name\n");
	return CL_ENULLARG;
    }

    if(!file->folder) {
	cli_errmsg("cab_extract: file->folder == NULL\n");
	return CL_ENULLARG;
    }

    file->ofd = open(name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU);
    if(file->ofd == -1) {
	cli_errmsg("cab_extract: Can't open file %s in write mode\n", name);
	return CL_ECREAT;
    }

    switch(file->folder->cmethod & 0x000f) {
	case 0x0000: /* STORE */
	    cli_dbgmsg("CAB: Compression method: STORED\n");
	    CAB_CHGFOLDER;
	    if(file->length > file->cab->length) {
		cli_dbgmsg("cab_extract: Stored file larger than archive itself, trimming down\n");
		file->length = file->cab->length;
	    }
	    ret = cab_unstore(file, file->length);
	    break;

	case 0x0001: /* MSZIP */
	    cli_dbgmsg("CAB: Compression method: MSZIP\n");
	    CAB_CHGFOLDER;
	    ret = mszip_decompress(file->cab->state->stream, file->length);
	    break;

	case 0x0002: /* QUANTUM */
	    cli_dbgmsg("CAB: Compression method: QUANTUM\n");
	    CAB_CHGFOLDER;
	    ret = qtm_decompress(file->cab->state->stream, file->length);
	    break;

	case 0x0003: /* LZX */
	    cli_dbgmsg("CAB: Compression method: LZX\n");
	    CAB_CHGFOLDER;
	    ret = lzx_decompress(file->cab->state->stream, file->length);
	    break;

	default:
	    cli_dbgmsg("CAB: Not supported compression method: 0x%x\n", file->folder->cmethod & 0x000f);
	    ret = CL_EFORMAT;
    }

    close(file->ofd);

    if(ret == CL_BREAK)
	ret = CL_SUCCESS;

    return ret;
}