diff --git a/tsk/fs/tsk_xfs.h b/tsk/fs/tsk_xfs.h index b696f1db9f5cf6e00c8bc21c55a8ea1add3d79a1..ab5ac0acd58d2cc003d319b440a75f91cf8fa3fa 100644 --- a/tsk/fs/tsk_xfs.h +++ b/tsk/fs/tsk_xfs.h @@ -269,17 +269,37 @@ typedef struct xfs_dir2_sf { xfs_dir2_sf_entry_t list[1]; } xfs_dir2_sf_t; +/* + * Attribute flags + * NOTE: the INCOMPLETE bit must not collide with the flags bits specified + * on the system call, they are "or"ed together for various operations. + */ +#define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */ +#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */ +#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */ +#define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */ +#define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT) +#define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT) +#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT) +#define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT) + +#define ATTR_SF_HDR_SIZE 3 +struct xfs_attr_sf_hdr { + uint16_t totsize; + uint8_t count; +}; +/* size of attribute entry without name+value */ +#define ATTR_SF_ENTRY_SIZE 3 +struct xfs_attr_sf_entry { + uint8_t namelen; + uint8_t valuelen; + uint8_t flags; + uint8_t nameval[1]; +}; + typedef struct xfs_attr_shortform { - struct xfs_attr_sf_hdr { - uint16_t totsize; - uint8_t count; - } hdr; - struct xfs_attr_sf_entry { - uint8_t namelen; - uint8_t valuelen; - uint8_t flags; - uint8_t nameval[1]; - } list[1]; + xfs_attr_sf_hdr hdr; + xfs_attr_sf_entry list[1]; } xfs_attr_shortform_t; typedef struct xfs_dinode diff --git a/tsk/fs/xfs.cpp b/tsk/fs/xfs.cpp index 32400a2057075f4bfde1dd3921b6958865b8a2da..4107c4a6f3fe7be52bf58485c5c268f014d7239b 100644 --- a/tsk/fs/xfs.cpp +++ b/tsk/fs/xfs.cpp @@ -1056,7 +1056,7 @@ xfs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr) { free(agf); free(agfl); - + if (inode_flag == TSK_FS_META_FLAG_ALLOC) return (TSK_FS_BLOCK_FLAG_ENUM) (TSK_FS_BLOCK_FLAG_META | TSK_FS_BLOCK_FLAG_ALLOC); else if (inode_flag == TSK_FS_META_FLAG_UNALLOC) @@ -1574,6 +1574,95 @@ print_addr_act(TSK_FS_FILE * fs_file, TSK_OFF_T a_off, TSK_DADDR_T addr, return TSK_WALK_CONT; } + +/** + * Parse extended attributes + * + * @param a_fs File system file is located in + * @param a_dino_buf Inode buffer + * @param a_hFile File handle to print text to + * + * @returns 1 on error and 0 on success + */ +static uint8_t +parse_extended_attrs(XFSFS_INFO *a_xfsfs, xfs_dinode_t *a_dino_buf, FILE *a_hFile) +{ + if (a_dino_buf->di_core.di_forkoff == 0) + { + return 0; + } + + tsk_fprintf(a_hFile, "\nExtended Attributes: \n"); + + void* in_base = (void*) &a_dino_buf->di_core; + uint64_t in_offset = a_xfsfs->inode_size - + XFS_DFORK_ASIZE(&a_dino_buf->di_core, a_xfsfs); + + if (a_dino_buf->di_core.di_aformat == XFS_DINODE_FMT_LOCAL) + { + uint16_t attr_fork_size = XFS_DFORK_ASIZE(&a_dino_buf->di_core, a_xfsfs); + + xfs_attr_sf_hdr *attr_hdr = (xfs_attr_sf_hdr*) (in_base + in_offset); + uint16_t totsize = tsk_getu16(TSK_BIG_ENDIAN, &attr_hdr->totsize); + + if (attr_fork_size < ATTR_SF_HDR_SIZE || + attr_fork_size - ATTR_SF_HDR_SIZE < totsize) + { + tsk_fprintf(a_hFile, "incorrect attribute header"); + return 1; + } + + in_offset = roundup(in_offset + ATTR_SF_HDR_SIZE, sizeof(uint64_t)); + xfs_attr_sf_entry *sf_entry = (xfs_attr_sf_entry*) (in_base + in_offset); + uint64_t limit = a_xfsfs->inode_size; + + // we intentionally attempt to go beyond entry_num and not + // beyond inode end if more (hidden) attributes are allocated + for (uint8_t entry_num = 0; in_offset < limit; entry_num++) + { + uint64_t sf_entry_size = ATTR_SF_ENTRY_SIZE + sf_entry->namelen + + sf_entry->valuelen; + if (sf_entry_size >= limit) + { + tsk_fprintf(a_hFile, "sf_entry goes past the inode literal area"); + return 1; + } + + if(sf_entry->flags & XFS_ATTR_ROOT) + { + tsk_fprintf(a_hFile, "root,"); + } + else + { + tsk_fprintf(a_hFile, "user,"); + } + if(sf_entry->flags & XFS_ATTR_SECURE) + { + tsk_fprintf(a_hFile, "secure,"); + } + if(sf_entry->flags & XFS_ATTR_LOCAL) + { + tsk_fprintf(a_hFile, "local,"); + } + if(sf_entry->flags & XFS_ATTR_INCOMPLETE) + { + tsk_fprintf(a_hFile, "incomplete,"); + } + + char name[sf_entry->namelen + 1] = {0}; + memcpy(&name, &sf_entry->nameval, sf_entry->namelen); + char val[sf_entry->valuelen + 1] = {0}; + memcpy(&val, &sf_entry->nameval + sf_entry->namelen, + sf_entry->valuelen); + + tsk_fprintf(a_hFile, ".%s=%s\n", &name, &val); + + in_offset = roundup(in_offset + sf_entry_size, sizeof(uint64_t)); + sf_entry = (xfs_attr_sf_entry*) (in_base + in_offset); + } + } +} + /** * Print details on a specific file to a file handle. * @@ -1678,19 +1767,7 @@ xfs_istat(TSK_FS_INFO * fs, TSK_FS_ISTAT_FLAG_ENUM istat_flags, FILE * hFile, TS tsk_fprintf(hFile, "size: %" PRIuOFF "\n", fs_meta->size); tsk_fprintf(hFile, "num of links: %d\n", fs_meta->nlink); - // Extended attributes - /* - if (dino_buf->di_core.di_forkoff != 0) - { - xfs_dinode_core_t* _di_core = &dino_buf->di_core; - void attr_offset = XFS_DFORK_PTR(_di_core, XFS_ATTR_FORK); - tsk_fprintf(hFile, "attr_offset: 0x %x\n", attr_offset); - - // TODO: parse extended attributes and test - // 14.4 Attribute Fork of - // http://ftp.ntu.edu.tw/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf - } - */ + parse_extended_attrs(xfsfs, dino_buf, hFile); if (sec_skew != 0) { tsk_fprintf(hFile, "\nAdjusted Inode Times:\n"); @@ -1816,7 +1893,7 @@ parse_dir_block( char *dirbuf = NULL; XFSFS_INFO *xfs = (XFSFS_INFO *) a_fs; xfs_sb_t *sb = xfs->fs; - + uint8_t ftype_size = (sb->sb_features2 & XFS_SB_VERSION2_FTYPE) ? sizeof(uint8_t) : 0; @@ -2167,7 +2244,7 @@ visit_btree_node( free(node_recs); free(node_ptrs); - + return TSK_OK; } else @@ -2310,8 +2387,8 @@ xfs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir, * sf_entry goes after xfs_dir2_sf_hdr, which is defined as: * * typedef struct xfs_dir2_sf_hdr { - * __uint8_t count; - * __uint8_t i8count; + * uint8_t count; + * uint8_t i8count; * xfs_dir2_inou_t parent; <-- uint32_t (uint64_t if i8count > 0) * } xfs_dir2_sf_hdr_t; */ @@ -2326,10 +2403,10 @@ xfs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir, { /* * typedef struct { - * __uint8_t namelen; + * uint8_t namelen; * xfs_dir2_sf_off_t offset; - * __uint8_t name[1]; - * __uint8_t ftype; + * uint8_t name[1]; + * uint8_t ftype; * xfs_dir2_inou_t inumber; * } xfs_dir2_sf_entry_t; */ @@ -2368,7 +2445,7 @@ xfs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir, } ftype = dino_buf->di_core.di_mode & XFS_IN_FMT; - + free(dino_buf); } @@ -2780,7 +2857,7 @@ TSK_FS_INFO * } sb = xfsfs->fs; - + sb->sb_magicnum = tsk_getu32(TSK_BIG_ENDIAN, &sb->sb_magicnum); sb->sb_blocksize = tsk_getu32(TSK_BIG_ENDIAN, &sb->sb_blocksize); sb->sb_dblocks = tsk_getu64(TSK_BIG_ENDIAN, &sb->sb_dblocks);