Пример #1
0
/* Verify that a specific attribute can be read from the file
* @param a_addr The metadata address of the file to analyze
* @param a_type Type that is known to be in file
* @returns 1 if a test failed
*/
static int
test_get_type(TSK_FS_INFO * a_fs, TSK_INUM_T a_addr,
    TSK_FS_ATTR_TYPE_ENUM a_type)
{
    TSK_FS_FILE *fs_file;

    // open the file
    fs_file = tsk_fs_file_open_meta(a_fs, NULL, a_addr);
    if (!fs_file) {
        fprintf(stderr, "Error opening file %" PRIuINUM " via meta\n",
            a_addr);
        tsk_error_print(stderr);
        return 1;
    }

    // verify the specified type can be opened
    const TSK_FS_ATTR *fs_attr =
        tsk_fs_file_attr_get_type(fs_file, a_type, 0, 0);
    if (!fs_attr) {
        fprintf(stderr,
            "Error getting specified attribute %d-X (no id) from %"
            PRIuINUM "\n", a_type, a_addr);
        tsk_error_print(stderr);
        return 1;
    }

    tsk_fs_file_close(fs_file);
    return 0;
}
Пример #2
0
/*
 * Class:     edu_uw_apl_commons_tsk4j_filesys_FileSystem
 * Method:    fileOpenMeta
 * Signature: (JJ)Ledu/uw/apl/commons/tsk4j/filesys/File;
 */
JNIEXPORT jobject JNICALL 
Java_edu_uw_apl_commons_tsk4j_filesys_FileSystem_fileOpenMeta
(JNIEnv * env, jobject thiz, jlong nativePtr, jlong metadataAddr ) {

  TSK_FS_INFO* info = (TSK_FS_INFO*)nativePtr;

  TSK_FS_FILE* fsFile = tsk_fs_file_open_meta( info, NULL, 
											   (TSK_INUM_T)metadataAddr );
  if( !fsFile )
	return (jobject)NULL;

  jobject fileMeta = createFileMeta( env, fsFile->meta );
  if( !fileMeta ) {
	tsk_fs_file_close( fsFile );
	return (jobject)NULL;
  }

  jobject result = createFile( env, fsFile, thiz, fileMeta, NULL ); 
  if( !result ) {
	tsk_fs_file_close( fsFile );
	// LOOK: free fileMeta ??
	return (jobject)NULL;
  }
  return result;
}
/*
 * Open the file with the given id in the given file system
 * @return the created TSK_FS_FILE pointer
 * @param env pointer to java environment this was called from
 * @param obj the java object this was called from
 * @param a_fs_info the pointer to the parent file system object
 * @param file_id id of the file to open 
 */
JNIEXPORT jlong JNICALL
Java_org_sleuthkit_datamodel_SleuthkitJNI_openFileNat(JNIEnv * env,
    jclass obj, jlong a_fs_info, jlong file_id)
{
    TSK_FS_INFO *fs_info = castFsInfo(env, a_fs_info);
    TSK_FS_FILE *file_info;

    file_info = tsk_fs_file_open_meta(fs_info, NULL, (TSK_INUM_T) file_id);
    if (file_info == NULL) {
        throwTskError(env, tsk_error_get());
    }

    return (jlong) file_info;
}
Пример #4
0
int
testfile(TSK_FS_INFO * a_fs, TSK_INUM_T a_inum)
{
    TSK_FS_FILE *file1 = NULL;

    if ((s_buf = (char *) malloc(a_fs->block_size)) == NULL) {
        fprintf(stderr, "Error allocating  memory\n");
        return 1;
    }

    file1 = tsk_fs_file_open_meta(a_fs, NULL, a_inum);
    if (file1 == NULL) {
        fprintf(stderr, "Error opening inode %" PRIuINUM "\n", a_inum);
        return 1;
    }

    s_file2 = tsk_fs_file_open_meta(a_fs, NULL, a_inum);
    if (s_file2 == NULL) {
        fprintf(stderr, "Error opening inode %" PRIuINUM "\n", a_inum);
        return 1;
    }

    s_off = 0;
    if (tsk_fs_file_walk(file1, (TSK_FS_FILE_WALK_FLAG_ENUM) 0,
            fw_action1, NULL)) {
        fprintf(stderr, "Error walking file inode: %" PRIuINUM "\n",
            a_inum);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }

    free(s_buf);
    tsk_fs_file_close(file1);
    tsk_fs_file_close(s_file2);
    return 0;
}
Пример #5
0
/** 
* \ingroup fslib
* Return the handle structure for a specific file, given its full path. Note that
* if you have the metadata address fo the file, then tsk_fs_file_open_meta() is a
* more efficient approach. 
*
* @param a_fs File system to analyze
* @param a_fs_file Structure to store file data in or NULL to have one allocated. 
* @param a_path Path of file to open
* @returns NULL on error
*/
TSK_FS_FILE *
tsk_fs_file_open(TSK_FS_INFO * a_fs,
    TSK_FS_FILE * a_fs_file, const char *a_path)
{
    TSK_INUM_T inum;
    int8_t retval;
    TSK_FS_FILE *fs_file = NULL;
    TSK_FS_NAME *fs_name = NULL;

    if ((a_fs == NULL) || (a_fs->tag != TSK_FS_INFO_TAG)) {
        tsk_error_set_errno(TSK_ERR_FS_ARG);
        tsk_error_set_errstr
            ("tsk_fs_file_open: called with NULL or unallocated structures");
        return NULL;
    }

    // allocate a structure to store the name in
    if ((fs_name = tsk_fs_name_alloc(128, 32)) == NULL) {
        return NULL;
    }

    retval = tsk_fs_path2inum(a_fs, a_path, &inum, fs_name);
    if (retval == -1) {
        tsk_fs_name_free(fs_name);
        return NULL;
    }
    else if (retval == 1) {
        tsk_fs_name_free(fs_name);
        tsk_error_set_errno(TSK_ERR_FS_ARG);
        tsk_error_set_errstr("tsk_fs_file_open: path not found: %s",
            a_path);
        return NULL;
    }


    fs_file = tsk_fs_file_open_meta(a_fs, a_fs_file, inum);
    if (fs_file) {
        // Add the name to the structure
        fs_file->name = fs_name;

        // path2inum did not put this in there...
        fs_name->meta_seq = fs_file->meta->seq;
    }
    else {
        tsk_fs_name_free(fs_name);
    }

    return fs_file;
}
Пример #6
0
/* Place journal data in *fs
 *
 * Return 0 on success and 1 on error 
 * */
uint8_t
ext2fs_jopen(TSK_FS_INFO * fs, TSK_INUM_T inum)
{
    EXT2FS_INFO *ext2fs = (EXT2FS_INFO *) fs;
    EXT2FS_JINFO *jinfo;

    // clean up any error messages that are lying around
    tsk_error_reset();

    if (!fs) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_ARG;
        snprintf(tsk_errstr, TSK_ERRSTR_L, "ext2fs_jopen: fs is null");
        return 1;
    }

    ext2fs->jinfo = jinfo =
        (EXT2FS_JINFO *) tsk_malloc(sizeof(EXT2FS_JINFO));
    if (jinfo == NULL) {
        return 1;
    }
    jinfo->j_inum = inum;

    jinfo->fs_file = tsk_fs_file_open_meta(fs, NULL, inum);
    if (!jinfo->fs_file) {
        free(jinfo);
        return 1;
//      error("error finding journal inode %" PRIu32, inum);
    }

    if (tsk_fs_file_walk(jinfo->fs_file, 0, load_sb_action, NULL)) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_FWALK;
        snprintf(tsk_errstr, TSK_ERRSTR_L, "Error loading ext3 journal");
        tsk_fs_file_close(jinfo->fs_file);
        free(jinfo);
        return 1;
    }

    if (tsk_verbose)
        tsk_fprintf(stderr,
            "journal opened at inode %" PRIuINUM " bsize: %" PRIu32
            " First JBlk: %" PRIuDADDR " Last JBlk: %" PRIuDADDR "\n",
            inum, jinfo->bsize, jinfo->first_block, jinfo->last_block);

    return 0;
}
Пример #7
0
/* Return 1 on error and 0 on success */
uint8_t
tsk_fs_icat(TSK_FS_INFO * fs, TSK_INUM_T inum,
    TSK_FS_ATTR_TYPE_ENUM type, uint8_t type_used,
    uint16_t id, uint8_t id_used, TSK_FS_FILE_WALK_FLAG_ENUM flags)
{
    TSK_FS_FILE *fs_file;

#ifdef TSK_WIN32
    if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_WRITE;
        snprintf(tsk_errstr, TSK_ERRSTR_L,
            "icat_lib: error setting stdout to binary: %s",
            strerror(errno));
        return 1;
    }
#endif

    fs_file = tsk_fs_file_open_meta(fs, NULL, inum);
    if (!fs_file) {
        return 1;
    }

    if (type_used) {
        if (id_used == 0) {
            flags |= TSK_FS_FILE_WALK_FLAG_NOID;
        }
        if (tsk_fs_file_walk_type(fs_file, type, id, flags, icat_action,
                NULL)) {
            tsk_fs_file_close(fs_file);
            return 1;
        }
    }
    else {
        if (tsk_fs_file_walk(fs_file, flags, icat_action, NULL)) {
            tsk_fs_file_close(fs_file);
            return 1;
        }
    }


    tsk_fs_file_close(fs_file);

    return 0;
}
Пример #8
0
/**
 * Open the Update Sequence Number Journal stored at the inode inum.
 *
 * @param ntfs File system where the journal is stored
 * @param inum file reference number where the USN journal is located
 * @returns 0 on success, 1 otherwise
 */
uint8_t
tsk_ntfs_usnjopen(TSK_FS_INFO *fs, TSK_INUM_T inum)
{
    NTFS_INFO *ntfs = (NTFS_INFO*)fs;

    tsk_error_reset();

    if (ntfs == NULL || ntfs->fs_info.ftype != TSK_FS_TYPE_NTFS) {
        tsk_error_set_errno(TSK_ERR_FS_ARG);
        tsk_error_set_errstr("Invalid FS type in tsk_ntfs_usnjopen");
        return 1;
    }

    /* Initialize usnjinfo support structure */
    ntfs->usnjinfo = tsk_malloc(sizeof *ntfs->usnjinfo);
    if (ntfs->usnjinfo == NULL)
        return 1;

    ntfs->usnjinfo->usnj_inum = inum;
    ntfs->usnjinfo->bsize = ntfs->fs_info.block_size;

    ntfs->usnjinfo->fs_file = tsk_fs_file_open_meta(&ntfs->fs_info, NULL, inum);
    if (ntfs->usnjinfo->fs_file == NULL) {
        tsk_error_set_errno(TSK_ERR_FS_ARG);
        tsk_error_set_errstr("ntfs_usnjopen: tsk_fs_file_open_meta");
        free(ntfs->usnjinfo);
        return 1;
    }

    if (tsk_verbose)
        tsk_fprintf(stderr, "usn journal opened at inode %" PRIuINUM
                    " bsize: %" PRIu32 "\n",
                    ntfs->usnjinfo->usnj_inum, ntfs->usnjinfo->bsize);

    return 0;
}
Пример #9
0
/** \internal
* Process a directory and load up FS_DIR with the entries. If a pointer to
* an already allocated FS_DIR struture is given, it will be cleared.  If no existing
* FS_DIR structure is passed (i.e. NULL), then a new one will be created. If the return
* value is error or corruption, then the FS_DIR structure could
* have entries (depending on when the error occured).
*
* @param a_fs File system to analyze
* @param a_fs_dir Pointer to FS_DIR pointer. Can contain an already allocated
* structure or a new structure.
* @param a_addr Address of directory to process.
* @returns error, corruption, ok etc.
*/
TSK_RETVAL_ENUM
hfs_dir_open_meta(TSK_FS_INFO * fs, TSK_FS_DIR ** a_fs_dir,
                  TSK_INUM_T a_addr)
{
    HFS_INFO *hfs = (HFS_INFO *) fs;
    uint32_t cnid;              /* catalog node ID of the entry (= inum) */
    TSK_FS_DIR *fs_dir;
    TSK_FS_NAME *fs_name;
    HFS_DIR_OPEN_META_INFO info;


    tsk_error_reset();

    cnid = (uint32_t) a_addr;

    if (tsk_verbose)
        fprintf(stderr,
                "hfs_dir_open_meta: called for directory %" PRIu32 "\n", cnid);

    if (a_addr < fs->first_inum || a_addr > fs->last_inum) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
        tsk_error_set_errstr("hfs_dir_open_meta: Invalid inode value: %"
                             PRIuINUM, a_addr);
        return TSK_ERR;
    }
    else if (a_fs_dir == NULL) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_ARG);
        tsk_error_set_errstr
        ("hfs_dir_open_meta: NULL fs_dir argument given");
        return TSK_ERR;
    }

    if (tsk_verbose)
        tsk_fprintf(stderr,
                    "hfs_dir_open_meta: Processing directory %" PRIuINUM "\n",
                    a_addr);

    fs_dir = *a_fs_dir;
    if (fs_dir) {
        tsk_fs_dir_reset(fs_dir);
        fs_dir->addr = a_addr;
    }
    else if ((*a_fs_dir = fs_dir =
                              tsk_fs_dir_alloc(fs, a_addr, 128)) == NULL) {
        return TSK_ERR;
    }

    if ((fs_name = tsk_fs_name_alloc(HFS_MAXNAMLEN, 0)) == NULL) {
        return TSK_ERR;
    }
    info.fs_dir = fs_dir;
    info.fs_name = fs_name;

    if ((fs_dir->fs_file =
                tsk_fs_file_open_meta(fs, NULL, a_addr)) == NULL) {
        tsk_error_errstr2_concat(" - hfs_dir_open_meta");
        tsk_fs_name_free(fs_name);
        return TSK_ERR;
    }

    // if we are listing the root directory, add the Orphan directory and special HFS file entries
    if (a_addr == fs->root_inum) {
        int i;
        for (i = 0; i < 6; i++) {
            switch (i) {
            case 0:
                if (!hfs->has_extents_file)
                    continue;
                strncpy(fs_name->name, HFS_EXTENTS_FILE_NAME,
                        fs_name->name_size);
                fs_name->meta_addr = HFS_EXTENTS_FILE_ID;
                break;
            case 1:
                strncpy(fs_name->name, HFS_CATALOG_FILE_NAME,
                        fs_name->name_size);
                fs_name->meta_addr = HFS_CATALOG_FILE_ID;
                break;
            case 2:
                // Note: the Extents file and the BadBlocks file are really the same.
                if (!hfs->has_extents_file)
                    continue;
                strncpy(fs_name->name, HFS_BAD_BLOCK_FILE_NAME,
                        fs_name->name_size);
                fs_name->meta_addr = HFS_BAD_BLOCK_FILE_ID;
                break;
            case 3:
                strncpy(fs_name->name, HFS_ALLOCATION_FILE_NAME,
                        fs_name->name_size);
                fs_name->meta_addr = HFS_ALLOCATION_FILE_ID;
                break;
            case 4:
                if (!hfs->has_startup_file)
                    continue;
                strncpy(fs_name->name, HFS_STARTUP_FILE_NAME,
                        fs_name->name_size);
                fs_name->meta_addr = HFS_STARTUP_FILE_ID;
                break;
            case 5:
                if (!hfs->has_attributes_file)
                    continue;
                strncpy(fs_name->name, HFS_ATTRIBUTES_FILE_NAME,
                        fs_name->name_size);
                fs_name->meta_addr = HFS_ATTRIBUTES_FILE_ID;
                break;
                /*
                   case 6:
                   strncpy(fs_name->name, HFS_REPAIR_CATALOG_FILE_NAME, fs_name->name_size);
                   fs_name->meta_addr = HFS_REPAIR_CATALOG_FILE_ID;
                   break;
                   case 7:
                   strncpy(fs_name->name, HFS_BOGUS_EXTENT_FILE_NAME, fs_name->name_size);
                   fs_name->meta_addr = HFS_BOGUS_EXTENT_FILE_ID;
                   break;
                 */
            }
            fs_name->type = TSK_FS_NAME_TYPE_REG;
            fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
            if (tsk_fs_dir_add(fs_dir, fs_name)) {
                tsk_fs_name_free(fs_name);
                return TSK_ERR;
            }
        }
    }

    if (hfs_cat_traverse(hfs, &cnid, hfs_dir_open_meta_cb, &info)) {
        tsk_fs_name_free(fs_name);
        return TSK_ERR;
    }

    tsk_fs_name_free(fs_name);
    return TSK_OK;
}
Пример #10
0
int TskImageFileTsk::openFile(const uint64_t fileId)
{
    if (m_img_info == NULL) {
        if (open() != 0)
            return -1;
    }

    // Use ImgDb::getFileUniqueIdentifiers to get the four needed values.
    uint64_t fsByteOffset = 0;
    uint64_t fsFileId = 0;
    int attrType = 0;
    int attrId = 0;

    if (m_db.getFileUniqueIdentifiers(fileId, fsByteOffset, fsFileId, attrType, attrId) != 0)
    {
        LOGERROR(L"TskImageFileTsk::openFile - Error getting file identifiers.\n");
        return -1;
    }

    // Check if the file system at the offset is already open (using m_openFs).  If not, open it (tsk_fs_open) and add it to the map.
    TSK_FS_INFO * fsInfo = m_openFs[fsByteOffset];

    if (fsInfo == NULL)
    {
        // Open the file system and add it to the map.
        fsInfo = tsk_fs_open_img(m_img_info, fsByteOffset, TSK_FS_TYPE_DETECT);

        if (fsInfo == NULL)
        {
            std::wstringstream errorMsg;
            errorMsg << L"TskImageFileTsk::openFile - Error opening file system : " << tsk_error_get();
            LOGERROR(errorMsg.str());
            return -1;
        }

        m_openFs[fsByteOffset] = fsInfo;
    }

    // Find a new entry in m_openFiles and use tsk_fs_file_open to open the file and save the handle in m_openFiles. 
    TSK_FS_FILE * fsFile = tsk_fs_file_open_meta(fsInfo, NULL, fsFileId);

    if (fsFile == NULL)
    {
        std::wstringstream errorMsg;
        errorMsg << L"TskImageFileTsk::openFile - Error opening file : " << tsk_error_get();
        LOGERROR(errorMsg.str());
        return -1;
    }

    const TSK_FS_ATTR * fsAttr = tsk_fs_file_attr_get_id(fsFile, attrId);

    // @@@ TSK_ATTR_TYPE_ENUM should have a value added to it to represent an
    // empty (or null) attribute type and we should then compare attrType against
    // this enum value instead of 0.

    // It is possible to have a file with no attributes. We only report an
    // error if we are expecting a valid attribute.
    if (attrType != 0 && fsAttr == NULL)
    {
        std::wstringstream msg;
        msg << L"TskImageFileTsk::openFile - Error getting attribute : " << tsk_error_get();
        LOGERROR(msg.str());
        return -1;
    }

    TskImageFileTsk::OPEN_FILE * openFile = new TskImageFileTsk::OPEN_FILE();
    openFile->fsFile = fsFile;
    openFile->fsAttr = fsAttr;

    m_openFiles.push_back(openFile);

    // Return the index into m_openFiles
    return m_openFiles.size() - 1;
}
Пример #11
0
TSK_RETVAL_ENUM
ext2fs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
    TSK_INUM_T a_addr)
{
    EXT2FS_INFO *ext2fs = (EXT2FS_INFO *) a_fs;
    char *dirbuf, *dirptr;
    TSK_OFF_T size;
    TSK_FS_LOAD_FILE load_file;
    TSK_FS_DIR *fs_dir;
    TSK_LIST *list_seen = NULL;

    /* If we get corruption in one of the blocks, then continue processing.
     * retval_final will change when corruption is detected.  Errors are
     * returned immediately. */
    TSK_RETVAL_ENUM retval_tmp;
    TSK_RETVAL_ENUM retval_final = TSK_OK;

    if (a_addr < a_fs->first_inum || a_addr > a_fs->last_inum) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
        tsk_error_set_errstr("ext2fs_dir_open_meta: inode value: %"
            PRIuINUM "\n", a_addr);
        return TSK_ERR;
    }
    else if (a_fs_dir == NULL) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_ARG);
        tsk_error_set_errstr
            ("ext2fs_dir_open_meta: NULL fs_attr argument given");
        return TSK_ERR;
    }

    if (tsk_verbose) {
        tsk_fprintf(stderr,
            "ext2fs_dir_open_meta: Processing directory %" PRIuINUM
            "\n", a_addr);
#ifdef Ext4_DBG
        tsk_fprintf(stderr,
            "ext2fs_dir_open_meta: $OrphanFiles Inum %" PRIuINUM
            " == %" PRIuINUM ": %d\n", TSK_FS_ORPHANDIR_INUM(a_fs), a_addr,
            a_addr == TSK_FS_ORPHANDIR_INUM(a_fs));
#endif
    }

    fs_dir = *a_fs_dir;
    if (fs_dir) {
        tsk_fs_dir_reset(fs_dir);
        fs_dir->addr = a_addr;
    }
    else {
        if ((*a_fs_dir = fs_dir =
                tsk_fs_dir_alloc(a_fs, a_addr, 128)) == NULL) {
            return TSK_ERR;
        }
    }

    //  handle the orphan directory if its contents were requested
    if (a_addr == TSK_FS_ORPHANDIR_INUM(a_fs)) {
#ifdef Ext4_DBG
        tsk_fprintf(stderr, "DEBUG: Getting ready to process ORPHANS\n");
#endif
        return tsk_fs_dir_find_orphans(a_fs, fs_dir);
    }
    else {
#ifdef Ext4_DBG
        tsk_fprintf(stderr,
            "DEBUG: not orphan %" PRIuINUM "!=%" PRIuINUM "\n", a_addr,
            TSK_FS_ORPHANDIR_INUM(a_fs));
#endif
    }

    if ((fs_dir->fs_file =
            tsk_fs_file_open_meta(a_fs, NULL, a_addr)) == NULL) {
        tsk_error_reset();
        tsk_error_errstr2_concat("- ext2fs_dir_open_meta");
        return TSK_COR;
    }

    size = roundup(fs_dir->fs_file->meta->size, a_fs->block_size);
    if ((dirbuf = tsk_malloc((size_t) size)) == NULL) {
        return TSK_ERR;
    }

    /* make a copy of the directory contents that we can process */
    load_file.left = load_file.total = (size_t) size;
    load_file.base = load_file.cur = dirbuf;

    if (tsk_fs_file_walk(fs_dir->fs_file,
            TSK_FS_FILE_WALK_FLAG_SLACK,
            tsk_fs_load_file_action, (void *) &load_file)) {
        tsk_error_reset();
        tsk_error_errstr2_concat("- ext2fs_dir_open_meta");
        free(dirbuf);
        return TSK_COR;
    }

    /* Not all of the directory was copied, so we exit */
    if (load_file.left > 0) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_FWALK);
        tsk_error_set_errstr
            ("ext2fs_dir_open_meta: Error reading directory contents: %"
            PRIuINUM "\n", a_addr);
        free(dirbuf);
        return TSK_COR;
    }
    dirptr = dirbuf;

    while ((int64_t) size > 0) {
        int len =
            (a_fs->block_size < size) ? a_fs->block_size : (int) size;

        retval_tmp =
            ext2fs_dent_parse_block(ext2fs, fs_dir,
            (fs_dir->fs_file->meta->
                flags & TSK_FS_META_FLAG_UNALLOC) ? 1 : 0, &list_seen,
            dirptr, len);

        if (retval_tmp == TSK_ERR) {
            retval_final = TSK_ERR;
            break;
        }
        else if (retval_tmp == TSK_COR) {
            retval_final = TSK_COR;
        }

        size -= len;
        dirptr = (char *) ((uintptr_t) dirptr + len);
    }
    free(dirbuf);


    // if we are listing the root directory, add the Orphan directory entry
    if (a_addr == a_fs->root_inum) {
        TSK_FS_NAME *fs_name = tsk_fs_name_alloc(256, 0);
        if (fs_name == NULL)
            return TSK_ERR;

        if (tsk_fs_dir_make_orphan_dir_name(a_fs, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }

        if (tsk_fs_dir_add(fs_dir, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }
        tsk_fs_name_free(fs_name);
    }

    return retval_final;
}
Пример #12
0
/* This test checks the RECOVER flags 
 */
int
test_fat_recover()
{
    TSK_FS_INFO *fs;
    TSK_IMG_INFO *img;
    const char *tname = "fe_test_1.img-FAT";
    char fname[512];
    TSK_FS_FILE *file1;
    TSK_FS_FILE *file2;
    char buf[512];
    ssize_t retval;

    snprintf(fname, 512, "%s/fe_test_1.img", s_root);
    if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
        fprintf(stderr, "Error opening %s image\n", tname);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }

    if ((fs =
            tsk_fs_open_img(img, 41126400,
                (TSK_FS_TYPE_ENUM) 0)) == NULL) {
        fprintf(stderr, "Error opening %s image\n", tname);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }


    // fragmented.html
    const char *fname2 = "fragmented.html";
    file1 = tsk_fs_file_open_meta(fs, NULL, 1162);
    if (file1 == NULL) {
        fprintf(stderr, "Error opening %s (%s)\n", fname2, tname);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }

    // verify expected size
    if (file1->meta->size != 5905) {
        fprintf(stderr,
            "Error: %s not expected size (%" PRIuOFF ") (%s)\n", fname2,
            file1->meta->size, tname);
        return 1;
    }

    // verify we can open it via name as well
    file2 = tsk_fs_file_open(fs, NULL, "/deleted/fragmented.html");
    if (file2 == NULL) {
        fprintf(stderr,
            "Error opening /deleted/fragmented.html via path name (%s)\n",
            tname);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }

    if (file2->name == NULL) {
        fprintf(stderr,
            "Opening /deleted/fragmented.html via path name did not have name set(%s)\n",
            tname);
        return 1;
    }

    if (strcmp(file2->name->name, fname2) != 0) {
        fprintf(stderr,
            "Opening /deleted/fragmented.html via path had incorrect name set (%s) (%s)\n",
            file2->name->name, tname);
        return 1;
    }

    if ((file2->name->meta_addr != file2->meta->addr)
        || (file2->meta->addr != file1->meta->addr)) {
        fprintf(stderr,
            "Opening /deleted/fragmented.html via path had incorrect meta addresses (%"
            PRIuINUM " %" PRIuINUM " %" PRIuINUM " (%s)\n",
            file2->name->meta_addr, file2->meta->addr, file1->meta->addr,
            tname);
        return 1;
    }
    tsk_fs_file_close(file2);
    file2 = NULL;

    // try to read past end of first 2048-byte cluster
    retval =
        tsk_fs_file_read(file1, 2048, buf, 512,
        (TSK_FS_FILE_READ_FLAG_ENUM) 0);
    if (retval == -1) {
        fprintf(stderr, "Error reading %s past end w/out Recover flag\n",
            fname2);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }
    // current behavior is to return 0s in "unitialized" space 
    //if (retval != 0) {
    if (retval != 512) {
        fprintf(stderr,
            "Unexpected return value from reading %s past end w/out Recover flag.\n",
            fname2);
        fprintf(stderr, "Expected: 0.  Got: %zd\n", retval);
        return 1;
    }

    retval =
        tsk_fs_file_read(file1, 2048, buf, 512,
        (TSK_FS_FILE_READ_FLAG_ENUM) 0);
    if (retval == -1) {
        fprintf(stderr, "Error reading %s past end w/Recover flag\n",
            fname2);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }
    if (retval != 512) {
        fprintf(stderr,
            "Unexpected return value from %s past end w/Recover flag.\n",
            fname2);
        fprintf(stderr, "Expected: 512.  Got: %zd\n", retval);
        return 1;
    }

    // verify the term in the slack space
    if (memcmp("appear", buf, 6) != 0) {
        fprintf(stderr,
            "expected string not found in %s recovery: %c %c %c %c %c %c\n",
            fname2, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
        return 1;
    }

    tsk_fs_file_close(file1);
    tsk_fs_close(fs);
    tsk_img_close(img);
    return 0;
}
Пример #13
0
uint8_t
ntfs_find_file(TSK_FS_INFO * fs, TSK_INUM_T inode_toid, uint32_t type_toid,
    uint8_t type_used, uint16_t id_toid, uint8_t id_used,
    TSK_FS_DIR_WALK_FLAG_ENUM dir_walk_flags, TSK_FS_DIR_WALK_CB action,
    void *ptr)
{
    TSK_FS_META_NAME_LIST *fs_name_list;
    NTFS_INFO *ntfs = (NTFS_INFO *) fs;
    char *attr = NULL;
    NTFS_DINFO dinfo;
    TSK_FS_FILE *fs_file;

    /* sanity check */
    if (inode_toid < fs->first_inum || inode_toid > fs->last_inum) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_ARG;
        snprintf(tsk_errstr, TSK_ERRSTR_L,
            "ntfs_find_file: invalid inode value: %" PRIuINUM "\n",
            inode_toid);
        return 1;
    }

    // open the file to ID
    fs_file = tsk_fs_file_open_meta(fs, NULL, inode_toid);
    if (fs_file == NULL) {
        strncat(tsk_errstr2, " - ntfs_find_file",
            TSK_ERRSTR_L - strlen(tsk_errstr2));
        tsk_fs_file_close(fs_file);
        return 1;
    }

    // see if its allocation status meets the callback needs
    if ((fs_file->meta->flags & TSK_FS_META_FLAG_ALLOC)
        && ((dir_walk_flags & TSK_FS_DIR_WALK_FLAG_ALLOC) == 0)) {
        tsk_fs_file_close(fs_file);
        return 1;
    }
    else if ((fs_file->meta->flags & TSK_FS_META_FLAG_UNALLOC)
        && ((dir_walk_flags & TSK_FS_DIR_WALK_FLAG_UNALLOC) == 0)) {
        tsk_fs_file_close(fs_file);
        return 1;
    }


    /* Allocate a name and fill in some details  */
    if ((fs_file->name =
            tsk_fs_name_alloc(NTFS_MAXNAMLEN_UTF8, 0)) == NULL) {
        return 1;
    }
    fs_file->name->meta_addr = inode_toid;
    fs_file->name->meta_seq = 0;
    fs_file->name->flags =
        ((tsk_getu16(fs->endian,
                ntfs->
                mft->flags) & NTFS_MFT_INUSE) ? TSK_FS_NAME_FLAG_ALLOC :
        TSK_FS_NAME_FLAG_UNALLOC);

    memset(&dinfo, 0, sizeof(NTFS_DINFO));

    /* in this function, we use the dinfo->dirs array in the opposite order.
     * we set the end of it to NULL and then prepend the
     * directories to it
     *
     * dinfo->didx[dinfo->depth] will point to where the current level started their
     * dir name
     */
    dinfo.dirs[DIR_STRSZ - 2] = '/';
    dinfo.dirs[DIR_STRSZ - 1] = '\0';
    dinfo.didx[0] = &dinfo.dirs[DIR_STRSZ - 2];
    dinfo.depth = 1;


    /* Get the name for the attribute - if specified */
    if (type_used) {
        const TSK_FS_ATTR *fs_attr;

        if (id_used)
            fs_attr =
                tsk_fs_attrlist_get_id(fs_file->meta->attr, type_toid,
                id_toid);
        else
            fs_attr = tsk_fs_attrlist_get(fs_file->meta->attr, type_toid);

        if (!fs_attr) {
            tsk_error_reset();
            tsk_errno = TSK_ERR_FS_INODE_COR;
            snprintf(tsk_errstr, TSK_ERRSTR_L,
                "find_file: Type %" PRIu32 " Id %" PRIu16
                " not found in MFT %" PRIuINUM "", type_toid, id_toid,
                inode_toid);
            tsk_fs_file_close(fs_file);
            return 1;
        }

        /* only add the attribute name if it is the non-default data stream */
        if (strcmp(fs_attr->name, "$Data") != 0)
            attr = fs_attr->name;
    }

    /* loop through all the names it may have */
    for (fs_name_list = fs_file->meta->name2; fs_name_list != NULL;
        fs_name_list = fs_name_list->next) {
        int retval;

        /* Append on the attribute name, if it exists */
        if (attr != NULL) {
            snprintf(fs_file->name->name, fs_file->name->name_size,
                "%s:%s", fs_name_list->name, attr);
        }
        else {
            strncpy(fs_file->name->name, fs_name_list->name,
                fs_file->name->name_size);
        }

        /* if this is in the root directory, then call back */
        if (fs_name_list->par_inode == NTFS_ROOTINO) {

            retval = action(fs_file, dinfo.didx[0], ptr);
            if (retval == TSK_WALK_STOP) {
                tsk_fs_file_close(fs_file);
                return 0;
            }
            else if (retval == TSK_WALK_ERROR) {
                tsk_fs_file_close(fs_file);
                return 1;
            }
        }
        /* call the recursive function on the parent to get the full path */
        else {
            if (ntfs_find_file_rec(fs, &dinfo, fs_file, fs_name_list,
                    action, ptr)) {
                tsk_fs_file_close(fs_file);
                return 1;
            }
        }
    }                           /* end of name loop */

    tsk_fs_file_close(fs_file);
    return 0;
}
Пример #14
0
// XXX([email protected]): had better fix the comment
// find file of the given inode
// 
// \param fs         filesystem info structure defined in sleuthkit
// \param lclflags   traverse options defined in sleuthkit
// \param a_inode    the inode of the file
// \param type       filesystem type number
// \param type_used  don't know what it is, just give a 0(XXX)
// \param id         the id of file attribute that the inode refers
// \param id_used    don't know what it is, just give a 0(XXX)
// \param flags      traverse options difned in sleuthkit
// 
// Return 0 if error, otherwise a pointer
static MBA_FFIND_DATA*
fs_ffind(TSK_FS_INFO * fs, TSK_FS_FFIND_FLAG_ENUM lclflags,
    TSK_INUM_T a_inode,
    TSK_FS_ATTR_TYPE_ENUM type, uint8_t type_used,
    uint16_t id, uint8_t id_used, TSK_FS_DIR_WALK_FLAG_ENUM flags)
{
    MBA_FFIND_DATA* data=(MBA_FFIND_DATA*)malloc(sizeof(MBA_FFIND_DATA));
    char* orphan =NULL;
    int size = 0;

    if(data == NULL)
    {
        printf("Cannot allocate memory\n");
        return NULL;
    }

    data->found = 0;
    data->flags = lclflags;
    data->inode = a_inode;
    utarray_new(data->filenames, &ut_str_icd);


    /* Since we start the walk on the root inode, then this will not show
     ** up in the above functions, so do it now
     */
    if (data->inode == fs->root_inum) {
        if (flags & TSK_FS_DIR_WALK_FLAG_ALLOC) {
            //tsk_printf("/\n");
            data->found = 1;

            if (!(lclflags & TSK_FS_FFIND_ALL))
                return data;
        }
    }

    if (TSK_FS_TYPE_ISNTFS(fs->ftype)) {
        if (ntfs_find_file(fs, data->inode, type, type_used, id, id_used,
                flags, find_file_act, data))
            return NULL;
    }
    else {
        if (tsk_fs_dir_walk(fs, fs->root_inum, flags, find_file_act,
                data))
            return NULL;
    }

    if (data->found == 0) {

        /* With FAT, we can at least give the name of the file and call
         * it orphan
         */
        if (TSK_FS_TYPE_ISFAT(fs->ftype)) {
            TSK_FS_FILE *fs_file =
                tsk_fs_file_open_meta(fs, NULL, data->inode);
            if ((fs_file != NULL) && (fs_file->meta != NULL)
                && (fs_file->meta->name2 != NULL)) {
                //if (fs_file->meta->flags & TSK_FS_META_FLAG_UNALLOC)
                //    tsk_printf("* ");
                //tsk_printf("%s/%s\n", TSK_FS_ORPHAN_STR,
                //    fs_file->meta->name2->name);

                //Added Ophan file into file list
                size = strlen(TSK_FS_ORPHAN_STR) + strlen(fs_file->meta->name2->name)+2;
                orphan = (char*)malloc(size);
                if(orphan == NULL)
                {
                    printf("Cannot allocate memory\n");
                }else
                {
                    snprintf(orphan, size, "%s/%s", TSK_FS_ORPHAN_STR,fs_file->meta->name2->name);
                    utarray_push_back(data->filenames, orphan );
                }
            }
            if (fs_file)
                tsk_fs_file_close(fs_file);
        }
        else {
            tsk_printf("File name not found for inode\n");
        }
    }
    return data;
}
Пример #15
0
int TskImageFileTsk::openFile(const uint64_t fileId)
{
    if (m_img_info == NULL) {
        if (open() != 0)
            return -1;
    }

    // Use ImgDb::getFileUniqueIdentifiers to get the four needed values.
    uint64_t fsByteOffset = 0;
    uint64_t fsFileId = 0;
    int attrType = 0;
    int attrId = 0;

    if (m_db.getFileUniqueIdentifiers(fileId, fsByteOffset, fsFileId, attrType, attrId) != 0)
    {
        LOGERROR(L"TskImageFileTsk::openFile - Error getting file identifiers.\n");
        return -1;
    }

    // Check if the file system at the offset is already open (using m_openFs).  If not, open it (tsk_fs_open) and add it to the map.
    TSK_FS_INFO * fsInfo = m_openFs[fsByteOffset];

    if (fsInfo == NULL)
    {
        // Open the file system and add it to the map.
        fsInfo = tsk_fs_open_img(m_img_info, fsByteOffset, TSK_FS_TYPE_DETECT);

        if (fsInfo == NULL)
        {
            std::wstringstream errorMsg;
            errorMsg << L"TskImageFileTsk::openFile - Error opening file system : "
                << tsk_error_get() << std::endl;
            LOGERROR(errorMsg.str());
            return -1;
        }

        m_openFs[fsByteOffset] = fsInfo;
    }

    // Find a new entry in m_openFiles and use tsk_fs_file_open to open the file and save the handle in m_openFiles. 
    TSK_FS_FILE * fsFile = tsk_fs_file_open_meta(fsInfo, NULL, fsFileId);

    if (fsFile == NULL)
    {
        std::wstringstream errorMsg;
        errorMsg << L"TskImageFileTsk::openFile - Error opening file : "
            << tsk_error_get() << std::endl;
        LOGERROR(errorMsg.str());
        return -1;
    }

    TskImageFileTsk::OPEN_FILE * openFile = new TskImageFileTsk::OPEN_FILE();
    openFile->attrId = attrId;
    openFile->attrType = attrType;
    openFile->fsFile = fsFile;

    m_openFiles.push_back(openFile);

    // Return the index into m_openFiles
    return m_openFiles.size() - 1;
}
Пример #16
0
/* This test checks the SLACK flags and verifies
 * that we read data from the slack space
 */
int
test_ntfs_slack_ads()
{
    TSK_FS_INFO *fs;
    TSK_IMG_INFO *img;
    const char *tname = "ntfs-img-kw";
    char fname[512];
    TSK_FS_FILE *file1;
    char buf[512];
    ssize_t retval;

    snprintf(fname, 512, "%s/ntfs-img-kw-1.dd", s_root);
    if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
        fprintf(stderr, "Error opening %s image\n", tname);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }

    if ((fs = tsk_fs_open_img(img, 0, (TSK_FS_TYPE_ENUM) 0)) == NULL) {
        fprintf(stderr, "Error opening %s image\n", tname);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }


    // file-n-44.dat
    file1 = tsk_fs_file_open_meta(fs, NULL, 36);
    if (file1 == NULL) {
        fprintf(stderr, "Error opening file-n-4.dat (%s)\n", tname);
        return 1;
    }

    // verify expected size
    if (file1->meta->size != 2000) {
        fprintf(stderr,
            "Error: file-n-4.dat not expected size (%" PRIuOFF ") (%s)\n",
            file1->meta->size, tname);
        return 1;
    }

    // try to read all of last sector with/out Slack set
    retval =
        tsk_fs_file_read(file1, 1536, buf, 512,
        (TSK_FS_FILE_READ_FLAG_ENUM) 0);
    if (retval == -1) {
        fprintf(stderr,
            "Error reading file-n-4.dat to end w/out slack flag (%s)\n",
            tname);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }
    if (retval != 464) {
        fprintf(stderr,
            "Unexpected return value from reading file-n-4.dat to end w/out slack flag (%s).\n",
            tname);
        fprintf(stderr, "Expected: 464.  Got: %zd\n", retval);
        return 1;
    }

    retval =
        tsk_fs_file_read(file1, 1536, buf, 512,
        TSK_FS_FILE_READ_FLAG_SLACK);
    if (retval == -1) {
        fprintf(stderr,
            "Error reading file-n-4.dat to end w/slack flag (%s)\n",
            tname);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }
    if (retval != 512) {
        fprintf(stderr,
            "Unexpected return value from reading file-n-4.dat  w/slack flag. (%s)\n",
            tname);
        fprintf(stderr, "Expected: 512.  Got: %zd\n", retval);
        return 1;
    }

    // verify the term in the slack space
    if (memcmp("n-slack", &buf[485], 7) != 0) {
        fprintf(stderr,
            "slack string not found in file-n-4.dat slack space: %c %c %c %c %c %c %c (%s)\n",
            buf[485], buf[486], buf[487], buf[488], buf[489], buf[490],
            buf[491], tname);
        return 1;
    }


    // try to read past end of file 
    retval =
        tsk_fs_file_read(file1, 2001, buf, 32,
        (TSK_FS_FILE_READ_FLAG_ENUM) 0);
    if (retval != -1) {
        fprintf(stderr,
            "Unexpected return value from reading file-n-4.dat after end of file (%s).\n",
            tname);
        fprintf(stderr, "Expected: -1.  Got: %zd\n", retval);
        return 1;
    }


    tsk_fs_file_close(file1);

    // file-n-5.dat
    file1 = tsk_fs_file_open_meta(fs, NULL, 37);
    if (file1 == NULL) {
        fprintf(stderr, "Error opening file-n-5.dat (%s)\n", tname);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }

    // check the default size to make sure it is the default $Data
    if (file1->meta->size != 1300) {
        fprintf(stderr,
            "file-n-5.dat size is not 1300 (%" PRIuOFF ") (%s)",
            file1->meta->size, tname);
        return 1;
    }

    // test the getsize API for both attributes
    const TSK_FS_ATTR *fs_attr =
        tsk_fs_file_attr_get_type(file1, TSK_FS_ATTR_TYPE_NTFS_DATA, 3, 1);
    if (!fs_attr) {
        fprintf(stderr,
            "Error getting data attribute 3 in file-n-5.dat (%s)", tname);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }
    if (fs_attr->size != 1300) {
        fprintf(stderr,
            "file-n-5.dat size (via getsize) is not 1300 (%" PRIuOFF
            ") (%s)", fs_attr->size, tname);
        return 1;
    }

    fs_attr =
        tsk_fs_file_attr_get_type(file1, TSK_FS_ATTR_TYPE_NTFS_DATA, 5, 1);
    if (!fs_attr) {
        fprintf(stderr,
            "Error getting size of attribute 5 in file-n-5.dat (%s)",
            tname);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }
    if (fs_attr->size != 2000) {
        fprintf(stderr,
            "file-n-5.dat:here size (via getsize) is not 2000 (%" PRIuOFF
            ") (%s)", fs_attr->size, tname);
        return 1;
    }

    tsk_fs_file_close(file1);

    tsk_fs_close(fs);
    tsk_img_close(img);
    return 0;
}
Пример #17
0
TSK_RETVAL_ENUM
fatfs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
    TSK_INUM_T a_addr)
{
    TSK_OFF_T size, len;
    FATFS_INFO *fatfs = (FATFS_INFO *) a_fs;
    char *dirbuf;
    TSK_DADDR_T *addrbuf;
    FATFS_LOAD_DIR load;
    int retval;

    TSK_FS_DIR *fs_dir;

    if ((a_addr < a_fs->first_inum) || (a_addr > a_fs->last_inum)) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
        tsk_error_set_errstr("fatfs_dir_open_meta: invalid a_addr value: %"
            PRIuINUM "\n", a_addr);
        return TSK_ERR;
    }
    else if (a_fs_dir == NULL) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_ARG);
        tsk_error_set_errstr
            ("fatfs_dir_open_meta: NULL fs_attr argument given");
        return TSK_ERR;
    }

    fs_dir = *a_fs_dir;
    if (fs_dir) {
        tsk_fs_dir_reset(fs_dir);
    }
    else {
        if ((*a_fs_dir = fs_dir =
                tsk_fs_dir_alloc(a_fs, a_addr, 128)) == NULL) {
            return TSK_ERR;
        }
    }

    //  handle the orphan directory if its contents were requested
    if (a_addr == TSK_FS_ORPHANDIR_INUM(a_fs)) {
        return tsk_fs_dir_find_orphans(a_fs, fs_dir);
    }

    fs_dir->fs_file = tsk_fs_file_open_meta(a_fs, NULL, a_addr);
    if (fs_dir->fs_file == NULL) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_INODE_NUM);
        tsk_error_set_errstr("fatfs_dir_open_meta: %" PRIuINUM
            " is not a valid inode", a_addr);
        return TSK_COR;
    }

    size = fs_dir->fs_file->meta->size;
    len = roundup(size, fatfs->ssize);

    if (tsk_verbose)
        tsk_fprintf(stderr,
            "fatfs_dir_open_meta: Processing directory %" PRIuINUM "\n",
            a_addr);

    if (size == 0) {
        if (tsk_verbose)
            tsk_fprintf(stderr,
                "fatfs_dir_open_meta: directory has 0 size\n");
        return TSK_OK;
    }

    /* Make a copy of the directory contents using file_walk */
    if ((dirbuf = tsk_malloc((size_t) len)) == NULL) {
        return TSK_ERR;
    }
    load.curdirptr = dirbuf;
    load.dirleft = (size_t) size;

    /* We are going to save the address of each sector in the directory
     * in a stack - they are needed to determine the inode address.
     */
    load.addrsize = (size_t) (len / fatfs->ssize);
    addrbuf =
        (TSK_DADDR_T *) tsk_malloc(load.addrsize * sizeof(TSK_DADDR_T));
    if (addrbuf == NULL) {
        free(dirbuf);
        return TSK_ERR;
    }

    /* Set the variables that are used during the copy */
    load.addridx = 0;
    load.addrbuf = addrbuf;

    /* save the directory contents into dirbuf */
    if (tsk_fs_file_walk(fs_dir->fs_file,
            TSK_FS_FILE_WALK_FLAG_SLACK,
            fatfs_dent_action, (void *) &load)) {
        tsk_error_errstr2_concat("- fatfs_dir_open_meta");
        free(dirbuf);
        free(addrbuf);
        return TSK_COR;
    }

    /* We did not copy the entire directory, which occurs if an error occured */
    if (load.dirleft > 0) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_FWALK);
        tsk_error_set_errstr
            ("fatfs_dir_open_meta: Error reading directory %" PRIuINUM,
            a_addr);

        /* Free the local buffers */
        free(dirbuf);
        free(addrbuf);
        return TSK_COR;
    }

    if (tsk_verbose)
        fprintf(stderr,
            "fatfs_dir_open_meta: Parsing directory %" PRIuINUM "\n",
            a_addr);

    retval = fatfs_dent_parse_buf(fatfs, fs_dir, dirbuf, len, addrbuf);

    free(dirbuf);
    free(addrbuf);

    // if we are listing the root directory, add the Orphan directory and special FAT file entries
    if (a_addr == a_fs->root_inum) {
        TSK_FS_NAME *fs_name = tsk_fs_name_alloc(256, 0);
        if (fs_name == NULL)
            return TSK_ERR;

        // MBR Entry
        strncpy(fs_name->name, FATFS_MBRNAME, fs_name->name_size);
        fs_name->meta_addr = FATFS_MBRINO(a_fs);
        fs_name->type = TSK_FS_NAME_TYPE_VIRT;
        fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
        if (tsk_fs_dir_add(fs_dir, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }

        // FAT1 Entry
        strncpy(fs_name->name, FATFS_FAT1NAME, fs_name->name_size);
        fs_name->meta_addr = FATFS_FAT1INO(a_fs);
        fs_name->type = TSK_FS_NAME_TYPE_VIRT;
        fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
        if (tsk_fs_dir_add(fs_dir, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }

        // FAT2 Entry
        strncpy(fs_name->name, FATFS_FAT2NAME, fs_name->name_size);
        fs_name->meta_addr = FATFS_FAT2INO(a_fs);
        fs_name->type = TSK_FS_NAME_TYPE_VIRT;
        fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
        if (tsk_fs_dir_add(fs_dir, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }

        // orphan directory
        if (tsk_fs_dir_make_orphan_dir_name(a_fs, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }
        if (tsk_fs_dir_add(fs_dir, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }
        tsk_fs_name_free(fs_name);
    }

    return retval;
}
Пример #18
0
/**
 * Populates the buffer with the contents of the specified filename.
 *
 * \param id_number The id number of the file (in our case the inode)
 * \param filename The real filename for this file.
 * \param buf The buffer to write data into
 * \param size The size of the buffer
 * \param offset The offset into the file the data should be taken from.
 * \returns The amount of bytes read, or -1 on error.
 */
int do_read(unsigned int id_number, const char *filename, char *buf, size_t size, off_t offset)
{
//FILE* outfile = fopen("/tmp/sleuth.txt", "a");
//fprintf(outfile, "do_read(%u, %s, %p, %zu, %zu);\n", id_number, filename, buf, size, offset);
//fflush(outfile);
//fprintf(outfile, "inode_buffer=%p, inode_buffered=%lld, inode_buf_pos=%llu, end=%llu\n", inode_buffer, inode_buffered, inode_buffer_pos, inode_buffer_pos + inode_buffer_size);
//fflush(outfile);
  // If the data is already cached in our buffer then read from that instead
  if ((inode_buffer != NULL) && (id_number == inode_buffered) && (offset >= inode_buffer_pos) && (offset < inode_buffer_pos + inode_buffer_size))
  {
    if ((offset + size) <= (inode_buffer_pos + inode_buffer_size))
    {
      offset = offset % BUFFER_AMOUNT;
      memcpy(buf, inode_buffer + offset, size);
//fprintf(outfile, "Fully cached!\n");
//fclose(outfile);
      return size;
    }
    // If we're here then we've cached part of the data needed, but not all of it
    // (ie, the data requested spans a block boundary)
    offset = offset % BUFFER_AMOUNT;
    memcpy(buf, inode_buffer + offset, inode_buffer_size - offset);
    int ret_size = inode_buffer_size - offset;

    ret_size += do_read(id_number, filename, buf + ret_size, size - ret_size, inode_buffer_pos + inode_buffer_size);
//fprintf(outfile, "Partially cached: Size = %d\n", ret_size);
//fclose(outfile);
    return ret_size;
  }

  TSK_FS_FILE *fs_file = tsk_fs_file_open_meta(fs_info, NULL, id_number);

  if (fs_file == NULL)
  {
//fprintf(outfile, "FS file not found?\n");
//fclose(outfile);
    return -1;
  }
  // If the file is larger than FILE_SIZE_THRESHOLD, and the offset is larger 
  // than FILE_OFFSET_THRESHOLD, buffer up BUFFER_AMOUNT and return from that

  if (fs_file->meta != NULL)
  {
//fprintf(outfile, "File size is %" PRIdDADDR" bytes\n", fs_file->meta->size);
//fflush(outfile);
    if (offset >= fs_file->meta->size)
    {
//fprintf(outfile, "Reading beyond end of file\n");
//fclose(outfile);
      return 0;
    }
    if ((fs_file->meta->size >= FILE_SIZE_THRESHOLD) && (offset >= FILE_OFFSET_THRESHOLD))
    {
      if (inode_buffer == NULL)
      {
        inode_buffer = (unsigned char *) g_malloc(BUFFER_AMOUNT);
      }
      inode_buffered = id_number;
      inode_buffer_pos = (offset / BUFFER_AMOUNT) * BUFFER_AMOUNT;

      struct read_struct r;

      r.buf = inode_buffer;
      r.offset = inode_buffer_pos;
      r.size = BUFFER_AMOUNT;
      r.read = 0;

//fprintf(outfile, "Caching data...offset = %zu, size =%zu\n", r.offset, r.size);
//fflush(outfile);
      tsk_fs_file_walk(fs_file, TSK_FS_FILE_WALK_FLAG_NONE, read_file_content_callback, &r);

      inode_buffer_size = r.read;
//fprintf(outfile, "Recursing to read data\n");
//fclose(outfile);
      return do_read(id_number, filename, buf, size, offset);
    }
  }

  struct read_struct r;

  r.buf = (unsigned char *) buf;
  r.offset = offset;
  r.size = size;
  r.read = 0;

  tsk_fs_file_walk(fs_file, TSK_FS_FILE_WALK_FLAG_NONE, read_file_content_callback, &r);
  tsk_fs_file_close(fs_file);

//fprintf(outfile, "Simple read %zu\n", r.read);
//fclose(outfile);
  return r.read;
}
Пример #19
0
/* 
 * Looks up the parent inode described in fs_name. 
 *
 * fs_name was filled in by ntfs_find_file and will get the final path
 * added to it before action is called
 *
 * return 1 on error and 0 on success
 */
static uint8_t
ntfs_find_file_rec(TSK_FS_INFO * fs, NTFS_DINFO * dinfo,
    TSK_FS_FILE * fs_file, TSK_FS_META_NAME_LIST * fs_name_list,
    TSK_FS_DIR_WALK_CB action, void *ptr)
{
    TSK_FS_FILE *fs_file_par;
    TSK_FS_META_NAME_LIST *fs_name_list_par;
    uint8_t decrem = 0;
    size_t len = 0, i;
    char *begin = NULL;
    int retval;


    if (fs_name_list->par_inode < fs->first_inum ||
        fs_name_list->par_inode > fs->last_inum) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_ARG;
        snprintf(tsk_errstr, TSK_ERRSTR_L,
            "invalid inode value: %" PRIuINUM "\n",
            fs_name_list->par_inode);
        return 1;
    }

    fs_file_par = tsk_fs_file_open_meta(fs, NULL, fs_name_list->par_inode);
    if (fs_file_par == NULL) {
        strncat(tsk_errstr2, " - ntfs_find_file_rec",
            TSK_ERRSTR_L - strlen(tsk_errstr2));
        return 1;
    }

    /* 
     * Orphan File
     * This occurs when the file is deleted and either:
     * - The parent is no longer a directory 
     * - The sequence number of the parent is no longer correct
     */
    if ((fs_file_par->meta->type != TSK_FS_META_TYPE_DIR)
        || (fs_file_par->meta->seq != fs_name_list->par_seq)) {
        char *str = TSK_FS_ORPHAN_STR;
        len = strlen(str);

        /* @@@ There should be a sanity check here to verify that the 
         * previous name was unallocated ... but how do I get it again?
         */
        if ((((uintptr_t) dinfo->didx[dinfo->depth - 1] - len) >=
                (uintptr_t) & dinfo->dirs[0])
            && (dinfo->depth < MAX_DEPTH)) {
            begin = dinfo->didx[dinfo->depth] =
                (char *) ((uintptr_t) dinfo->didx[dinfo->depth - 1] - len);

            dinfo->depth++;
            decrem = 1;

            for (i = 0; i < len; i++)
                begin[i] = str[i];
        }

        retval = action(fs_file, begin, ptr);

        if (decrem)
            dinfo->depth--;

        tsk_fs_file_close(fs_file_par);
        return (retval == TSK_WALK_ERROR) ? 1 : 0;
    }

    for (fs_name_list_par = fs_file_par->meta->name2;
        fs_name_list_par != NULL;
        fs_name_list_par = fs_name_list_par->next) {

        len = strlen(fs_name_list_par->name);

        /* do some length checks on the dir structure 
         * if we can't fit it then forget about it */
        if ((((uintptr_t) dinfo->didx[dinfo->depth - 1] - len - 1) >=
                (uintptr_t) & dinfo->dirs[0])
            && (dinfo->depth < MAX_DEPTH)) {
            begin = dinfo->didx[dinfo->depth] =
                (char *) ((uintptr_t) dinfo->didx[dinfo->depth - 1] - len -
                1);

            dinfo->depth++;
            decrem = 1;

            *begin = '/';
            for (i = 0; i < len; i++)
                begin[i + 1] = fs_name_list_par->name[i];
        }
        else {
            begin = dinfo->didx[dinfo->depth];
            decrem = 0;
        }


        /* if we are at the root, then fill out the rest of fs_name with
         * the full path and call the action 
         */
        if (fs_name_list_par->par_inode == NTFS_ROOTINO) {
            /* increase the path by one so that we do not pass the '/'
             * if we do then the printed result will have '//' at 
             * the beginning
             */
            if (TSK_WALK_ERROR == action(fs_file,
                    (const char *) ((uintptr_t) begin + 1), ptr)) {
                tsk_fs_file_close(fs_file_par);
                return 1;
            }
        }

        /* otherwise, recurse some more */
        else {
            if (ntfs_find_file_rec(fs, dinfo, fs_file, fs_name_list_par,
                    action, ptr)) {
                tsk_fs_file_close(fs_file_par);
                return 1;
            }
        }

        /* if we incremented before, then decrement the depth now */
        if (decrem)
            dinfo->depth--;
    }

    tsk_fs_file_close(fs_file_par);

    return 0;
}
Пример #20
0
/* This test checks the SLACK flags and verifies
 * that we read data from the slack space
 */
int
test_fat_slack()
{
    TSK_FS_INFO *fs;
    TSK_IMG_INFO *img;
    const char *tname = "fat-img-kw";
    char fname[512];
    TSK_FS_FILE *file1;
    char buf[512];
    ssize_t retval;

    snprintf(fname, 512, "%s/fat-img-kw.dd", s_root);
    if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
        fprintf(stderr, "Error opening %s image\n", tname);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }

    if ((fs = tsk_fs_open_img(img, 0, (TSK_FS_TYPE_ENUM) 0)) == NULL) {
        fprintf(stderr, "Error opening %s image\n", tname);
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }


    // file4.dat
    file1 = tsk_fs_file_open_meta(fs, NULL, 10);
    if (file1 == NULL) {
        fprintf(stderr, "Error opening file4.dat (%s)\n", tname);
        return 1;
    }

    // verify expected size
    if (file1->meta->size != 631) {
        fprintf(stderr,
            "Error: file4.dat not expected size (%" PRIuOFF ") (%s)\n",
            file1->meta->size, tname);
        return 1;
    }

    // try to read all of last sector with/out Slack set
    retval =
        tsk_fs_file_read(file1, 512, buf, 512,
        (TSK_FS_FILE_READ_FLAG_ENUM) 0);
    if (retval == -1) {
        fprintf(stderr,
            "Error reading file4.dat to end w/out slack flag\n");
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }
    if (retval != 119) {
        fprintf(stderr,
            "Unexpected return value from reading file4.dat to end w/out slack flag.\n");
        fprintf(stderr, "Expected: 119.  Got: %zd\n", retval);
        return 1;
    }

    retval =
        tsk_fs_file_read(file1, 512, buf, 512,
        TSK_FS_FILE_READ_FLAG_SLACK);
    if (retval == -1) {
        fprintf(stderr, "Error reading file4.dat to end w/slack flag\n");
        tsk_error_print(stderr);
        tsk_error_reset();
        return 1;
    }
    if (retval != 512) {
        fprintf(stderr,
            "Unexpected return value from reading file4.dat  w/slack flag.\n");
        fprintf(stderr, "Expected: 512.  Got: %zd\n", retval);
        return 1;
    }

    // verify the term in the slack space
    if (memcmp("3slack3", &buf[385], 7) != 0) {
        fprintf(stderr,
            "slack string not found in file4.dat slack space: %x %x %x %x %x %x %x\n",
            buf[385], buf[386], buf[387], buf[388], buf[389], buf[390],
            buf[391]);
        return 1;
    }


    tsk_fs_close(fs);
    tsk_img_close(img);
    return 0;
}
Пример #21
0
/** \internal
* Process a directory and load up FS_DIR with the entries. If a pointer to
* an already allocated FS_DIR struture is given, it will be cleared.  If no existing
* FS_DIR structure is passed (i.e. NULL), then a new one will be created. If the return 
* value is error or corruption, then the FS_DIR structure could  
* have entries (depending on when the error occured). 
*
* @param a_fs File system to analyze
* @param a_fs_dir Pointer to FS_DIR pointer. Can contain an already allocated
* structure or a new structure. 
* @param a_addr Address of directory to process.
* @returns error, corruption, ok etc. 
*/
TSK_RETVAL_ENUM
ntfs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
    TSK_INUM_T a_addr)
{
    NTFS_INFO *ntfs = (NTFS_INFO *) a_fs;
    TSK_FS_DIR *fs_dir;
    const TSK_FS_ATTR *fs_attr_root = NULL;
    const TSK_FS_ATTR *fs_attr_idx;
    char *idxalloc;
    ntfs_idxentry *idxe;
    ntfs_idxroot *idxroot;
    ntfs_idxelist *idxelist;
    ntfs_idxrec *idxrec_p, *idxrec;
    int off;
    TSK_OFF_T idxalloc_len;
    TSK_FS_LOAD_FILE load_file;
    NTFS_PAR_MAP *map;

    /* In this function, we will return immediately if we get an error.
     * If we get corruption though, we will record that in 'retval_final'
     * and continue processing. 
     */
    TSK_RETVAL_ENUM retval_final = TSK_OK;
    TSK_RETVAL_ENUM retval_tmp;

    /* sanity check */
    if (a_addr < a_fs->first_inum || a_addr > a_fs->last_inum) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_WALK_RNG;
        snprintf(tsk_errstr, TSK_ERRSTR_L,
            "ntfs_dir_open_meta: inode value: %" PRIuINUM "\n", a_addr);
        return TSK_ERR;
    }
    else if (a_fs_dir == NULL) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_ARG;
        snprintf(tsk_errstr, TSK_ERRSTR_L,
            "ntfs_dir_open_meta: NULL fs_attr argument given");
        return TSK_ERR;
    }

    if (tsk_verbose)
        tsk_fprintf(stderr,
            "ntfs_open_dir: Processing directory %" PRIuINUM "\n", a_addr);


    fs_dir = *a_fs_dir;
    if (fs_dir) {
        tsk_fs_dir_reset(fs_dir);
    }
    else {
        if ((*a_fs_dir = fs_dir = tsk_fs_dir_alloc(a_fs, 128)) == NULL) {
            return TSK_ERR;
        }
    }

    //  handle the orphan directory if its contents were requested
    if (a_addr == TSK_FS_ORPHANDIR_INUM(a_fs)) {
        return tsk_fs_dir_find_orphans(a_fs, fs_dir);
    }

    /* Get the inode and verify it has attributes */
    if ((fs_dir->fs_file =
            tsk_fs_file_open_meta(a_fs, NULL, a_addr)) == NULL) {
        strncat(tsk_errstr2, " - ntfs_dir_open_meta",
            TSK_ERRSTR_L - strlen(tsk_errstr2));
        return TSK_COR;
    }

    if (!(fs_dir->fs_file->meta->attr)) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_INODE_COR;
        snprintf(tsk_errstr, TSK_ERRSTR_L,
            "dent_walk: Error: Directory address %" PRIuINUM
            " has no attributes", a_addr);
        return TSK_COR;
    }


    /* 
     * Read the Index Root Attribute  -- we do some sanity checking here
     * to report errors before we start to make up data for the "." and ".."
     * entries
     */
    fs_attr_root =
        tsk_fs_attrlist_get(fs_dir->fs_file->meta->attr,
        NTFS_ATYPE_IDXROOT);
    if (!fs_attr_root) {
        strncat(tsk_errstr2, " - dent_walk: $IDX_ROOT not found",
            TSK_ERRSTR_L - strlen(tsk_errstr2));
        return TSK_COR;
    }

    if (fs_attr_root->flags & TSK_FS_ATTR_NONRES) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_INODE_COR;
        snprintf(tsk_errstr, TSK_ERRSTR_L,
            "dent_walk: $IDX_ROOT is not resident - it should be");
        return TSK_COR;
    }
    idxroot = (ntfs_idxroot *) fs_attr_root->rd.buf;

    /* Verify that the attribute type is $FILE_NAME */
    if (tsk_getu32(a_fs->endian, idxroot->type) == 0) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_INODE_COR;
        snprintf(tsk_errstr, TSK_ERRSTR_L,
            "dent_walk: Attribute type in index root is 0");
        return TSK_COR;
    }
    else if (tsk_getu32(a_fs->endian, idxroot->type) != NTFS_ATYPE_FNAME) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_INODE_COR;
        snprintf(tsk_errstr, TSK_ERRSTR_L,
            "ERROR: Directory index is sorted by type: %" PRIu32
            ".\nOnly $FNAME is currently supported",
            tsk_getu32(a_fs->endian, idxroot->type));
        return TSK_COR;
    }

    /* Get the header of the index entry list */
    idxelist = &idxroot->list;

    /* Get the offset to the start of the index entry list */
    idxe = (ntfs_idxentry *) ((uintptr_t) idxelist +
        tsk_getu32(a_fs->endian, idxelist->begin_off));

    /* 
     * NTFS does not have "." and ".." entries in the index trees
     * (except for a "." entry in the root directory)
     * 
     * So, we'll make 'em up by making a TSK_FS_NAME structure for
     * a '.' and '..' entry and call the action
     */
    if (a_addr != a_fs->root_inum) {    // && (flags & TSK_FS_NAME_FLAG_ALLOC)) {
        TSK_FS_NAME *fs_name;
        TSK_FS_META_NAME_LIST *fs_name_list;

        if (tsk_verbose)
            tsk_fprintf(stderr,
                "ntfs_dir_open_meta: Creating . and .. entries\n");

        if ((fs_name = tsk_fs_name_alloc(16, 0)) == NULL) {
            return TSK_ERR;
        }
        /* 
         * "." 
         */
        fs_name->meta_addr = a_addr;
        fs_name->meta_seq = fs_dir->fs_file->meta->seq;
        fs_name->type = TSK_FS_NAME_TYPE_DIR;
        strcpy(fs_name->name, ".");

        fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
        if (tsk_fs_dir_add(fs_dir, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }


        /*
         * ".."
         */
        strcpy(fs_name->name, "..");
        fs_name->type = TSK_FS_NAME_TYPE_DIR;

        /* The fs_name structure holds the parent inode value, so we 
         * just cycle using those
         */
        for (fs_name_list = fs_dir->fs_file->meta->name2;
            fs_name_list != NULL; fs_name_list = fs_name_list->next) {
            fs_name->meta_addr = fs_name_list->par_inode;
            fs_name->meta_seq = fs_name_list->par_seq;
            if (tsk_fs_dir_add(fs_dir, fs_name)) {
                tsk_fs_name_free(fs_name);
                return TSK_ERR;
            }
        }

        tsk_fs_name_free(fs_name);
        fs_name = NULL;
    }

    /* Now we return to processing the Index Root Attribute */
    if (tsk_verbose)
        tsk_fprintf(stderr,
            "ntfs_dir_open_meta: Processing $IDX_ROOT of inum %" PRIuINUM
            "\n", a_addr);

    /* Verify the offset pointers */
    if ((tsk_getu32(a_fs->endian, idxelist->seqend_off) <
            tsk_getu32(a_fs->endian, idxelist->begin_off)) ||
        (tsk_getu32(a_fs->endian, idxelist->bufend_off) <
            tsk_getu32(a_fs->endian, idxelist->seqend_off)) ||
        (((uintptr_t) idxe + tsk_getu32(a_fs->endian,
                    idxelist->bufend_off)) >
            ((uintptr_t) fs_attr_root->rd.buf +
                fs_attr_root->rd.buf_size))) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_INODE_COR;
        snprintf(tsk_errstr, TSK_ERRSTR_L,
            "Error: Index list offsets are invalid on entry: %" PRIuINUM,
            fs_dir->fs_file->meta->addr);
        return TSK_COR;
    }

    retval_tmp = ntfs_proc_idxentry(ntfs, fs_dir,
        (fs_dir->fs_file->meta->flags & TSK_FS_META_FLAG_UNALLOC) ? 1 : 0,
        idxe,
        tsk_getu32(a_fs->endian, idxelist->bufend_off) -
        tsk_getu32(a_fs->endian, idxelist->begin_off),
        tsk_getu32(a_fs->endian, idxelist->seqend_off) -
        tsk_getu32(a_fs->endian, idxelist->begin_off));

    // stop if we get an error, continue if we got corruption
    if (retval_tmp == TSK_ERR) {
        return TSK_ERR;
    }
    else if (retval_tmp == TSK_COR) {
        retval_final = TSK_COR;
    }

    /* 
     * get the index allocation attribute if it exists (it doesn't for 
     * small directories 
     */
    fs_attr_idx =
        tsk_fs_attrlist_get(fs_dir->fs_file->meta->attr,
        NTFS_ATYPE_IDXALLOC);


    /* if we don't have an index alloc then return, we have processed
     * all of the entries 
     */
    if (!fs_attr_idx) {
        if (tsk_getu32(a_fs->endian,
                idxelist->flags) & NTFS_IDXELIST_CHILD) {
            tsk_error_reset();
            tsk_errno = TSK_ERR_FS_INODE_COR;
            snprintf(tsk_errstr, TSK_ERRSTR_L,
                "Error: $IDX_ROOT says there should be children, but there isn't");
            return TSK_COR;
        }
    }
    else {

        if (fs_attr_idx->flags & TSK_FS_ATTR_RES) {
            tsk_error_reset();
            tsk_errno = TSK_ERR_FS_INODE_COR;
            snprintf(tsk_errstr, TSK_ERRSTR_L,
                "$IDX_ALLOC is Resident - it shouldn't be");
            return TSK_COR;
        }

        /* 
         * Copy the index allocation run into a big buffer
         */
        idxalloc_len = fs_attr_idx->nrd.allocsize;
        if ((idxalloc = tsk_malloc((size_t) idxalloc_len)) == NULL) {
            return TSK_ERR;
        }

        /* Fill in the loading data structure */
        load_file.total = load_file.left = (size_t) idxalloc_len;
        load_file.cur = load_file.base = idxalloc;

        if (tsk_verbose)
            tsk_fprintf(stderr,
                "ntfs_dir_open_meta: Copying $IDX_ALLOC into buffer\n");

        if (tsk_fs_attr_walk(fs_attr_idx,
                TSK_FS_FILE_WALK_FLAG_SLACK, tsk_fs_load_file_action,
                (void *) &load_file)) {
            free(idxalloc);
            strncat(tsk_errstr2, " - ntfs_dir_open_meta",
                TSK_ERRSTR_L - strlen(tsk_errstr2));
            return TSK_COR;     // this could be an error though
        }

        /* Not all of the directory was copied, so we exit */
        if (load_file.left > 0) {
            free(idxalloc);

            tsk_error_reset();
            tsk_errno = TSK_ERR_FS_FWALK;
            snprintf(tsk_errstr, TSK_ERRSTR_L,
                "Error reading directory contents: %" PRIuINUM "\n",
                a_addr);
            return TSK_COR;
        }

        /*
         * The idxalloc is a big buffer that contains one or more
         * idx buffer structures.  Each idxrec is a node in the B-Tree.  
         * We do not process the tree as a tree because then we could
         * not find the deleted file names.
         *
         * Therefore, we scan the big buffer looking for the index record
         * structures.  We save a pointer to the known beginning (idxrec_p).
         * Then we scan for the beginning of the next one (idxrec) and process
         * everything in the middle as an ntfs_idxrec.  We can't use the
         * size given because then we wouldn't see the deleted names
         */

        /* Set the previous pointer to NULL */
        idxrec_p = idxrec = NULL;

        /* Loop by cluster size */
        for (off = 0; off < idxalloc_len; off += ntfs->csize_b) {
            uint32_t list_len, rec_len;

            idxrec = (ntfs_idxrec *) & idxalloc[off];

            if (tsk_verbose)
                tsk_fprintf(stderr,
                    "ntfs_dir_open_meta: Index Buffer Offset: %d  Magic: %"
                    PRIx32 "\n", off, tsk_getu32(a_fs->endian,
                        idxrec->magic));

            /* Is this the begining of an index record? */
            if (tsk_getu32(a_fs->endian,
                    idxrec->magic) != NTFS_IDXREC_MAGIC)
                continue;


            /* idxrec_p is only NULL for the first time 
             * Set it and start again to find the next one */
            if (idxrec_p == NULL) {
                idxrec_p = idxrec;
                continue;
            }

            /* Process the previous structure */

            /* idxrec points to the next idxrec structure, idxrec_p
             * points to the one we are going to process
             */
            rec_len =
                (uint32_t) ((uintptr_t) idxrec - (uintptr_t) idxrec_p);

            if (tsk_verbose)
                tsk_fprintf(stderr,
                    "ntfs_dir_open_meta: Processing previous index record (len: %"
                    PRIu32 ")\n", rec_len);

            /* remove the update sequence in the index record */
            if (ntfs_fix_idxrec(ntfs, idxrec_p, rec_len)) {
                free(idxalloc);
                return TSK_COR;
            }

            /* Locate the start of the index entry list */
            idxelist = &idxrec_p->list;
            idxe = (ntfs_idxentry *) ((uintptr_t) idxelist +
                tsk_getu32(a_fs->endian, idxelist->begin_off));

            /* the length from the start of the next record to where our
             * list starts.
             * This should be the same as bufend_off in idxelist, but we don't
             * trust it.
             */
            list_len = (uint32_t) ((uintptr_t) idxrec - (uintptr_t) idxe);

            /* Verify the offset pointers */
            if (((uintptr_t) idxe > (uintptr_t) idxrec) ||
                ((uintptr_t) idxelist +
                    tsk_getu32(a_fs->endian,
                        idxelist->seqend_off) > (uintptr_t) idxrec)) {
                tsk_error_reset();
                tsk_errno = TSK_ERR_FS_INODE_COR;
                snprintf(tsk_errstr, TSK_ERRSTR_L,
                    "Error: Index list offsets are invalid on entry: %"
                    PRIuINUM, fs_dir->fs_file->meta->addr);
                free(idxalloc);
                return TSK_COR;
            }


            /* process the list of index entries */
            retval_tmp = ntfs_proc_idxentry(ntfs, fs_dir,
                (fs_dir->fs_file->
                    meta->flags & TSK_FS_META_FLAG_UNALLOC) ? 1 : 0, idxe,
                list_len, tsk_getu32(a_fs->endian,
                    idxelist->seqend_off) - tsk_getu32(a_fs->endian,
                    idxelist->begin_off));
            // stop if we get an error, record if we get corruption
            if (retval_tmp == TSK_ERR) {
                free(idxalloc);
                return TSK_ERR;
            }
            else if (retval_tmp == TSK_COR) {
                retval_final = TSK_COR;
            }

            /* reset the pointer to the next record */
            idxrec_p = idxrec;

        }                       /* end of cluster loop */


        /* Process the final record */
        if (idxrec_p) {
            uint32_t list_len, rec_len;

            /* Length from end of attribute to start of this */
            rec_len =
                (uint32_t) (idxalloc_len - (uintptr_t) idxrec_p -
                (uintptr_t) idxalloc);

            if (tsk_verbose)
                tsk_fprintf(stderr,
                    "ntfs_dir_open_meta: Processing final index record (len: %"
                    PRIu32 ")\n", rec_len);

            /* remove the update sequence */
            if (ntfs_fix_idxrec(ntfs, idxrec_p, rec_len)) {
                free(idxalloc);
                return TSK_COR;
            }

            idxelist = &idxrec_p->list;
            idxe = (ntfs_idxentry *) ((uintptr_t) idxelist +
                tsk_getu32(a_fs->endian, idxelist->begin_off));

            /* This is the length of the idx entries */
            list_len =
                (uint32_t) ((uintptr_t) idxalloc + idxalloc_len) -
                (uintptr_t) idxe;

            /* Verify the offset pointers */
            if ((list_len > rec_len) ||
                ((uintptr_t) idxelist +
                    tsk_getu32(a_fs->endian, idxelist->seqend_off) >
                    (uintptr_t) idxalloc + idxalloc_len)) {
                tsk_error_reset();
                tsk_errno = TSK_ERR_FS_INODE_COR;
                snprintf(tsk_errstr, TSK_ERRSTR_L,
                    "Error: Index list offsets are invalid on entry: %"
                    PRIuINUM, fs_dir->fs_file->meta->addr);
                free(idxalloc);
                return TSK_COR;
            }

            /* process the list of index entries */
            retval_tmp = ntfs_proc_idxentry(ntfs, fs_dir,
                (fs_dir->fs_file->
                    meta->flags & TSK_FS_META_FLAG_UNALLOC) ? 1 : 0, idxe,
                list_len, tsk_getu32(a_fs->endian,
                    idxelist->seqend_off) - tsk_getu32(a_fs->endian,
                    idxelist->begin_off));
            // stop if we get an error, record if we get corruption
            if (retval_tmp == TSK_ERR) {
                free(idxalloc);
                return TSK_ERR;
            }
            else if (retval_tmp == TSK_COR) {
                retval_final = TSK_COR;
            }
        }

        free(idxalloc);
    }


    // get the orphan files
    // load and cache the map if it has not already been done
    if (ntfs->orphan_map == NULL) {
        if (a_fs->inode_walk(a_fs, a_fs->first_inum, a_fs->last_inum,
                TSK_FS_META_FLAG_UNALLOC, ntfs_orphan_act, NULL)) {
            return TSK_ERR;
        }
    }

    // see if there are any entries for this dir
    map = ntfs_orphan_map_get(ntfs, a_addr);
    if (map != NULL) {
        int a;
        TSK_FS_NAME *fs_name;
        TSK_FS_FILE *fs_file_orp = NULL;

        if ((fs_name = tsk_fs_name_alloc(256, 0)) == NULL)
            return TSK_ERR;

        fs_name->flags = TSK_FS_NAME_FLAG_UNALLOC;
        fs_name->type = TSK_FS_NAME_TYPE_UNDEF;

        for (a = 0; a < map->used_cnt; a++) {
            /* Fill in the basics of the fs_name entry 
             * so we can print in the fls formats */
            fs_name->meta_addr = map->addrs[a];

            // lookup the file to get its name (we did not cache that)
            fs_file_orp =
                tsk_fs_file_open_meta(a_fs, fs_file_orp, map->addrs[a]);
            if ((fs_file_orp) && (fs_file_orp->meta)
                && (fs_file_orp->meta->name2)) {
                TSK_FS_META_NAME_LIST *n2 = fs_file_orp->meta->name2;
                while (n2) {
                    if (n2->par_inode == a_addr) {
                        strncpy(fs_name->name, n2->name,
                            fs_name->name_size);
                        tsk_fs_dir_add(fs_dir, fs_name);
                    }
                    n2 = n2->next;
                }
            }
        }
        tsk_fs_name_free(fs_name);
    }

    // if we are listing the root directory, add the Orphan directory entry
    if (a_addr == a_fs->root_inum) {
        TSK_FS_NAME *fs_name;

        if ((fs_name = tsk_fs_name_alloc(256, 0)) == NULL)
            return TSK_ERR;

        if (tsk_fs_dir_make_orphan_dir_name(a_fs, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }

        if (tsk_fs_dir_add(fs_dir, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }
        tsk_fs_name_free(fs_name);
    }


    return retval_final;
}
Пример #22
0
/* Verify that all attributes can be accessed from both get_idx and get_type...
 * @param a_addr The metadata address of the file to analyze
 * @param a_len Expected number of attributes in file.
 * @returns 1 if a test failed
 */
static int
test_get_apis(TSK_FS_INFO * a_fs, TSK_INUM_T a_addr, int a_len)
{
    TSK_FS_FILE *fs_file;
    int retval = 0;

    // open the file
    fs_file = tsk_fs_file_open_meta(a_fs, NULL, a_addr);
    if (!fs_file) {
        fprintf(stderr, "Error opening file %" PRIuINUM " via meta\n",
            a_addr);
        tsk_error_print(stderr);
        return 1;
    }

    int len = tsk_fs_file_attr_getsize(fs_file);
    if (len != a_len) {
        fprintf(stderr,
            "%" PRIuINUM
            " attribute count diff from expected (%d vs %d)\n", a_addr,
            a_len, len);
        tsk_error_print(stderr);
        return 1;
    }

    for (int i = 0; i < len; i++) {

        // get the attribute by index
        const TSK_FS_ATTR *fs_attr = tsk_fs_file_attr_get_idx(fs_file, i);
        if (!fs_attr) {
            fprintf(stderr,
                "Error getting attribute %d from %" PRIuINUM "\n", i,
                a_addr);
            tsk_error_print(stderr);
            return 1;
        }

        // verify we can also get it via type / id
        const TSK_FS_ATTR *fs_attr2 =
            tsk_fs_file_attr_get_type(fs_file, fs_attr->type, fs_attr->id,
            1);
        if (!fs_attr2) {
            fprintf(stderr,
                "Error getting attribute %d-%d from %" PRIuINUM "\n",
                fs_attr->type, fs_attr->id, a_addr);
            tsk_error_print(stderr);
            return 1;
        }

        if ((fs_attr->type != fs_attr2->type)
            || (fs_attr->id != fs_attr2->id)) {
            fprintf(stderr,
                "Attribute from get_type not expected %d-%d vs %d-%d from %"
                PRIuINUM "\n", fs_attr->type, fs_attr->id, fs_attr2->type,
                fs_attr2->id, a_addr);
            tsk_error_print(stderr);
            return 1;
        }

        if (fs_attr != fs_attr2) {
            fprintf(stderr,
                "Attribute from get_type not same addr as original %lu vs %lu from %"
                PRIuINUM "\n", (long) fs_attr, (long) fs_attr2, a_addr);
            tsk_error_print(stderr);
            return 1;
        }

        // verify we also get something via only type
        fs_attr2 = tsk_fs_file_attr_get_type(fs_file, fs_attr->type, 0, 0);
        if (!fs_attr2) {
            fprintf(stderr,
                "Error getting attribute %d (no id) from %" PRIuINUM "\n",
                fs_attr->type, a_addr);
            tsk_error_print(stderr);
            return 1;
        }

        if (fs_attr->type != fs_attr2->type) {
            fprintf(stderr,
                "Attribute from get_type (no id) not expected %d vs %d from %"
                PRIuINUM "\n", fs_attr->type, fs_attr2->type, a_addr);
            tsk_error_print(stderr);
            return 1;
        }

        // Try with a "random" ID: Note this atribute could actually exist...
        fs_attr2 =
            tsk_fs_file_attr_get_type(fs_file, fs_attr->type, 0xfd, 1);
        if (fs_attr2) {
            fprintf(stderr,
                "Got unexpected attribute %d-0xfd (random ID) from %"
                PRIuINUM "\n", fs_attr->type, a_addr);
            tsk_error_print(stderr);
            return 1;
        }
        else if (tsk_error_get_errno() != TSK_ERR_FS_ATTR_NOTFOUND) {
            fprintf(stderr,
                "Unexpected error code %x from getting %d-0xfd (random ID) from %"
                PRIuINUM "\n", (int)tsk_error_get_errno(), fs_attr->type, a_addr);
            tsk_error_print(stderr);
            return 1;
        }
        tsk_error_reset();

        // Try with a "random" type Note this atribute could actually exist...
        fs_attr2 =
            tsk_fs_file_attr_get_type(fs_file,
            (TSK_FS_ATTR_TYPE_ENUM) (fs_attr->type + 37), 0, 0);
        if (fs_attr2) {
            fprintf(stderr,
                "Got unexpected attribute %d-X (random type, no id) from %"
                PRIuINUM "\n", fs_attr->type + 37, a_addr);
            tsk_error_print(stderr);
            return 1;
        }
        else if (tsk_error_get_errno() != TSK_ERR_FS_ATTR_NOTFOUND) {
            fprintf(stderr,
                "Unexpected error code %x from getting %d-X (random type, no id) from %"
                PRIuINUM "\n", (int)tsk_error_get_errno(), fs_attr->type, a_addr);
            tsk_error_print(stderr);
            return 1;
        }
        tsk_error_reset();

    }

    tsk_fs_file_close(fs_file);

    return retval;
}
Пример #23
0
/** \internal
 * Process a directory and load up FS_DIR with the entries. If a pointer to
 * an already allocated FS_DIR struture is given, it will be cleared.  If no existing
 * FS_DIR structure is passed (i.e. NULL), then a new one will be created. If the return
 * value is error or corruption, then the FS_DIR structure could
 * have entries (depending on when the error occured).
 *
 * @param a_fs File system to analyze
 * @param a_fs_dir Pointer to FS_DIR pointer. Can contain an already allocated
 * structure or a new structure.
 * @param a_addr Address of directory to process.
 * @returns error, corruption, ok etc.
 */
TSK_RETVAL_ENUM
ffs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
                  TSK_INUM_T a_addr)
{
    TSK_OFF_T size;
    FFS_INFO *ffs = (FFS_INFO *) a_fs;
    char *dirbuf;
    int nchnk, cidx;
    TSK_FS_LOAD_FILE load_file;
    TSK_FS_DIR *fs_dir;

    /* If we get corruption in one of the blocks, then continue processing.
     * retval_final will change when corruption is detected.  Errors are
     * returned immediately. */
    TSK_RETVAL_ENUM retval_tmp;
    TSK_RETVAL_ENUM retval_final = TSK_OK;


    if (a_addr < a_fs->first_inum || a_addr > a_fs->last_inum) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
        tsk_error_set_errstr("ffs_dir_open_meta: Invalid inode value: %"
                             PRIuINUM, a_addr);
        return TSK_ERR;
    }
    else if (a_fs_dir == NULL) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_ARG);
        tsk_error_set_errstr
        ("ffs_dir_open_meta: NULL fs_attr argument given");
        return TSK_ERR;
    }

    if (tsk_verbose)
        tsk_fprintf(stderr,
                    "ffs_dir_open_meta: Processing directory %" PRIuINUM "\n",
                    a_addr);

    fs_dir = *a_fs_dir;
    if (fs_dir) {
        tsk_fs_dir_reset(fs_dir);
    }
    else {
        if ((*a_fs_dir = fs_dir =
                             tsk_fs_dir_alloc(a_fs, a_addr, 128)) == NULL) {
            return TSK_ERR;
        }
    }

    //  handle the orphan directory if its contents were requested
    if (a_addr == TSK_FS_ORPHANDIR_INUM(a_fs)) {
        return tsk_fs_dir_find_orphans(a_fs, fs_dir);
    }

    if ((fs_dir->fs_file =
                tsk_fs_file_open_meta(a_fs, NULL, a_addr)) == NULL) {
        tsk_error_reset();
        tsk_error_errstr2_concat("- ffs_dir_open_meta");
        return TSK_COR;
    }

    /* make a copy of the directory contents that we can process */
    /* round up cause we want the slack space too */
    size = roundup(fs_dir->fs_file->meta->size, FFS_DIRBLKSIZ);
    if ((dirbuf = tsk_malloc((size_t) size)) == NULL) {
        return TSK_ERR;
    }

    load_file.total = load_file.left = (size_t) size;
    load_file.base = load_file.cur = dirbuf;

    if (tsk_fs_file_walk(fs_dir->fs_file,
                         TSK_FS_FILE_WALK_FLAG_SLACK,
                         tsk_fs_load_file_action, (void *) &load_file)) {
        tsk_error_reset();
        tsk_error_errstr2_concat("- ffs_dir_open_meta");
        free(dirbuf);
        return TSK_COR;
    }

    /* Not all of the directory was copied, so we return */
    if (load_file.left > 0) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_FWALK);
        tsk_error_set_errstr("ffs_dir_open_meta: Error reading directory %"
                             PRIuINUM, a_addr);
        free(dirbuf);
        return TSK_COR;
    }

    /* Directory entries are written in chunks of DIRBLKSIZ
     ** determine how many chunks of this size we have to read to
     ** get a full block
     **
     ** Entries do not cross over the DIRBLKSIZ boundary
     */
    nchnk = (int) (size) / (FFS_DIRBLKSIZ) + 1;

    for (cidx = 0; cidx < nchnk && (int64_t) size > 0; cidx++) {
        int len = (FFS_DIRBLKSIZ < size) ? FFS_DIRBLKSIZ : (int) size;

        retval_tmp =
            ffs_dent_parse_block(ffs, fs_dir,
                                 (fs_dir->fs_file->
                                  meta->flags & TSK_FS_META_FLAG_UNALLOC) ? 1 : 0,
                                 dirbuf + cidx * FFS_DIRBLKSIZ, len);

        if (retval_tmp == TSK_ERR) {
            retval_final = TSK_ERR;
            break;
        }
        else if (retval_tmp == TSK_COR) {
            retval_final = TSK_COR;
        }
        size -= len;
    }
    free(dirbuf);

    // if we are listing the root directory, add the Orphan directory entry
    if (a_addr == a_fs->root_inum) {
        TSK_FS_NAME *fs_name = tsk_fs_name_alloc(256, 0);
        if (fs_name == NULL)
            return TSK_ERR;

        if (tsk_fs_dir_make_orphan_dir_name(a_fs, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }

        if (tsk_fs_dir_add(fs_dir, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }
        tsk_fs_name_free(fs_name);
    }

    return retval_final;
}
Пример #24
0
/** \internal
 * Process a directory and load up FS_DIR with the entries. If a pointer to
 * an already allocated FS_DIR struture is given, it will be cleared.  If no existing
 * FS_DIR structure is passed (i.e. NULL), then a new one will be created. If the return
 * value is error or corruption, then the FS_DIR structure could
 * have entries (depending on when the error occured).
 *
 * @param a_fs File system to analyze
 * @param a_fs_dir Pointer to FS_DIR pointer. Can contain an already allocated
 * structure or a new structure.
 * @param a_addr Address of directory to process.
 * @returns error, corruption, ok etc.
 */
TSK_RETVAL_ENUM
iso9660_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
    TSK_INUM_T a_addr)
{
    TSK_RETVAL_ENUM retval;
    TSK_FS_DIR *fs_dir;
    ssize_t cnt;
    char *buf;
    size_t length;

    if (a_addr < a_fs->first_inum || a_addr > a_fs->last_inum) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
        tsk_error_set_errstr
            ("iso9660_dir_open_meta: Invalid inode value: %" PRIuINUM,
            a_addr);
        return TSK_ERR;
    }
    else if (a_fs_dir == NULL) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_ARG);
        tsk_error_set_errstr
            ("iso9660_dir_open_meta: NULL fs_attr argument given");
        return TSK_ERR;
    }

    if (tsk_verbose)
        tsk_fprintf(stderr,
            "iso9660_dir_open_meta: Processing directory %" PRIuINUM "\n",
            a_addr);

    fs_dir = *a_fs_dir;
    if (fs_dir) {
        tsk_fs_dir_reset(fs_dir);
    }
    else {
        if ((*a_fs_dir = fs_dir =
                tsk_fs_dir_alloc(a_fs, a_addr, 128)) == NULL) {
            return TSK_ERR;
        }
    }

    //  handle the orphan directory if its contents were requested
    if (a_addr == TSK_FS_ORPHANDIR_INUM(a_fs)) {
        return tsk_fs_dir_find_orphans(a_fs, fs_dir);
    }

    fs_dir->fs_file = tsk_fs_file_open_meta(a_fs, NULL, a_addr);
    if (fs_dir->fs_file == NULL) {
        tsk_error_reset();
        tsk_error_set_errno(TSK_ERR_FS_INODE_NUM);
        tsk_error_set_errstr("iso9660_dir_open_meta: %" PRIuINUM
            " is not a valid inode", a_addr);
        return TSK_COR;
    }

    /* read directory extent into memory */
    length = (size_t) fs_dir->fs_file->meta->size;
    if ((buf = tsk_malloc(length)) == NULL)
        return TSK_ERR;

    cnt = tsk_fs_file_read(fs_dir->fs_file, 0, buf, length, 0);
    if (cnt != length) {
        if (cnt >= 0) {
            tsk_error_reset();
            tsk_error_set_errno(TSK_ERR_FS_READ);
        }
        tsk_error_set_errstr2("iso9660_dir_open_meta");
        return TSK_ERR;
    }

    // process the contents
    retval = iso9660_proc_dir(a_fs, fs_dir, buf, length, a_addr,
        fs_dir->fs_file->meta->attr->head->nrd.run->addr);

    // if we are listing the root directory, add the Orphan directory entry
    if (a_addr == a_fs->root_inum) {
        TSK_FS_NAME *fs_name = tsk_fs_name_alloc(256, 0);
        if (fs_name == NULL)
            return TSK_ERR;

        if (tsk_fs_dir_make_orphan_dir_name(a_fs, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }

        if (tsk_fs_dir_add(fs_dir, fs_name)) {
            tsk_fs_name_free(fs_name);
            return TSK_ERR;
        }
        tsk_fs_name_free(fs_name);
    }

    return retval;
}