297
285
/* other methods: (blockno+1) * 512 or (blockno * block_size) + 512; */
298
286
offset = (blockno << hdr->log2_big_block_size) + MAX(512, 1 << hdr->log2_big_block_size); /* 512 is header size */
300
if (hdr->m_area == NULL) {
301
if (lseek(fd, offset, SEEK_SET) != offset) {
304
if (cli_readn(fd, buff, size) != size) {
308
offend = offset + size;
309
if ((offend <= 0) || (offend > hdr->m_length)) {
312
memcpy(buff, hdr->m_area+offset, size);
288
offend = offset + size;
289
if ((offend <= 0) || (offend > hdr->m_length)) {
292
if(!(pblock = fmap_need_off_once(hdr->map, offset, size))) {
295
memcpy(buff, pblock, size);
317
static int32_t ole2_get_next_bat_block(int fd, ole2_header_t *hdr, int32_t current_block)
299
static int32_t ole2_get_next_bat_block(ole2_header_t *hdr, int32_t current_block)
319
301
int32_t bat_array_index;
320
302
uint32_t bat[128];
328
310
cli_dbgmsg("bat_array index error\n");
331
if (!ole2_read_block(fd, hdr, &bat, 512,
313
if (!ole2_read_block(hdr, &bat, 512,
332
314
ole2_endian_convert_32(hdr->bat_array[bat_array_index]))) {
335
317
return ole2_endian_convert_32(bat[current_block-(bat_array_index * 128)]);
338
static int32_t ole2_get_next_xbat_block(int fd, ole2_header_t *hdr, int32_t current_block)
320
static int32_t ole2_get_next_xbat_block(ole2_header_t *hdr, int32_t current_block)
340
322
int32_t xbat_index, xbat_block_index, bat_index, bat_blockno;
341
323
uint32_t xbat[128], bat[128];
355
337
bat_index = current_block % 128;
357
if (!ole2_read_block(fd, hdr, &xbat, 512, hdr->xbat_start)) {
339
if (!ole2_read_block(hdr, &xbat, 512, hdr->xbat_start)) {
361
343
/* Follow the chain of XBAT blocks */
362
344
while (xbat_block_index > 0) {
363
if (!ole2_read_block(fd, hdr, &xbat, 512,
345
if (!ole2_read_block(hdr, &xbat, 512,
364
346
ole2_endian_convert_32(xbat[127]))) {
367
349
xbat_block_index--;
370
if (!ole2_read_block(fd, hdr, &bat, 512, ole2_endian_convert_32(xbat[bat_blockno]))) {
352
if (!ole2_read_block(hdr, &bat, 512, ole2_endian_convert_32(xbat[bat_blockno]))) {
374
356
return ole2_endian_convert_32(bat[bat_index]);
377
static int32_t ole2_get_next_block_number(int fd, ole2_header_t *hdr, int32_t current_block)
359
static int32_t ole2_get_next_block_number(ole2_header_t *hdr, int32_t current_block)
379
361
if (current_block < 0) {
383
365
if ((current_block / 128) > 108) {
384
return ole2_get_next_xbat_block(fd, hdr, current_block);
366
return ole2_get_next_xbat_block(hdr, current_block);
386
return ole2_get_next_bat_block(fd, hdr, current_block);
368
return ole2_get_next_bat_block(hdr, current_block);
390
static int32_t ole2_get_next_sbat_block(int fd, ole2_header_t *hdr, int32_t current_block)
372
static int32_t ole2_get_next_sbat_block(ole2_header_t *hdr, int32_t current_block)
392
374
int32_t iter, current_bat_block;
393
375
uint32_t sbat[128];
399
381
current_bat_block = hdr->sbat_start;
400
382
iter = current_block / 128;
401
383
while (iter > 0) {
402
current_bat_block = ole2_get_next_block_number(fd, hdr, current_bat_block);
384
current_bat_block = ole2_get_next_block_number(hdr, current_bat_block);
405
if (!ole2_read_block(fd, hdr, &sbat, 512, current_bat_block)) {
387
if (!ole2_read_block(hdr, &sbat, 512, current_bat_block)) {
408
390
return ole2_endian_convert_32(sbat[current_block % 128]);
411
393
/* Retrieve the block containing the data for the given sbat index */
412
static int32_t ole2_get_sbat_data_block(int fd, ole2_header_t *hdr, void *buff, int32_t sbat_index)
394
static int32_t ole2_get_sbat_data_block(ole2_header_t *hdr, void *buff, int32_t sbat_index)
414
396
int32_t block_count, current_block;
425
407
block_count = sbat_index / (1 << (hdr->log2_big_block_size - hdr->log2_small_block_size));
426
408
current_block = hdr->sbat_root_start;
427
409
while (block_count > 0) {
428
current_block = ole2_get_next_block_number(fd, hdr, current_block);
410
current_block = ole2_get_next_block_number(hdr, current_block);
431
413
/* current_block now contains the block number of the sbat array
432
414
containing the entry for the required small block */
434
return(ole2_read_block(fd, hdr, buff, 1 << hdr->log2_big_block_size, current_block));
416
return(ole2_read_block(hdr, buff, 1 << hdr->log2_big_block_size, current_block));
437
static int ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir, int32_t prop_index,
438
int (*handler)(int fd, ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx),
419
static int ole2_walk_property_tree(ole2_header_t *hdr, const char *dir, int32_t prop_index,
420
int (*handler)(ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx),
439
421
unsigned int rec_level, unsigned int *file_count, cli_ctx *ctx, unsigned long *scansize)
441
423
property_t prop_block[4];
461
443
idx = prop_index / 4;
462
444
for (i=0 ; i < idx ; i++) {
463
current_block = ole2_get_next_block_number(fd, hdr, current_block);
445
current_block = ole2_get_next_block_number(hdr, current_block);
464
446
if (current_block < 0) {
465
447
return CL_SUCCESS;
468
450
idx = prop_index % 4;
469
if (!ole2_read_block(fd, hdr, prop_block, 512,
451
if (!ole2_read_block(hdr, prop_block, 512,
470
452
current_block)) {
471
453
return CL_SUCCESS;
508
490
hdr->sbat_root_start = prop_block[idx].start_block;
510
(ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
512
(ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
514
(ret=ole2_walk_property_tree(fd, hdr, dir,prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
492
(ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
494
(ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
496
(ret=ole2_walk_property_tree(hdr, dir,prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
517
499
case 2: /* File */
522
504
if (!ctx || !ctx->engine->maxfilesize || prop_block[idx].size <= ctx->engine->maxfilesize || prop_block[idx].size <= *scansize) {
524
506
*scansize-=prop_block[idx].size;
525
if ((ret=handler(fd, hdr, &prop_block[idx], dir, ctx)) != CL_SUCCESS)
507
if ((ret=handler(hdr, &prop_block[idx], dir, ctx)) != CL_SUCCESS)
528
510
cli_dbgmsg("OLE2: filesize exceeded\n");
531
(ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].prev, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
533
(ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].next, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
535
(ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].child, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
513
(ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].prev, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
515
(ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].next, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
517
(ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].child, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
538
520
case 1: /* Directory */
540
522
dirname = (char *) cli_malloc(strlen(dir)+8);
541
523
if (!dirname) return CL_BREAK;
542
snprintf(dirname, strlen(dir)+8, "%s/%.6d", dir, prop_index);
524
snprintf(dirname, strlen(dir)+8, "%s"PATHSEP"%.6d", dir, prop_index);
543
525
if (mkdir(dirname, 0700) != 0) {
547
529
cli_dbgmsg("OLE2 dir entry: %s\n",dirname);
548
530
} else dirname = NULL;
550
(ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
552
(ret=ole2_walk_property_tree(fd, hdr, dir,prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
554
(ret=ole2_walk_property_tree(fd, hdr, dirname, prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
532
(ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
534
(ret=ole2_walk_property_tree(hdr, dir,prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
536
(ret=ole2_walk_property_tree(hdr, dirname, prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
556
538
if (dirname) free(dirname);
563
545
return CL_SUCCESS;
565
547
/* Write file Handler - write the contents of the entry to a file */
566
static int handler_writefile(int fd, ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
548
static int handler_writefile(ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
568
550
unsigned char *buff;
569
551
int32_t current_block, ofd, len, offset;
585
567
name = get_property_name2(prop->name, prop->name_size);
586
568
if (name) cnt = uniq_add(hdr->U, name, strlen(name), &hash);
587
569
else cnt = uniq_add(hdr->U, NULL, 0, &hash);
588
snprintf(newname, sizeof(newname), "%s/%s_%u", dir, hash, cnt);
570
snprintf(newname, sizeof(newname), "%s"PATHSEP"%s_%u", dir, hash, cnt);
589
571
newname[sizeof(newname)-1]='\0';
590
572
cli_dbgmsg("OLE2 [handler_writefile]: Dumping '%s' to '%s'\n", name ? name : "<empty>", newname);
591
573
if (name) free(name);
637
619
if (prop->size < (int64_t)hdr->sbat_cutoff) {
638
620
/* Small block file */
639
if (!ole2_get_sbat_data_block(fd, hdr, buff, current_block)) {
621
if (!ole2_get_sbat_data_block(hdr, buff, current_block)) {
640
622
cli_dbgmsg("OLE2 [handler_writefile]: ole2_get_sbat_data_block failed\n");
656
638
len -= MIN(len,1 << hdr->log2_small_block_size);
657
current_block = ole2_get_next_sbat_block(fd, hdr, current_block);
639
current_block = ole2_get_next_sbat_block(hdr, current_block);
659
641
/* Big block file */
660
if (!ole2_read_block(fd, hdr, buff, 1 << hdr->log2_big_block_size, current_block)) {
642
if (!ole2_read_block(hdr, buff, 1 << hdr->log2_big_block_size, current_block)) {
663
645
cli_bitset_free(blk_bitset);
684
666
/* enum file Handler - checks for VBA presence */
685
static int handler_enum(int fd, ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
667
static int handler_enum(ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
764
746
if (prop->size < (int64_t)hdr->sbat_cutoff) {
765
747
/* Small block file */
766
if (!ole2_get_sbat_data_block(fd, hdr, buff, current_block)) {
748
if (!ole2_get_sbat_data_block(hdr, buff, current_block)) {
767
749
cli_dbgmsg("ole2_get_sbat_data_block failed\n");
784
766
len -= MIN(len,1 << hdr->log2_small_block_size);
785
current_block = ole2_get_next_sbat_block(fd, hdr, current_block);
767
current_block = ole2_get_next_sbat_block(hdr, current_block);
787
769
/* Big block file */
788
if (!ole2_read_block(fd, hdr, buff, 1 << hdr->log2_big_block_size, current_block)) {
770
if (!ole2_read_block(hdr, buff, 1 << hdr->log2_big_block_size, current_block)) {
791
773
if (cli_writen(ofd, buff, MIN(len,(1 << hdr->log2_big_block_size))) !=
887
int cli_ole2_extract(int fd, const char *dirname, cli_ctx *ctx, struct uniq **vba)
869
int cli_ole2_extract(const char *dirname, cli_ctx *ctx, struct uniq **vba)
889
871
ole2_header_t hdr;
890
872
int hdr_size, ret=CL_CLEAN;
892
873
unsigned int file_count=0;
893
874
unsigned long scansize, scansize2;
895
877
cli_dbgmsg("in cli_ole2_extract()\n");
906
888
/* size of header - size of other values in struct */
907
889
hdr_size = sizeof(struct ole2_header_tag) - sizeof(int32_t) - sizeof(uint32_t) -
908
sizeof(unsigned char *) - sizeof(off_t) - sizeof(bitset_t *) -
909
sizeof(struct uniq *) - sizeof(int);
913
if (fstat(fd, &statbuf) == 0) {
914
if (statbuf.st_size < hdr_size) {
918
hdr.m_length = statbuf.st_size;
919
hdr.m_area = (unsigned char *) mmap(NULL, hdr.m_length, PROT_READ, MAP_PRIVATE, fd, 0);
920
if (hdr.m_area == MAP_FAILED) {
923
cli_dbgmsg("mmap'ed file\n");
924
memcpy(&hdr, hdr.m_area, hdr_size);
929
if (hdr.m_area == NULL) {
931
#if defined(HAVE_ATTRIB_PACKED) || defined(HAVE_PRAGMA_PACK) || defined(HAVE_PRAGMA_PACK_HPPA)
932
if (cli_readn(fd, &hdr, hdr_size) != hdr_size) {
936
if (!ole2_read_header(fd, &hdr)) {
890
sizeof(off_t) - sizeof(bitset_t *) -
891
sizeof(struct uniq *) - sizeof(int) - sizeof(fmap_t *);
893
if((*ctx->fmap)->len < hdr_size) {
896
hdr.map = *ctx->fmap;
897
hdr.m_length = hdr.map->len;
898
phdr = fmap_need_off_once(hdr.map, 0, hdr_size);
900
memcpy(&hdr, phdr, hdr_size);
902
cli_dbgmsg("cli_ole2_extract: failed to read header\n");
942
906
hdr.minor_version = ole2_endian_convert_16(hdr.minor_version);
943
907
hdr.dll_version = ole2_endian_convert_16(hdr.dll_version);
944
908
hdr.byte_order = ole2_endian_convert_16(hdr.byte_order);
982
946
/* 8 SBAT blocks per file block */
983
hdr.max_block_no = (statbuf.st_size - MAX(512, 1 << hdr.log2_big_block_size)) / (1 << hdr.log2_small_block_size);
947
hdr.max_block_no = (hdr.map->len - MAX(512, 1 << hdr.log2_big_block_size)) / (1 << hdr.log2_small_block_size);
985
949
print_ole2_header(&hdr);
986
950
cli_dbgmsg("Max block number: %lu\n", (unsigned long int) hdr.max_block_no);
988
952
/* PASS 1 : Count files and check for VBA */
990
ret = ole2_walk_property_tree(fd, &hdr, NULL, 0, handler_enum, 0, &file_count, ctx, &scansize);
954
ret = ole2_walk_property_tree(&hdr, NULL, 0, handler_enum, 0, &file_count, ctx, &scansize);
991
955
cli_bitset_free(hdr.bitset);
992
956
hdr.bitset = NULL;
993
957
if (!file_count || !(hdr.bitset = cli_bitset_init()))
1006
ole2_walk_property_tree(fd, &hdr, dirname, 0, handler_writefile, 0, &file_count, ctx, &scansize2);
970
ole2_walk_property_tree(&hdr, dirname, 0, handler_writefile, 0, &file_count, ctx, &scansize2);
1011
975
/* PASS 2/B : OTF scan */
1014
ret = ole2_walk_property_tree(fd, &hdr, NULL, 0, handler_otf, 0, &file_count, ctx, &scansize2);
978
ret = ole2_walk_property_tree(&hdr, NULL, 0, handler_otf, 0, &file_count, ctx, &scansize2);
1019
if (hdr.m_area != NULL) {
1020
munmap(hdr.m_area, hdr.m_length);
1024
983
cli_bitset_free(hdr.bitset);