117
102
#define chm_endian_convert_64(x) le64_to_host(x)
119
104
/* Read in a block of data from either the mmap area or the given fd */
120
static int chm_read_data(int fd, char *dest, off_t offset, off_t len,
121
char *m_area, off_t m_length)
105
static int chm_read_data(fmap_t *map, char *dest, off_t offset, off_t len)
123
if ((offset < 0) || (len < 0) || ((offset+len) < 0)) {
126
if (m_area != NULL) {
127
if ((offset+len) > m_length) {
130
memcpy(dest, m_area+offset, len);
132
if (lseek(fd, offset, SEEK_SET) != offset) {
135
if (cli_readn(fd, dest, len) != len) {
107
void *src = fmap_need_off_once(map, offset, len);
108
if(!src) return FALSE;
109
memcpy(dest, src, len);
142
113
static uint64_t chm_copy_file_data(int ifd, int ofd, uint64_t len)
185
static int itsf_read_header(int fd, chm_itsf_header_t *itsf_hdr, char *m_area, off_t m_length)
156
static int itsf_read_header(chm_metadata_t *metadata)
187
#if defined(HAVE_ATTRIB_PACKED) || defined(HAVE_PRAGMA_PACK) || defined(HAVE_PRAGMA_PACK_HPPA)
188
if (!chm_read_data(fd, (char *) itsf_hdr, 0, CHM_ITSF_MIN_LEN,
193
if (cli_readn(fd, &itsf_hdr->signature, 4) != 4) {
196
if (cli_readn(fd, &itsf_hdr->version, 4) != 4) {
199
if (cli_readn(fd, &itsf_hdr->header_len, 4) != 4) {
202
if (cli_readn(fd, &itsf_hdr->unknown, 4) != 4) {
205
if (cli_readn(fd, &itsf_hdr->last_modified, 4) != 4) {
208
if (cli_readn(fd, &itsf_hdr->lang_id, 4) != 4) {
211
if (cli_readn(fd, &itsf_hdr->dir_clsid, 16) != 16) {
214
if (cli_readn(fd, &itsf_hdr->stream_clsid, 16) != 16) {
217
if (cli_readn(fd, &itsf_hdr->sec0_offset, 8) != 8) {
220
if (cli_readn(fd, &itsf_hdr->sec0_len, 8) != 8) {
223
if (cli_readn(fd, &itsf_hdr->dir_offset, 8) != 8) {
226
if (cli_readn(fd, &itsf_hdr->dir_len, 8) != 8) {
229
if (itsf_hdr->version > 2) {
230
if (cli_readn(fd, &itsf_hdr->data_offset, 8) != 8) {
158
chm_itsf_header_t *itsf_hdr = &metadata->itsf_hdr;
159
if (!chm_read_data(metadata->map, (char *)itsf_hdr, 0, CHM_ITSF_MIN_LEN))
235
161
if (memcmp(itsf_hdr->signature, "ITSF", 4) != 0) {
236
162
cli_dbgmsg("ITSF signature mismatch\n");
270
196
cli_dbgmsg("Lang ID:\t%u\n\n", itsp_hdr->lang_id);
273
static int itsp_read_header(int fd, chm_itsp_header_t *itsp_hdr, off_t offset,
274
char *m_area, off_t m_length)
199
static int itsp_read_header(chm_metadata_t *metadata, off_t offset)
276
#if defined(HAVE_ATTRIB_PACKED) || defined(HAVE_PRAGMA_PACK) || defined(HAVE_PRAGMA_PACK_HPPA)
277
if (!chm_read_data(fd, (char *) itsp_hdr, offset, CHM_ITSP_LEN,
282
if (lseek(fd, offset, SEEK_SET) != offset) {
285
if (cli_readn(fd, &itsp_hdr->signature, 4) != 4) {
288
if (cli_readn(fd, &itsp_hdr->version, 4) != 4) {
291
if (cli_readn(fd, &itsp_hdr->header_len, 4) != 4) {
294
if (cli_readn(fd, &itsp_hdr->unknown1, 4) != 4) {
297
if (cli_readn(fd, &itsp_hdr->block_len, 4) != 4) {
300
if (cli_readn(fd, &itsp_hdr->blockidx_intvl, 4) != 4) {
303
if (cli_readn(fd, &itsp_hdr->index_depth, 4) != 4) {
306
if (cli_readn(fd, &itsp_hdr->index_root, 4) != 4) {
309
if (cli_readn(fd, &itsp_hdr->index_head, 4) != 4) {
312
if (cli_readn(fd, &itsp_hdr->index_tail, 4) != 4) {
315
if (cli_readn(fd, &itsp_hdr->unknown2, 4) != 4) {
318
if (cli_readn(fd, &itsp_hdr->num_blocks, 4) != 4) {
321
if (cli_readn(fd, &itsp_hdr->lang_id, 4) != 4) {
324
if (cli_readn(fd, &itsp_hdr->system_clsid, 16) != 16) {
327
if (cli_readn(fd, &itsp_hdr->unknown4, 16) != 16) {
201
chm_itsp_header_t *itsp_hdr = &metadata->itsp_hdr;
202
if (!chm_read_data(metadata->map, (char *)itsp_hdr, offset, CHM_ITSP_LEN))
331
204
if (memcmp(itsp_hdr->signature, "ITSP", 4) != 0) {
332
205
cli_dbgmsg("ITSP signature mismatch\n");
453
326
return CL_EFORMAT;
456
if (metadata->m_area != NULL) {
457
if (metadata->chunk_offset > metadata->m_length) {
460
if ((metadata->chunk_offset + metadata->itsp_hdr.block_len) > metadata->m_length) {
463
metadata->chunk_data = metadata->m_area + metadata->chunk_offset;
329
if (metadata->chunk_offset > metadata->m_length) {
332
if ((metadata->chunk_offset + metadata->itsp_hdr.block_len) > metadata->m_length) {
335
metadata->chunk_data = fmap_need_off_once(metadata->map, metadata->chunk_offset, metadata->itsp_hdr.block_len);
336
if(!metadata->chunk_data) return CL_EFORMAT;
466
if (!metadata->chunk_data) {
467
metadata->chunk_data = (char *) cli_malloc(metadata->itsp_hdr.block_len);
468
if (!metadata->chunk_data) {
472
if (lseek(fd, metadata->chunk_offset, SEEK_SET) != metadata->chunk_offset) {
475
if ((uint32_t) cli_readn(fd, metadata->chunk_data, metadata->itsp_hdr.block_len) != metadata->itsp_hdr.block_len) {
479
338
metadata->chunk_current = metadata->chunk_data + CHM_CHUNK_HDR_LEN;
480
339
metadata->chunk_end = metadata->chunk_data + metadata->itsp_hdr.block_len;
483
342
metadata->chunk_entries = (uint16_t)((((uint8_t const *)(metadata->chunk_data))[metadata->itsp_hdr.block_len-2] << 0)
484
343
| (((uint8_t const *)(metadata->chunk_data))[metadata->itsp_hdr.block_len-1] << 8));
485
344
} else if (memcmp(metadata->chunk_data, "PMGI", 4) != 0) {
486
if (!metadata->m_area && metadata->chunk_data) {
487
free(metadata->chunk_data);
492
348
return CL_SUCCESS;
494
if (!metadata->m_area && metadata->chunk_data) {
495
free(metadata->chunk_data);
496
metadata->chunk_data = NULL;
501
351
static void print_sys_control(lzx_control_t *lzx_control)
529
#if defined(HAVE_ATTRIB_PACKED) || defined(HAVE_PRAGMA_PACK) || defined(HAVE_PRAGMA_PACK_HPPA)
530
if (!chm_read_data(fd, (char *) lzx_control, offset, CHM_CONTROL_LEN,
531
metadata->m_area, metadata->m_length)) {
535
if (lseek(fd, offset, SEEK_SET) != offset) {
538
if (cli_readn(fd, &lzx_control->length, 4) != 4) {
541
if (cli_readn(fd, &lzx_control->signature, 4) != 4) {
544
if (cli_readn(fd, &lzx_control->version, 4) != 4) {
547
if (cli_readn(fd, &lzx_control->reset_interval, 4) != 4) {
550
if (cli_readn(fd, &lzx_control->window_size, 4) != 4) {
553
if (cli_readn(fd, &lzx_control->cache_size, 4) != 4) {
379
if (!chm_read_data(metadata->map, (char *) lzx_control, offset, CHM_CONTROL_LEN)) {
557
383
lzx_control->length = chm_endian_convert_32(lzx_control->length);
558
384
lzx_control->version = chm_endian_convert_32(lzx_control->version);
559
385
lzx_control->reset_interval = chm_endian_convert_32(lzx_control->reset_interval);
591
417
cli_dbgmsg("Length:\t%lu\n\n", (unsigned long int) lzx_content->length);
594
static int read_sys_content(int fd, chm_metadata_t *metadata, lzx_content_t *lzx_content)
420
static int read_sys_content(chm_metadata_t *metadata, lzx_content_t *lzx_content)
596
422
lzx_content->offset = metadata->itsf_hdr.data_offset + metadata->sys_content.offset;
597
423
lzx_content->length = metadata->sys_content.length;
632
458
/* Save the entry offset for later use */
633
459
lzx_reset_table->rt_offset = offset-4;
635
#if defined(HAVE_ATTRIB_PACKED) || defined(HAVE_PRAGMA_PACK) || defined(HAVE_PRAGMA_PACK_HPPA)
636
if (!chm_read_data(fd, (char *) lzx_reset_table, offset, CHM_RESET_TABLE_LEN,
637
metadata->m_area, metadata->m_length)) {
641
if (lseek(fd, offset, SEEK_SET) != offset) {
644
if (cli_readn(fd, &lzx_reset_table->num_entries, 4) != 4) {
647
if (cli_readn(fd, &lzx_reset_table->entry_size, 4) != 4) {
650
if (cli_readn(fd, &lzx_reset_table->table_offset, 4) != 4) {
653
if (cli_readn(fd, &lzx_reset_table->uncom_len, 8) != 8) {
656
if (cli_readn(fd, &lzx_reset_table->com_len, 8) != 8) {
659
if (cli_readn(fd, &lzx_reset_table->frame_len, 8) != 8) {
461
if (!chm_read_data(metadata->map, (char *) lzx_reset_table, offset, CHM_RESET_TABLE_LEN)) {
663
465
lzx_reset_table->num_entries = chm_endian_convert_32(lzx_reset_table->num_entries);
664
466
lzx_reset_table->entry_size = chm_endian_convert_32(lzx_reset_table->entry_size);
665
467
lzx_reset_table->table_offset = chm_endian_convert_32(lzx_reset_table->table_offset);
693
495
char filename[1024];
694
496
struct cab_file file;
696
snprintf(filename, 1024, "%s/clamav-unchm.bin", dirname);
498
snprintf(filename, 1024, "%s"PATHSEP"clamav-unchm.bin", dirname);
697
499
tmpfd = open(filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU);
699
501
cli_dbgmsg("open failed for %s\n", filename);
708
if (!read_sys_control(fd, metadata, &lzx_control)) {
711
if (!read_sys_content(fd, metadata, &lzx_content)) {
714
if (!read_sys_reset_table(fd, metadata, &lzx_reset_table)) {
510
if (!read_sys_control(metadata, &lzx_control)) {
513
if (!read_sys_content(metadata, &lzx_content)) {
516
if (!read_sys_reset_table(metadata, &lzx_reset_table)) {
805
607
if (metadata->ufd >= 0) {
806
608
close(metadata->ufd);
808
if (!metadata->m_area && metadata->chunk_data) {
809
free(metadata->chunk_data);
812
if (metadata->m_area) {
813
munmap(metadata->m_area, metadata->m_length);
610
funmap(metadata->map);
818
int cli_chm_extract_file(int fd, char *dirname, chm_metadata_t *metadata, cli_ctx *ctx)
613
int cli_chm_extract_file(char *dirname, chm_metadata_t *metadata, cli_ctx *ctx)
820
615
char filename[1024];
826
621
cli_dbgmsg("seek in uncompressed stream failed\n");
827
622
return CL_EFORMAT;
829
snprintf(filename, 1024, "%s/%lu.chm", dirname, (unsigned long int) metadata->file_offset);
624
snprintf(filename, 1024, "%s"PATHSEP"%lu.chm", dirname, (unsigned long int) metadata->file_offset);
830
625
metadata->ofd = open(filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU);
831
626
if (metadata->ofd < 0) {
832
627
return CL_ECREAT;
852
647
if (metadata->num_chunks == 0) {
855
if ((retval = read_chunk(metadata, fd)) != CL_SUCCESS) {
650
if ((retval = read_chunk(metadata)) != CL_SUCCESS) {
858
653
metadata->num_chunks--;
859
654
metadata->chunk_offset += metadata->itsp_hdr.block_len;
861
retval = prepare_file(fd, metadata);
656
retval = prepare_file(metadata);
862
657
} while (retval == CL_BREAK); /* Ran out of chunk entries before finding a file */
878
672
if (fstat(fd, &statbuf) == 0) {
879
673
if (statbuf.st_size < CHM_ITSF_MIN_LEN) {
882
676
metadata->m_length = statbuf.st_size;
883
metadata->m_area = (char *) mmap(NULL, metadata->m_length, PROT_READ, MAP_PRIVATE, fd, 0);
884
if (metadata->m_area == MAP_FAILED) {
885
metadata->m_area = NULL;
677
metadata->map = fmap(fd, 0, metadata->m_length);
678
if (!metadata->map) {
890
if (!itsf_read_header(fd, &metadata->itsf_hdr, metadata->m_area, metadata->m_length)) {
683
if (!itsf_read_header(metadata)) {
893
686
itsf_print_header(&metadata->itsf_hdr);
895
if (!itsp_read_header(fd, &metadata->itsp_hdr, metadata->itsf_hdr.dir_offset, metadata->m_area, metadata->m_length)) {
688
if (!itsp_read_header(metadata, metadata->itsf_hdr.dir_offset)) {
898
691
itsp_print_header(&metadata->itsp_hdr);