Esempio n. 1
0
/**
 * Identify regions in the partition list where there are unused sectors
 * and create new entries for them.
 *
 * @param a_vs Pointer to open volume system
 * @returns 1 on error and 0 on success
 */
uint8_t
tsk_vs_part_unused(TSK_VS_INFO * a_vs)
{
    TSK_VS_PART_INFO *part = a_vs->part_list;
    TSK_DADDR_T prev_end = 0;

    /* prev_ent is set to where the previous entry stopped  plus 1 */
    for (part = a_vs->part_list; part != NULL; part = part->next) {

        // ignore the META volume
        if (part->flags & TSK_VS_PART_FLAG_META)
            continue;

        // there is space before current and previous volume
        if (part->start > prev_end) {
            char *str;
            if ((str = tsk_malloc(12)) == NULL)
                return 1;

            snprintf(str, 12, "Unallocated");
            if (NULL == tsk_vs_part_add(a_vs, prev_end,
                    part->start - prev_end, TSK_VS_PART_FLAG_UNALLOC, str,
                    -1, -1)) {
                free(str);
                return 1;
            }
        }

        prev_end = part->start + part->len;
    }

    /* Is there unallocated space at the end? */
    if (prev_end < (TSK_DADDR_T) (a_vs->img_info->size / a_vs->block_size)) {
        char *str;
        if ((str = tsk_malloc(12)) == NULL)
            return 1;

        snprintf(str, 12, "Unallocated");
        if (NULL == tsk_vs_part_add(a_vs, prev_end,
                a_vs->img_info->size / a_vs->block_size - prev_end,
                TSK_VS_PART_FLAG_UNALLOC, str, -1, -1)) {
            free(str);
            return 1;
        }
    }

    return 0;
}
Esempio n. 2
0
/* load a sparc disk label, this is called from the general
 * sun_load_table
 */
static uint8_t
sun_load_table_sparc(TSK_VS_INFO * vs, sun_dlabel_sparc * dlabel_sp)
{
    uint32_t idx = 0;
    uint32_t cyl_conv;
    TSK_DADDR_T max_addr = (vs->img_info->size - vs->offset) / vs->block_size;  // max sector

    /* The value to convert cylinders to sectors */
    cyl_conv = tsk_getu16(vs->endian, dlabel_sp->sec_per_tr) *
        tsk_getu16(vs->endian, dlabel_sp->num_head);

    if (tsk_verbose)
        tsk_fprintf(stderr, "load_table_sparc: Number of partitions: %d\n",
            tsk_getu16(vs->endian, dlabel_sp->num_parts));

    /* Cycle through the partitions, there are either 8 or 16 */
    for (idx = 0; idx < tsk_getu16(vs->endian, dlabel_sp->num_parts);
        idx++) {
        TSK_VS_PART_FLAG_ENUM ptype = TSK_VS_PART_FLAG_ALLOC;
        uint32_t part_start = cyl_conv * tsk_getu32(vs->endian,
            dlabel_sp->part_layout[idx].start_cyl);

        uint32_t part_size = tsk_getu32(vs->endian,
            dlabel_sp->part_layout[idx].size_blk);

        if (tsk_verbose)
            tsk_fprintf(stderr,
                "load_table_sparc: %" PRIu32
                "  Starting Sector: %" PRIu32 "  Size: %" PRIu32
                "  Type: %" PRIu16 "\n", idx, part_start, part_size,
                tsk_getu16(vs->endian, dlabel_sp->part_meta[idx].type));

        if (part_size == 0)
            continue;

        // make sure the first couple are in the image bounds
        if ((idx < 2) && (part_start > max_addr)) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_VS_BLK_NUM);
            tsk_error_set_errstr
                ("sun_load_sparc: Starting sector too large for image");
            return 1;
        }

        // set the entry that covers the entire disk image as DESC
        if ((tsk_getu16(vs->endian, dlabel_sp->part_meta[idx].type) == 5)
            && (part_start == 0))
            ptype = TSK_VS_PART_FLAG_META;

        /* Add the partition to the internal sorted list */
        if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) part_start,
                (TSK_DADDR_T) part_size, ptype,
                sun_get_desc(tsk_getu16(vs->endian,
                        dlabel_sp->part_meta[idx].type)), -1, idx))
            return 1;

    }

    return 0;
}
Esempio n. 3
0
static uint8_t
sun_load_table_i386(TSK_VS_INFO * vs, sun_dlabel_i386 * dlabel_x86)
{
    uint32_t idx = 0;
    TSK_DADDR_T max_addr = (vs->img_info->size - vs->offset) / vs->block_size;  // max sector

    if (tsk_verbose)
        tsk_fprintf(stderr, "load_table_i386: Number of partitions: %d\n",
            tsk_getu16(vs->endian, dlabel_x86->num_parts));

    /* Cycle through the partitions, there are either 8 or 16 */
    for (idx = 0; idx < tsk_getu16(vs->endian, dlabel_x86->num_parts);
        idx++) {

        TSK_VS_PART_FLAG_ENUM ptype = TSK_VS_PART_FLAG_ALLOC;

        if (tsk_verbose)
            tsk_fprintf(stderr,
                "load_table_i386: %" PRIu32
                "  Starting Sector: %" PRIu32 "  Size: %" PRIu32
                "  Type: %" PRIu16 "\n", idx, tsk_getu32(vs->endian,
                    dlabel_x86->part[idx].start_sec),
                tsk_getu32(vs->endian, dlabel_x86->part[idx].size_sec),
                tsk_getu16(vs->endian, dlabel_x86->part[idx].type));

        if (tsk_getu32(vs->endian, dlabel_x86->part[idx].size_sec) == 0)
            continue;

        // make sure the first couple are in the image bounds
        if ((idx < 2) && (tsk_getu32(vs->endian,
                    dlabel_x86->part[idx].start_sec) > max_addr)) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_VS_BLK_NUM);
            tsk_error_set_errstr
                ("sun_load_i386: Starting sector too large for image");
            return 1;
        }

        // set the entry that covers the entire disk image as DESC
        if ((tsk_getu16(vs->endian, dlabel_x86->part[idx].type) == 5)
            && (tsk_getu32(vs->endian,
                    dlabel_x86->part[idx].start_sec) == 0))
            ptype = TSK_VS_PART_FLAG_META;

        /* Add the partition to the internal sorted list */
        if (NULL == tsk_vs_part_add(vs,
                (TSK_DADDR_T) tsk_getu32(vs->endian,
                    dlabel_x86->part[idx].start_sec),
                (TSK_DADDR_T) tsk_getu32(vs->endian,
                    dlabel_x86->part[idx].size_sec), ptype,
                sun_get_desc(tsk_getu16(vs->endian,
                        dlabel_x86->part[idx].type)), -1, idx)) {
            return 1;
        }
    }

    return 0;
}
Esempio n. 4
0
/* 
 * Process the partition table at the sector address 
 * 
 * It is loaded into the internal sorted list 
 */
static uint8_t
gpt_load_table(TSK_VS_INFO * vs)
{
    gpt_head *head;
    gpt_entry *ent;
    dos_sect *dos_part;
    unsigned int i, a;
    uint32_t ent_size;
    char *safe_str, *head_str, *tab_str, *ent_buf;
    ssize_t cnt;
    char *sect_buf;
    TSK_DADDR_T taddr = vs->offset / vs->block_size + GPT_PART_SOFFSET;
    TSK_DADDR_T max_addr = (vs->img_info->size - vs->offset) / vs->block_size;  // max sector

    if (tsk_verbose)
        tsk_fprintf(stderr, "gpt_load_table: Sector: %" PRIuDADDR "\n",
            taddr);

    if ((sect_buf = tsk_malloc(vs->block_size)) == NULL)
        return 1;
    dos_part = (dos_sect *) sect_buf;

    cnt = tsk_vs_read_block
        (vs, GPT_PART_SOFFSET, sect_buf, vs->block_size);
    /* if -1, then tsk_errno is already set */
    if (cnt != vs->block_size) {
        if (cnt >= 0) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_VS_READ);
        }
        tsk_error_set_errstr2
            ("Error reading DOS safety partition table in Sector: %"
            PRIuDADDR, taddr);
        free(sect_buf);
        return 1;
    }

    /* Sanity Check */
    if (tsk_vs_guessu16(vs, dos_part->magic, DOS_MAGIC)) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
        tsk_error_set_errstr
            ("Missing DOS safety partition (invalid magic) (Sector: %"
            PRIuDADDR ")", taddr);
        free(sect_buf);
        return 1;
    }

    if (dos_part->ptable[0].ptype != GPT_DOS_TYPE) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
        tsk_error_set_errstr
            ("Missing DOS safety partition (invalid type in table: %d)",
            dos_part->ptable[0].ptype);
        free(sect_buf);
        return 1;
    }

    /* Read the GPT header */
    head = (gpt_head *) sect_buf;
    cnt = tsk_vs_read_block
        (vs, GPT_PART_SOFFSET + 1, sect_buf, vs->block_size);
    if (cnt != vs->block_size) {
        if (cnt >= 0) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_VS_READ);
        }
        tsk_error_set_errstr2("GPT Header structure in Sector: %"
            PRIuDADDR, taddr + 1);
        free(sect_buf);
        return 1;
    }

    if (tsk_getu64(vs->endian, &head->signature) != GPT_HEAD_SIG) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
        tsk_error_set_errstr("GPT Header: %" PRIx64, tsk_getu64(vs->endian,
                &head->signature));
        free(sect_buf);
        return 1;
    }

    // now that we checked the sig, lets make the meta  entries
    if ((safe_str = tsk_malloc(16)) == NULL) {
        free(sect_buf);
        return 1;
    }

    snprintf(safe_str, 16, "Safety Table");
    if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) 0, (TSK_DADDR_T) 1,
            TSK_VS_PART_FLAG_META, safe_str, -1, -1)) {
        free(sect_buf);
        return 1;
    }


    if ((head_str = tsk_malloc(16)) == NULL) {
        free(sect_buf);
        return 1;
    }

    snprintf(head_str, 16, "GPT Header");
    if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) 1,
            (TSK_DADDR_T) ((tsk_getu32(vs->endian,
                        &head->head_size_b) + (vs->block_size-1)) / vs->block_size),
            TSK_VS_PART_FLAG_META, head_str, -1, -1)) {
        free(sect_buf);
        return 1;
    }

    /* Allocate a buffer for each table entry */
    ent_size = tsk_getu32(vs->endian, &head->tab_size_b);
    if (ent_size < sizeof(gpt_entry)) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
        tsk_error_set_errstr("Header reports partition entry size of %"
            PRIu32 " and not %" PRIuSIZE "", ent_size, sizeof(gpt_entry));
        free(sect_buf);
        return 1;
    }

    if ((tab_str = tsk_malloc(20)) == NULL) {
        free(sect_buf);
        return 1;
    }

    snprintf(tab_str, 20, "Partition Table");
    if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) tsk_getu64(vs->endian,
                &head->tab_start_lba),
            (TSK_DADDR_T) ((ent_size * tsk_getu32(vs->endian,
                        &head->tab_num_ent) + (vs->block_size-1)) / vs->block_size),
            TSK_VS_PART_FLAG_META, tab_str, -1, -1)) {
        free(sect_buf);
        return 1;
    }


    /* Process the partition table */
    if ((ent_buf = tsk_malloc(vs->block_size)) == NULL) {
        free(sect_buf);
        return 1;
    }

    i = 0;
    for (a = 0; i < tsk_getu32(vs->endian, &head->tab_num_ent); a++) {
        char *name;

        /* Read a sector */
        cnt = tsk_vs_read_block(vs,
            tsk_getu64(vs->endian, &head->tab_start_lba) + a,
            ent_buf, vs->block_size);
        if (cnt != vs->block_size) {
            if (cnt >= 0) {
                tsk_error_reset();
                tsk_error_set_errno(TSK_ERR_VS_READ);
            }
            tsk_error_set_errstr2
                ("Error reading GPT partition table sector : %" PRIuDADDR,
                tsk_getu64(vs->endian, &head->tab_start_lba) + a);
            free(ent_buf);
            free(sect_buf);
            return 1;
        }

        /* Process the sector */
        ent = (gpt_entry *) ent_buf;
        for (; (uintptr_t) ent < (uintptr_t) ent_buf + vs->block_size &&
            i < tsk_getu32(vs->endian, &head->tab_num_ent); i++) {

            UTF16 *name16;
            UTF8 *name8;
            int retVal;

            if (tsk_verbose)
                tsk_fprintf(stderr,
                    "gpt_load: %d  Starting Sector: %" PRIu64
                    "  End: %" PRIu64 " Flag: %" PRIx64 "\n", i,
                    tsk_getu64(vs->endian, ent->start_lba),
                    tsk_getu64(vs->endian, ent->end_lba),
                    tsk_getu64(vs->endian, ent->flags));


            if (tsk_getu64(vs->endian, ent->start_lba) == 0) {
                ent++;
                continue;
            }

            // make sure the first couple are in the image bounds
            if ((i < 2)
                && (tsk_getu64(vs->endian, ent->start_lba) > max_addr)) {
                tsk_error_reset();
                tsk_error_set_errno(TSK_ERR_VS_BLK_NUM);
                tsk_error_set_errstr
                    ("gpt_load_table: Starting sector too large for image");
                free(sect_buf);
                free(ent_buf);
                return 1;
            }


            if ((name = tsk_malloc(256)) == NULL) {
                free(sect_buf);
                free(ent_buf);
                return 1;
            }

            name16 = (UTF16 *) ((uintptr_t) ent->name);
            name8 = (UTF8 *) name;

            retVal =
                tsk_UTF16toUTF8(vs->endian, (const UTF16 **) &name16,
                (UTF16 *) ((uintptr_t) name16 + sizeof(ent->name)),
                &name8,
                (UTF8 *) ((uintptr_t) name8 + 256), TSKlenientConversion);

            if (retVal != TSKconversionOK) {
                if (tsk_verbose)
                    tsk_fprintf(stderr,
                        "gpt_load_table: Error converting name to UTF8: %d\n",
                        retVal);
                *name = '\0';
            }

            if (NULL == tsk_vs_part_add(vs,
                    (TSK_DADDR_T) tsk_getu64(vs->endian, ent->start_lba),
                    (TSK_DADDR_T) (tsk_getu64(vs->endian,
                            ent->end_lba) - tsk_getu64(vs->endian,
                            ent->start_lba) + 1), TSK_VS_PART_FLAG_ALLOC,
                    name, -1, i)) {
                free(sect_buf);
                free(ent_buf);
                return 1;
            }

            ent++;
        }
    }

    free(sect_buf);
    free(ent_buf);
    return 0;
}
Esempio n. 5
0
/* 
 * Given the path to the file, open it and load the internal
 * partition table structure
 *
 * offset is the byte offset to the start of the volume system
 *
 * If test is 1 then additional tests are performed to make sure 
 * it isn't a FAT or NTFS file system. This is used when autodetection
 * is being used to detect the volume system type. 
 */
TSK_VS_INFO *
tsk_vs_xtaf_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset, uint8_t test)
{
    TSK_VS_INFO *vs;
    ssize_t cnt = 0;
    char* xtaf_buffer[4];
    
    unsigned int sector_size;
    /* Offsets and lengths are hard-coded, except for the user data partition length. */
    /* Offsets are in bytes */
//    TSK_DADDR_T known_xtaf_offsets[] = {0x80000, 0x80080000, 0x10C080000, 0x118EB0000, 0x120eb0000, 0x130eb0000};
    TSK_DADDR_T known_xtaf_offsets[] = {1024, 4195328, 8782848, 9205120, 9467264, 9991552};
    /* Lengths are in sectors */
    TSK_DADDR_T known_xtaf_lengths[] = {4194304, 4587520, 422272 , 262144 , 524288 , 0};
    /* Partition labels c/o the Free60 Wiki: http://free60.org/FATX */
    char* known_xtaf_labels[] = {
      "XTAF (System Cache)",
      "XTAF (Game Cache)",
      "XTAF (System Extended)",
      "XTAF (System Extended 2)",
      "XTAF (Compatibility)",
      "XTAF (System)"
    }; //AJN: Recall that the label passed to tsk_vs_part_add must be malloc'ed.
    TSK_VS_PART_INFO* part;
    TSK_DADDR_T partition_offset;
    TSK_DADDR_T partition_length;
    int itor;
    char *part_label;
    int rc_verifysb;
    int partition_tally = 0;

    /* Clean up any errors that are lying around. */
    tsk_error_reset();

    /* Zero out buffer before reading */
    memset(xtaf_buffer, 0, sizeof(xtaf_buffer));

    sector_size = img_info->sector_size;
    if (0 == sector_size) {
        tsk_fprintf(stderr, "tsk_vs_xtaf_open: img_info has the sector size of this image as 0 bytes.  Guessing 512 instead, but this should be fixed.\n");
        sector_size = 512;
    }

    vs = (TSK_VS_INFO *) tsk_malloc(sizeof(*vs));
    if (vs == NULL)
        return NULL;

    vs->vstype = TSK_VS_TYPE_XTAF;
    vs->tag = TSK_VS_INFO_TAG;
    vs->img_info = img_info;
    vs->offset = offset;

    /* inititialize settings */
    vs->part_list = NULL;
    vs->endian = 0x02; /*AJN TODO Setting this to TSK_BIG_ENDIAN, which is the same value, causes XTAF recognition to immediately fail...why?*/
    vs->block_size = 512;

    /* Assign functions */
    vs->close = xtaf_close;
    vs->part_count = 0;

    /* Inspect beginning of image for XTAF superblock.  If one is present there, assume we're looking at a partition image, and quit early. */
    rc_verifysb = tsk_vs_xtaf_verifysb(img_info, 0, sector_size);
    if (rc_verifysb == 0) {
        if (tsk_verbose)
            tsk_fprintf(stderr, "tsk_vs_xtaf_open: Encountered XTAF superblock at beginning of image.  Assuming this is a partition image, not a disk image.\n");
        xtaf_close(vs);
        return NULL;
    }

    /* check to see if image is a single partition, in which case XTAF would start at the beginning */
    memset(xtaf_buffer, 0, sizeof(xtaf_buffer));
    cnt = tsk_img_read(img_info, 0x0, (char *) xtaf_buffer, 4);
    if(strncmp(xtaf_buffer, "XTAF", 4) == 0){
        partition_offset = 0;
        partition_length = img_info->size;
        rc_verifysb = tsk_vs_xtaf_verifysb(img_info, partition_offset, sector_size);
        /* Check for XTAF superblock. */
        if (rc_verifysb != 0) {
            if (tsk_verbose)
                tsk_fprintf(stderr, "Superblock incorrect\n");
            xtaf_close(vs);
            return NULL;
        }
        /* Allocate partition label. */
        part_label = (char *) tsk_malloc(XTAF_PART_LABEL_MAX_LENGTH * sizeof(char));
        for (itor = 0; itor < 6; itor++){
            if( (img_info->size/img_info->sector_size) == known_xtaf_lengths[itor]){
                /* Allocate partition label. */
                part_label = (char *) tsk_malloc(XTAF_PART_LABEL_MAX_LENGTH * sizeof(char));
                snprintf(part_label, XTAF_PART_LABEL_MAX_LENGTH, known_xtaf_labels[itor]);
                break;
            }
        }
        vs->part_count = 1;

        /* Populate partition struct and append to partition list. */
        part = tsk_vs_part_add(vs, partition_offset, partition_length, TSK_VS_PART_FLAG_ALLOC, part_label, 0, 0);
        if (NULL == part) {
            tsk_fprintf(stderr, "tsk_vs_xtaf_open: Failed to add partition %d to partition list.\n", itor);
            xtaf_close(vs);
            return NULL;
        }
        partition_tally = 1;
    }else{

        vs->part_count = 6;
        /* Loop through the known partition offsets, looking for XTAF file systems only by a sane XTAF superblock being present. */
        for (itor = 0; itor < 6; itor++) {
            /* Reset. */
            part = NULL;
            part_label = NULL;
    
            partition_offset = known_xtaf_offsets[itor]*512;
    
            /* Check to see if XTAF is at the location it should be */
            memset(xtaf_buffer, 0, sizeof(xtaf_buffer));
            cnt = tsk_img_read(img_info, partition_offset, (char *) xtaf_buffer, 4);
            if(strncmp(xtaf_buffer, "XTAF", 4) != 0){
                continue;
            }
    
            partition_length = known_xtaf_lengths[itor];
            /* Last partition will have variable size depending on the size of drive, this partition will run to the end of the drive */       
            if( partition_offset == 0x130eb0000){
                partition_length = img_info->size - 0x130eb0000;
            }
    
            if (0 == partition_length) {
                if (tsk_verbose) {
                    tsk_fprintf(stderr, "tsk_vs_xtaf_open: Computing partition length.\n");
                    tsk_fprintf(stderr, "tsk_vs_xtaf_open: Image size: %" PRIuOFF " bytes.\n", img_info->size);
                    tsk_fprintf(stderr, "tsk_vs_xtaf_open: Sector size: %u bytes.\n", img_info->sector_size);
                    tsk_fprintf(stderr, "tsk_vs_xtaf_open: Partition offset: %" PRIuDADDR " bytes.\n", partition_offset * img_info->sector_size);
                }
    
                /* Compute partition length of the user data partition differently - based on input image's length. */
                if ((img_info->size / sector_size) < partition_offset) {
                    if (tsk_verbose)
                        tsk_fprintf(stderr, "tsk_vs_xtaf_open: This image is smaller than the offset of the target partition.  Aborting.\n");
                    xtaf_close(vs);
                    return NULL;
                }
                partition_length = (img_info->size / sector_size) - partition_offset;
            }
    
            if (tsk_verbose) {
                tsk_fprintf(stderr, "tsk_vs_xtaf_open: Testing for partition.\n");
                tsk_fprintf(stderr, "tsk_vs_xtaf_open:   itor: %d.\n", itor);
                tsk_fprintf(stderr, "tsk_vs_xtaf_open:   offset: %" PRIuDADDR " sectors.\n", partition_offset);
                tsk_fprintf(stderr, "tsk_vs_xtaf_open:   length: %" PRIuDADDR " sectors.\n", partition_length);
            }
    
            /* Check for XTAF superblock. */
            rc_verifysb = tsk_vs_xtaf_verifysb(img_info, partition_offset, sector_size);
            if (rc_verifysb != 0) {
                continue;
            }
    
            /* Allocate partition label. */
            part_label = (char *) tsk_malloc(XTAF_PART_LABEL_MAX_LENGTH * sizeof(char));
            snprintf(part_label, XTAF_PART_LABEL_MAX_LENGTH, known_xtaf_labels[itor]);
    
            /* Populate partition struct and append to partition list. */
            part = tsk_vs_part_add(vs, (partition_offset/(512)), partition_length, TSK_VS_PART_FLAG_ALLOC, part_label, 0, 0);
//            part->start = (TSK_DADDR_T) partition_offset;
            if (NULL == part) {
                tsk_fprintf(stderr, "tsk_vs_xtaf_open: Failed to add partition %d to partition list.\n", itor);
                break;
            }
    
            partition_tally++;
        }
    }

    /* Don't call this an XTAF volume system if none of the hard-coded partitions were found. */
    if (partition_tally == 0) {
        xtaf_close(vs);
        return NULL;
    }

    /* Denote unallocated space as "Unused" disk area. */
    if (tsk_vs_part_unused(vs)) {
        xtaf_close(vs);
        return NULL;
    }

    return vs;
}
Esempio n. 6
0
/*
 * Load the primary partition table (MBR) into the internal
 * data structures in TSK_VS_INFO
 *
 * This will automatically call load_ext_table for extended
 * partitions
 *
 * sect_cur is the address of the table to load
 *
 * 0 is returned if the load is successful and 1 if error
 */
static uint8_t
dos_load_prim_table(TSK_VS_INFO * vs, uint8_t test)
{
    dos_sect *sect;
    char *sect_buf;
    int i, added = 0;
    char *table_str;
    ssize_t cnt;
    TSK_DADDR_T taddr = vs->offset / vs->block_size + DOS_PART_SOFFSET;
    TSK_DADDR_T max_addr = (vs->img_info->size - vs->offset) / vs->block_size;  // max sector

    if (tsk_verbose)
        tsk_fprintf(stderr,
            "dos_load_prim: Table Sector: %" PRIuDADDR "\n", taddr);

    if ((sect_buf = tsk_malloc(vs->block_size)) == NULL)
        return 1;
    sect = (dos_sect *) sect_buf;

    /* Read the table */
    cnt = tsk_vs_read_block
        (vs, DOS_PART_SOFFSET, sect_buf, vs->block_size);

    if (cnt != vs->block_size) {
        if (cnt >= 0) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_VS_READ);
        }
        tsk_error_set_errstr2("Primary DOS table sector %" PRIuDADDR,
            taddr);
        free(sect_buf);
        return 1;
    }


    /* Sanity Check */
    if (tsk_vs_guessu16(vs, sect->magic, DOS_MAGIC)) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
        tsk_error_set_errstr
            ("File is not a DOS partition (invalid primary magic) (Sector: %"
            PRIuDADDR ")", taddr);
        if (tsk_verbose)
            fprintf(stderr,
                "File is not a DOS partition (invalid primary magic) (Sector: %"
                PRIuDADDR ")", taddr);
        free(sect_buf);
        return 1;
    }

    /* Because FAT and NTFS use the same magic - check for a
     * standard MS OEM name and sizes.  Not a great check, but we can't
     * really test the table entries.
     */
    if (test) {
        if (tsk_verbose)
            tsk_fprintf(stderr,
                "dos_load_prim_table: Testing FAT/NTFS conditions\n");

        if (strncmp("MSDOS", sect->oemname, 5) == 0) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_VS_MAGIC);
            tsk_error_set_errstr
                ("dos_load_prim_table: MSDOS OEM name exists");
            if (tsk_verbose)
                tsk_fprintf(stderr,
                    "dos_load_prim_table: MSDOS OEM name exists\n");
            free(sect_buf);
            return 1;
        }
        else if (strncmp("MSWIN", sect->oemname, 5) == 0) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_VS_MAGIC);
            tsk_error_set_errstr
                ("dos_load_prim_table: MSWIN OEM name exists");
            if (tsk_verbose)
                tsk_fprintf(stderr,
                    "dos_load_prim_table: MSWIN OEM name exists\n");
            free(sect_buf);
            return 1;
        }
        else if (strncmp("NTFS", sect->oemname, 4) == 0) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_VS_MAGIC);
            tsk_error_set_errstr
                ("dos_load_prim_table: NTFS OEM name exists");
            if (tsk_verbose)
                tsk_fprintf(stderr,
                    "dos_load_prim_table: NTFS OEM name exists\n");
            free(sect_buf);
            return 1;
        }
        else if (strncmp("FAT", sect->oemname, 4) == 0) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_VS_MAGIC);
            tsk_error_set_errstr
                ("dos_load_prim_table: FAT OEM name exists");
            if (tsk_verbose)
                tsk_fprintf(stderr,
                    "dos_load_prim_table: FAT OEM name exists\n");
            free(sect_buf);
            return 1;
        }
    }

    /* Add an entry of 1 sector for the table  to the internal structure */
    if ((table_str = tsk_malloc(32)) == NULL) {
        free(sect_buf);
        return 1;
    }

    snprintf(table_str, 32, "Primary Table (#0)");
    if (NULL == tsk_vs_part_add(vs, DOS_PART_SOFFSET, (TSK_DADDR_T) 1,
            TSK_VS_PART_FLAG_META, table_str, -1, -1)) {
        free(sect_buf);
        return 1;
    }

    /* Cycle through the partition table */
    for (i = 0; i < 4; i++) {
        dos_part *part = &sect->ptable[i];

        /* We currently ignore CHS */
        uint32_t part_start = tsk_getu32(vs->endian, part->start_sec);
        uint32_t part_size = tsk_getu32(vs->endian, part->size_sec);

        if (tsk_verbose)
            tsk_fprintf(stderr,
                "load_pri:0:%d    Start: %" PRIu32 "   Size: %" PRIu32
                "  Type: %d\n", i, part_start, part_size, part->ptype);

        if (part_size == 0)
            continue;

        // make sure the first couple are in the image bounds
        if ((i < 2) && (part_start > max_addr)) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_VS_BLK_NUM);
            tsk_error_set_errstr
                ("dos_load_prim_table: Starting sector too large for image");
            if (tsk_verbose)
                tsk_fprintf(stderr,
                    "Starting sector %" PRIu32 " too large for image\n",
                    part_start);
            free(sect_buf);
            return 1;
        }
#if 0
// I'm not sure if this is too strict ...
        else if ((part_start + part_size) > max_addr) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_VS_BLK_NUM);
            tsk_error_set_errstr
                ("dos_load_prim_table: Partition ends after image");
            return 1;
        }
#endif

        added = 1;

        /* Add the partition to the internal structure
         * If it is an extended partition, process it now */
        if (dos_is_ext(part->ptype)) {
            if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) part_start,
                    (TSK_DADDR_T) part_size, TSK_VS_PART_FLAG_META,
                    dos_get_desc(part->ptype), 0, i)) {
                free(sect_buf);
                return 1;
            }

            if (dos_load_ext_table(vs, part_start, part_start, 1)) {
                if (tsk_verbose) {
                    fprintf(stderr,
                        "Error loading extended table, moving on");
                    tsk_error_print(stderr);
                }
                tsk_error_reset();
            }
        }
        else {
            if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) part_start,
                    (TSK_DADDR_T) part_size, TSK_VS_PART_FLAG_ALLOC,
                    dos_get_desc(part->ptype), 0, i)) {
                free(sect_buf);
                return 1;
            }
        }
    }
    free(sect_buf);

    if (added == 0) {
        if (tsk_verbose)
            tsk_fprintf(stderr, "dos_load_prim: No valid entries\n");

        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
        tsk_error_set_errstr
            ("dos_load_prim_table: No valid entries in primary table");
        return 1;
    }
    return 0;
}
Esempio n. 7
0
/*
 * Load an extended partition table into the structure in TSK_VS_INFO.
 *
 * sect_cur: The sector where the extended table is located
 * sect_ext_base: The sector of the primary extended table (this does
 *   not change for recursive calls)
 * table: a counter that identifies the table depth
 *   (increases by 1 for each recursive call)
 *
 * For the primary extended table, sect_cur == sect_ext_base
 *
 * Return 1 on error and 0 on success
 *
 */
static uint8_t
dos_load_ext_table(TSK_VS_INFO * vs, TSK_DADDR_T sect_cur,
    TSK_DADDR_T sect_ext_base, int table)
{
    dos_sect *sect;
    char *sect_buf;
    int i;
    char *table_str;
    ssize_t cnt;
    TSK_DADDR_T max_addr = (vs->img_info->size - vs->offset) / vs->block_size;  // max sector

    if (tsk_verbose)
        tsk_fprintf(stderr,
            "dos_load_ext: Table Sector: %" PRIuDADDR
            ", Primary Base Sector: %" PRIuDADDR "\n", sect_cur,
            sect_ext_base);

    if ((sect_buf = tsk_malloc(vs->block_size)) == NULL)
        return 1;
    sect = (dos_sect *) sect_buf;

    /* Read the partition table sector */
    cnt = tsk_vs_read_block(vs, sect_cur, sect_buf, vs->block_size);
    if (cnt != vs->block_size) {
        if (cnt >= 0) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_VS_READ);
        }
        tsk_error_set_errstr2("Extended DOS table sector %" PRIuDADDR,
            sect_cur);
        free(sect_buf);
        return 1;
    }

    /* Sanity Check */
    if (tsk_getu16(vs->endian, sect->magic) != DOS_MAGIC) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
        tsk_error_set_errstr("Extended DOS partition table in sector %"
            PRIuDADDR, sect_cur);
        free(sect_buf);
        return 1;
    }

    /* Add an entry of 1 length for the table  to the internal structure */
    if ((table_str = tsk_malloc(32)) == NULL) {
        free(sect_buf);
        return 1;
    }

    snprintf(table_str, 32, "Extended Table (#%d)", table);
    if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) sect_cur,
            (TSK_DADDR_T) 1, TSK_VS_PART_FLAG_META, table_str, table,
            -1)) {
        free(sect_buf);
        return 1;
    }

    /* Cycle through the four partitions in the table
     *
     * When another extended partition is found, it is processed
     * inside of the loop
     */
    for (i = 0; i < 4; i++) {
        dos_part *part = &sect->ptable[i];

        /* Get the starting sector and size, we currently
         * ignore CHS */
        uint32_t part_start = tsk_getu32(vs->endian, part->start_sec);
        uint32_t part_size = tsk_getu32(vs->endian, part->size_sec);

        if (tsk_verbose)
            tsk_fprintf(stderr,
                "load_ext: %d:%d    Start: %" PRIu32 "   Size: %"
                PRIu32 "  Type: %d\n", table, i, part_start, part_size,
                part->ptype);

        if (part_size == 0)
            continue;

        /* partitions are addressed differently
         * in extended partitions */
        if (dos_is_ext(part->ptype)) {

            /* part start is added to the start of the
             * first extended partition (the primary
             * extended partition) */

            if (NULL == tsk_vs_part_add(vs,
                    (TSK_DADDR_T) (sect_ext_base + part_start),
                    (TSK_DADDR_T) part_size, TSK_VS_PART_FLAG_META,
                    dos_get_desc(part->ptype), table, i)) {
                free(sect_buf);
                return 1;
            }

            if (sect_ext_base + part_start > max_addr) {
                if (tsk_verbose)
                    tsk_fprintf(stderr,
                        "Starting sector %" PRIuDADDR
                        " of extended partition too large for image\n",
                        sect_ext_base + part_start);
            }
            /* Process the extended partition */
            else if (dos_load_ext_table(vs, sect_ext_base + part_start,
                    sect_ext_base, table + 1)) {
                free(sect_buf);
                return 1;
            }
        }

        else {
            /* part_start is added to the start of the
             * current partition for the actual
             * starting location */

            // we ignore the max_addr checks on extended partitions...

            if (NULL == tsk_vs_part_add(vs,
                    (TSK_DADDR_T) (sect_cur + part_start),
                    (TSK_DADDR_T) part_size, TSK_VS_PART_FLAG_ALLOC,
                    dos_get_desc(part->ptype), table, i)) {
                free(sect_buf);
                return 1;
            }
        }
    }

    free(sect_buf);
    return 0;
}