Coverage Report

Created: 2024-04-23 06:05

/src/sleuthkit/tsk/fs/fls_lib.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
** fls
3
** The Sleuth Kit
4
**
5
** Given an image and directory inode, display the file names and
6
** directories that exist (both active and deleted)
7
**
8
** Brian Carrier [carrier <at> sleuthkit [dot] org]
9
** Copyright (c) 2006-2011 Brian Carrier, Basis Technology.  All Rights reserved
10
** Copyright (c) 2003-2005 Brian Carier.  All rights reserved
11
**
12
** TASK
13
** Copyright (c) 2002 @stake Inc.  All rights reserved
14
**
15
** TCTUTILs
16
** Copyright (c) 2001 Brian Carrier.  All rights reserved
17
**
18
**
19
** This software is distributed under the Common Public License 1.0
20
**
21
*/
22
23
/** \file fls_lib.c
24
 * Contains the library code associated with the TSK fls tool to list files in a directory.
25
 */
26
27
#include "tsk_fs_i.h"
28
29
/** \internal
30
* Structure to store data for callbacks.
31
*/
32
typedef struct {
33
    /* Time skew of the system in seconds */
34
    int32_t sec_skew;
35
36
    /*directory prefix for printing mactime output */
37
    char *macpre;
38
    int flags;
39
} FLS_DATA;
40
41
42
43
44
/* this is a wrapper type function that takes care of the runtime
45
 * flags
46
 *
47
 * fs_attr should be set to NULL for all non-NTFS file systems
48
 */
49
static void
50
printit(TSK_FS_FILE * fs_file, const char *a_path,
51
    const TSK_FS_ATTR * fs_attr, const FLS_DATA * fls_data)
52
0
{
53
0
    TSK_FS_HASH_RESULTS hash_results;
54
55
0
    if ((!(fls_data->flags & TSK_FS_FLS_FULL)) && (a_path)) {
56
0
        uint8_t printed = 0;
57
0
        unsigned int i;
58
59
        // lazy way to find out how many dirs there could be
60
0
        for (i = 0; a_path[i] != '\0'; i++) {
61
0
            if ((a_path[i] == '/') && (i != 0)) {
62
0
                tsk_fprintf(stdout, "+");
63
0
                printed = 1;
64
0
            }
65
0
        }
66
0
        if (printed)
67
0
            tsk_fprintf(stdout, " ");
68
0
    }
69
70
71
0
    if (fls_data->flags & TSK_FS_FLS_MAC) {
72
0
        if (fls_data->flags & TSK_FS_FLS_HASH) {
73
0
            if(0 == tsk_fs_file_hash_calc(fs_file, &hash_results,
74
0
                TSK_BASE_HASH_MD5)){
75
0
        tsk_fs_name_print_mac_md5(stdout, fs_file, a_path, fs_attr,
76
0
          fls_data->macpre, fls_data->sec_skew,
77
0
          hash_results.md5_digest);
78
0
                                tsk_printf("\n");
79
0
      }
80
0
      else {
81
0
              unsigned char null_buf[16];
82
        // If the hash calculation had errors, pass in a buffer of nulls
83
0
        memset(null_buf, 0, 16);
84
0
        tsk_fs_name_print_mac_md5(stdout, fs_file, a_path, fs_attr,
85
0
          fls_data->macpre, fls_data->sec_skew,
86
0
          null_buf);
87
0
                                tsk_printf("\n");
88
0
      }
89
0
        }
90
0
        else {
91
0
            tsk_fs_name_print_mac(stdout, fs_file, a_path,
92
0
                fs_attr, fls_data->macpre, fls_data->sec_skew);
93
0
            tsk_printf("\n");
94
0
        }
95
0
    }
96
0
    else if (fls_data->flags & TSK_FS_FLS_LONG) {
97
0
        tsk_fs_name_print_long(stdout, fs_file, a_path, fs_file->fs_info,
98
0
            fs_attr, TSK_FS_FLS_FULL & fls_data->flags ? 1 : 0,
99
0
            fls_data->sec_skew);
100
0
        tsk_printf("\n");
101
0
    }
102
0
    else {
103
0
        tsk_fs_name_print(stdout, fs_file, a_path, fs_file->fs_info,
104
0
            fs_attr, TSK_FS_FLS_FULL & fls_data->flags ? 1 : 0);
105
0
        tsk_printf("\n");
106
0
    }
107
0
}
108
109
110
/*
111
 * call back action function for dent_walk
112
 */
113
static TSK_WALK_RET_ENUM
114
print_dent_act(TSK_FS_FILE * fs_file, const char *a_path, void *ptr)
115
795
{
116
795
    FLS_DATA *fls_data = (FLS_DATA *) ptr;
117
118
    /* only print dirs if TSK_FS_FLS_DIR is set and only print everything
119
     ** else if TSK_FS_FLS_FILE is set (or we aren't sure what it is)
120
     */
121
795
    if (((fls_data->flags & TSK_FS_FLS_DIR) &&
122
795
            ((fs_file->meta) &&
123
0
                (TSK_FS_IS_DIR_META(fs_file->meta->type))))
124
795
        || ((fls_data->flags & TSK_FS_FLS_FILE) && (((fs_file->meta)
125
0
                    && ( ! TSK_FS_IS_DIR_META(fs_file->meta->type)))
126
0
                || (!fs_file->meta)))) {
127
128
129
        /* Make a special case for NTFS so we can identify all of the
130
         * alternate data streams!
131
         */
132
0
        if ((TSK_FS_TYPE_ISNTFS(fs_file->fs_info->ftype))
133
0
            && (fs_file->meta)) {
134
0
            uint8_t printed = 0;
135
0
            int i, cnt;
136
137
            // cycle through the attributes
138
0
            cnt = tsk_fs_file_attr_getsize(fs_file);
139
0
            for (i = 0; i < cnt; i++) {
140
0
                const TSK_FS_ATTR *fs_attr =
141
0
                    tsk_fs_file_attr_get_idx(fs_file, i);
142
0
                if (!fs_attr)
143
0
                    continue;
144
145
0
                if (fs_attr->type == TSK_FS_ATTR_TYPE_NTFS_DATA) {
146
0
                    printed = 1;
147
148
0
                    if (fs_file->meta->type == TSK_FS_META_TYPE_DIR) {
149
150
                        /* we don't want to print the ..:blah stream if
151
                         * the -a flag was not given
152
                         */
153
0
                        if ((fs_file->name->name[0] == '.')
154
0
                            && (fs_file->name->name[1])
155
0
                            && (fs_file->name->name[2] == '\0')
156
0
                            && ((fls_data->flags & TSK_FS_FLS_DOT) == 0)) {
157
0
                            continue;
158
0
                        }
159
0
                    }
160
161
0
                    printit(fs_file, a_path, fs_attr, fls_data);
162
0
                }
163
0
                else if (fs_attr->type == TSK_FS_ATTR_TYPE_NTFS_IDXROOT) {
164
0
                    printed = 1;
165
166
                    /* If it is . or .. only print it if the flags say so,
167
                     * we continue with other streams though in case the
168
                     * directory has a data stream
169
                     */
170
0
                    if (!((TSK_FS_ISDOT(fs_file->name->name)) &&
171
0
                            ((fls_data->flags & TSK_FS_FLS_DOT) == 0)))
172
0
                        printit(fs_file, a_path, fs_attr, fls_data);
173
0
                }
174
                /* Print the FILE_NAME times if this is the same attribute
175
                 * that we collected the times from. */
176
0
                else if ((fs_attr->type == TSK_FS_ATTR_TYPE_NTFS_FNAME) &&
177
0
                    (fs_attr->id == fs_file->meta->time2.ntfs.fn_id) &&
178
0
                    (fls_data->flags & TSK_FS_FLS_MAC)) {
179
                    /* If it is . or .. only print it if the flags say so,
180
                     * we continue with other streams though in case the
181
                     * directory has a data stream
182
                     */
183
0
                    if (!((TSK_FS_ISDOT(fs_file->name->name)) &&
184
0
                            ((fls_data->flags & TSK_FS_FLS_DOT) == 0)))
185
0
                        printit(fs_file, a_path, fs_attr, fls_data);
186
0
                }
187
0
            }
188
189
            /* A user reported that an allocated file had the standard
190
             * attributes, but no $Data.  We should print something */
191
0
            if (printed == 0) {
192
0
                printit(fs_file, a_path, NULL, fls_data);
193
0
            }
194
195
0
        }
196
0
        else {
197
            /* skip it if it is . or .. and we don't want them */
198
0
            if (!((TSK_FS_ISDOT(fs_file->name->name))
199
0
                    && ((fls_data->flags & TSK_FS_FLS_DOT) == 0)))
200
0
                printit(fs_file, a_path, NULL, fls_data);
201
0
        }
202
0
    }
203
795
    return TSK_WALK_CONT;
204
795
}
205
206
207
/* Returns 0 on success and 1 on error */
208
uint8_t
209
tsk_fs_fls(TSK_FS_INFO * fs, TSK_FS_FLS_FLAG_ENUM lclflags,
210
    TSK_INUM_T inode, TSK_FS_DIR_WALK_FLAG_ENUM flags, TSK_TCHAR * tpre,
211
    int32_t skew)
212
3.37k
{
213
3.37k
    FLS_DATA data;
214
215
3.37k
    data.flags = lclflags;
216
3.37k
    data.sec_skew = skew;
217
218
#ifdef TSK_WIN32
219
    {
220
        UTF8 *ptr8;
221
        UTF16 *ptr16;
222
        int retval;
223
224
        if ((tpre != NULL) && (TSTRLEN(tpre) > 0)) {
225
            size_t clen = TSTRLEN(tpre) * 4;
226
            data.macpre = (char *) tsk_malloc(clen);
227
            if (data.macpre == NULL) {
228
                return 1;
229
            }
230
            ptr8 = (UTF8 *) data.macpre;
231
            ptr16 = (UTF16 *) tpre;
232
233
            retval =
234
                tsk_UTF16toUTF8_lclorder((const UTF16 **) &ptr16, (UTF16 *)
235
                & ptr16[TSTRLEN(tpre) + 1], &ptr8,
236
                (UTF8 *) ((uintptr_t) ptr8 + clen), TSKlenientConversion);
237
            if (retval != TSKconversionOK) {
238
                tsk_error_reset();
239
                tsk_error_set_errno(TSK_ERR_FS_UNICODE);
240
                tsk_error_set_errstr
241
                    ("Error converting fls mactime pre-text to UTF-8 %d\n",
242
                    retval);
243
                return 1;
244
            }
245
        }
246
        else {
247
            data.macpre = (char *) tsk_malloc(1);
248
            if (data.macpre == NULL) {
249
                return 1;
250
            }
251
            data.macpre[0] = '\0';
252
        }
253
254
        retval = tsk_fs_dir_walk(fs, inode, flags, print_dent_act, &data);
255
256
        free(data.macpre);
257
        data.macpre = NULL;
258
        return retval;
259
    }
260
#else
261
3.37k
    data.macpre = tpre;
262
3.37k
    return tsk_fs_dir_walk(fs, inode, flags, print_dent_act, &data);
263
3.37k
#endif
264
3.37k
}