1 /*
2 ** fatxxfs
3 ** The Sleuth Kit
4 **
5 ** Content and meta data layer support for the FATXX file system
6 **
7 ** Brian Carrier [carrier <at> sleuthkit [dot] org]
8 ** Copyright (c) 2006-2013 Brian Carrier, Basis Technology. All Rights reserved
9 ** Copyright (c) 2003-2005 Brian Carrier. All rights reserved
10 **
11 ** TASK
12 ** Copyright (c) 2002 Brian Carrier, @stake Inc. All rights reserved
13 **
14 **
15 ** This software is distributed under the Common Public License 1.0
16 **
17 ** Unicode added with support from I.D.E.A.L. Technology Corp (Aug '05)
18 **
19 */
20
21 /**
22 * \file fatxxfs.c
23 * Contains the internal TSK FATXX (FAT12, FAT16, FAT32) file system code to
24 * handle basic file system processing for opening file system, processing
25 * sectors, and directory entries.
26 */
27
28 #include "tsk_fatxxfs.h"
29 #include <assert.h>
30
31 /*
32 * Identify if the dentry is a valid 8.3 name
33 *
34 * returns 1 if it is, 0 if it does not
35 */
36 static uint8_t
is_83_name(FATXXFS_DENTRY * de)37 is_83_name(FATXXFS_DENTRY * de)
38 {
39 if (!de)
40 return 0;
41
42 /* The IS_NAME macro will fail if the value is 0x05, which is only
43 * valid in name[0], similarly with '.' */
44 if ((de->name[0] != FATXXFS_SLOT_E5) && (de->name[0] != '.') &&
45 (FATXXFS_IS_83_NAME(de->name[0]) == 0)) {
46 if (tsk_verbose)
47 fprintf(stderr, "fatfs_is_83_name: name[0] is invalid\n");
48 return 0;
49 }
50
51 // the name cannot start with 0x20
52 else if (de->name[0] == 0x20) {
53 if (tsk_verbose)
54 fprintf(stderr, "fatfs_is_83_name: name[0] has 0x20\n");
55 return 0;
56 }
57
58 /* the second name field can only be . if the first one is a . */
59 if (de->name[1] == '.') {
60 if (de->name[0] != '.') {
61 if (tsk_verbose)
62 fprintf(stderr, "fatfs_is_83_name: name[1] is .\n");
63 return 0;
64 }
65 }
66 else if (FATXXFS_IS_83_NAME(de->name[1]) == 0) {
67 if (tsk_verbose)
68 fprintf(stderr, "fatfs_is_83_name: name[1] is invalid\n");
69 return 0;
70 }
71
72 if (FATXXFS_IS_83_NAME(de->name[2]) == 0) {
73 if (tsk_verbose)
74 fprintf(stderr, "fatfs_is_83_name: name[2] is invalid\n");
75 return 0;
76 }
77 else if (FATXXFS_IS_83_NAME(de->name[3]) == 0) {
78 if (tsk_verbose)
79 fprintf(stderr, "fatfs_is_83_name: name[3] is invalid\n");
80 return 0;
81 }
82 else if (FATXXFS_IS_83_NAME(de->name[4]) == 0) {
83 if (tsk_verbose)
84 fprintf(stderr, "fatfs_is_83_name: name[4] is invalid\n");
85 return 0;
86 }
87 else if (FATXXFS_IS_83_NAME(de->name[5]) == 0) {
88 if (tsk_verbose)
89 fprintf(stderr, "fatfs_is_83_name: name[5] is invalid\n");
90 return 0;
91 }
92 else if (FATXXFS_IS_83_NAME(de->name[6]) == 0) {
93 if (tsk_verbose)
94 fprintf(stderr, "fatfs_is_83_name: name[6] is invalid\n");
95 return 0;
96 }
97 else if (FATXXFS_IS_83_NAME(de->name[7]) == 0) {
98 if (tsk_verbose)
99 fprintf(stderr, "fatfs_is_83_name: name[7] is invalid\n");
100 return 0;
101 }
102 else if (FATXXFS_IS_83_NAME(de->ext[0]) == 0) {
103 if (tsk_verbose)
104 fprintf(stderr, "fatfs_is_83_name: ext[0] is invalid\n");
105 return 0;
106 }
107 else if (FATXXFS_IS_83_NAME(de->ext[1]) == 0) {
108 if (tsk_verbose)
109 fprintf(stderr, "fatfs_is_83_name: ext[1] is invalid\n");
110 return 0;
111 }
112 else if (FATXXFS_IS_83_NAME(de->ext[2]) == 0) {
113 if (tsk_verbose)
114 fprintf(stderr, "fatfs_is_83_name: ext[2] is invalid\n");
115 return 0;
116 }
117
118 /* Ensure that if we get a "space", that the rest of the
119 * name is spaces. This is not in the spec, but is how
120 * windows operates and serves as a good check to remove
121 * false positives. We do not do this check for the
122 * volume label though. */
123 if ((de->attrib & FATFS_ATTR_VOLUME) != FATFS_ATTR_VOLUME) {
124 if (((de->name[1] == 0x20) && (de->name[2] != 0x20)) ||
125 ((de->name[2] == 0x20) && (de->name[3] != 0x20)) ||
126 ((de->name[3] == 0x20) && (de->name[4] != 0x20)) ||
127 ((de->name[4] == 0x20) && (de->name[5] != 0x20)) ||
128 ((de->name[5] == 0x20) && (de->name[6] != 0x20)) ||
129 ((de->name[6] == 0x20) && (de->name[7] != 0x20)) ||
130 ((de->ext[1] == 0x20) && (de->ext[2] != 0x20))) {
131 if (tsk_verbose)
132 fprintf(stderr,
133 "fatfs_is_83_name: space before non-space\n");
134 return 0;
135 }
136 }
137
138 return 1;
139 }
140
141 /**
142 * \internal
143 * Determine whether a buffer likely contains a directory entry.
144 * For the most reliable results, request the in-depth test.
145 *
146 * @param [in] a_fatfs Source file system for the directory entry.
147 * @param [in] a_dentry Buffer that may contain a directory entry.
148 * @param [in] a_cluster_is_alloc The allocation status, possibly unknown, of the
149 * cluster from which the buffer was filled.
150 * @param [in] a_do_basic_tests_only Whether to do basic or in-depth testing.
151 * @return 1 if the buffer likely contains a directory entry, 0 otherwise
152 */
153 uint8_t
fatxxfs_is_dentry(FATFS_INFO * a_fatfs,FATFS_DENTRY * a_dentry,FATFS_DATA_UNIT_ALLOC_STATUS_ENUM a_cluster_is_alloc,uint8_t a_do_basic_tests_only)154 fatxxfs_is_dentry(FATFS_INFO *a_fatfs, FATFS_DENTRY *a_dentry, FATFS_DATA_UNIT_ALLOC_STATUS_ENUM a_cluster_is_alloc, uint8_t a_do_basic_tests_only)
155 {
156 const char *func_name = "fatxxfs_is_dentry";
157 TSK_FS_INFO *fs = (TSK_FS_INFO *) & a_fatfs->fs_info;
158 FATXXFS_DENTRY *dentry = (FATXXFS_DENTRY*)a_dentry;
159
160 if (!a_dentry)
161 return 0;
162
163 /* LFN have their own checks, which are pretty weak since most
164 * fields are UTF16 */
165 if ((dentry->attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) {
166 FATXXFS_DENTRY_LFN *de_lfn = (FATXXFS_DENTRY_LFN*) dentry;
167
168 if ((de_lfn->seq > (FATXXFS_LFN_SEQ_FIRST | 0x0f))
169 && (de_lfn->seq != FATXXFS_SLOT_DELETED)) {
170 if (tsk_verbose)
171 fprintf(stderr, "%s: LFN seq\n", func_name);
172 return 0;
173 }
174
175 return 1;
176 }
177 else {
178 // the basic test is only for the 'essential data'.
179 if (a_do_basic_tests_only == 0) {
180 if (dentry->lowercase & ~(FATXXFS_CASE_LOWER_ALL)) {
181 if (tsk_verbose)
182 fprintf(stderr, "%s: lower case all\n", func_name);
183 return 0;
184 }
185 else if (dentry->attrib & ~(FATFS_ATTR_ALL)) {
186 if (tsk_verbose)
187 fprintf(stderr, "%s: attribute all\n", func_name);
188 return 0;
189 }
190
191 // verify we do not have too many flags set
192 if (dentry->attrib & FATFS_ATTR_VOLUME) {
193 if ((dentry->attrib & FATFS_ATTR_DIRECTORY) ||
194 (dentry->attrib & FATFS_ATTR_READONLY) ||
195 (dentry->attrib & FATFS_ATTR_ARCHIVE)) {
196 if (tsk_verbose)
197 fprintf(stderr,
198 "%s: Vol and Dir/RO/Arch\n", func_name);
199 return 0;
200 }
201 }
202
203 /* The ctime, cdate, and adate fields are optional and
204 * therefore 0 is a valid value
205 * We have had scenarios where ISDATE and ISTIME return true,
206 * but the unix2dos fail during the conversion. This has been
207 * useful to detect corrupt entries, so we do both.
208 */
209 if ((tsk_getu16(fs->endian, dentry->ctime) != 0) &&
210 (FATFS_ISTIME(tsk_getu16(fs->endian, dentry->ctime)) == 0)) {
211 if (tsk_verbose)
212 fprintf(stderr, "%s: ctime\n", func_name);
213 return 0;
214 }
215 else if ((tsk_getu16(fs->endian, dentry->wtime) != 0) &&
216 (FATFS_ISTIME(tsk_getu16(fs->endian, dentry->wtime)) == 0)) {
217 if (tsk_verbose)
218 fprintf(stderr, "%s: wtime\n", func_name);
219 return 0;
220 }
221 else if ((tsk_getu16(fs->endian, dentry->cdate) != 0) &&
222 ((FATFS_ISDATE(tsk_getu16(fs->endian, dentry->cdate)) == 0) ||
223 (fatfs_dos_2_unix_time(tsk_getu16(fs->endian, dentry->cdate),
224 tsk_getu16(fs->endian, dentry->ctime),
225 dentry->ctimeten) == 0))) {
226 if (tsk_verbose)
227 fprintf(stderr, "%s: cdate\n", func_name);
228 return 0;
229 }
230 else if (dentry->ctimeten > 200) {
231 if (tsk_verbose)
232 fprintf(stderr, "%s: ctimeten\n", func_name);
233 return 0;
234 }
235 else if ((tsk_getu16(fs->endian, dentry->adate) != 0) &&
236 ((FATFS_ISDATE(tsk_getu16(fs->endian, dentry->adate)) == 0) ||
237 (fatfs_dos_2_unix_time(tsk_getu16(fs->endian, dentry->adate),
238 0, 0) == 0))) {
239 if (tsk_verbose)
240 fprintf(stderr, "%s: adate\n", func_name);
241 return 0;
242 }
243 else if ((tsk_getu16(fs->endian, dentry->wdate) != 0) &&
244 ((FATFS_ISDATE(tsk_getu16(fs->endian, dentry->wdate)) == 0) ||
245 (fatfs_dos_2_unix_time(tsk_getu16(fs->endian, dentry->wdate),
246 tsk_getu16(fs->endian, dentry->wtime), 0) == 0))) {
247 if (tsk_verbose)
248 fprintf(stderr, "%s: wdate\n", func_name);
249 return 0;
250 }
251 }
252
253 /* verify the starting cluster is small enough */
254 if ((FATXXFS_DENTRY_CLUST(fs, dentry) > (a_fatfs->lastclust)) &&
255 (FATFS_ISEOF(FATXXFS_DENTRY_CLUST(fs, dentry), a_fatfs->mask) == 0)) {
256 if (tsk_verbose)
257 fprintf(stderr, "%s: start cluster\n", func_name);
258 return 0;
259 }
260
261 /* Verify the file size is smaller than the data area */
262 else if (tsk_getu32(fs->endian, dentry->size) >
263 ((a_fatfs->clustcnt * a_fatfs->csize) << a_fatfs->ssize_sh)) {
264 if (tsk_verbose)
265 fprintf(stderr, "%s: size\n", func_name);
266 return 0;
267 }
268
269 else if ((tsk_getu32(fs->endian, dentry->size) > 0)
270 && (FATXXFS_DENTRY_CLUST(fs, dentry) == 0)) {
271 if (tsk_verbose)
272 fprintf(stderr,
273 "%s: non-zero size and NULL starting cluster\n", func_name);
274 return 0;
275 }
276
277 else if((a_fatfs->subtype == TSK_FATFS_SUBTYPE_SPEC) && (is_83_name(dentry) == 0))
278 return 0;
279
280 // basic sanity check on values
281 else if ((tsk_getu16(fs->endian, dentry->ctime) == 0)
282 && (tsk_getu16(fs->endian, dentry->wtime) == 0)
283 && (tsk_getu16(fs->endian, dentry->cdate) == 0)
284 && (tsk_getu16(fs->endian, dentry->adate) == 0)
285 && (tsk_getu16(fs->endian, dentry->wdate) == 0)
286 && (FATXXFS_DENTRY_CLUST(fs, dentry) == 0)
287 && (tsk_getu32(fs->endian, dentry->size) == 0)) {
288 if (tsk_verbose)
289 fprintf(stderr,
290 "%s: nearly all values zero\n", func_name);
291 return 0;
292 }
293
294 return 1;
295 }
296 }
297
298 /*
299 * convert the attribute list in FAT to a UNIX mode
300 */
301 static TSK_FS_META_TYPE_ENUM
attr2type(uint16_t attr)302 attr2type(uint16_t attr)
303 {
304 if (attr & FATFS_ATTR_DIRECTORY)
305 return TSK_FS_META_TYPE_DIR;
306 else
307 return TSK_FS_META_TYPE_REG;
308 }
309
310 static int
attr2mode(uint16_t attr)311 attr2mode(uint16_t attr)
312 {
313 int mode;
314
315 /* every file is executable */
316 mode =
317 (TSK_FS_META_MODE_IXUSR | TSK_FS_META_MODE_IXGRP |
318 TSK_FS_META_MODE_IXOTH);
319
320 if ((attr & FATFS_ATTR_READONLY) == 0)
321 mode |=
322 (TSK_FS_META_MODE_IRUSR | TSK_FS_META_MODE_IRGRP |
323 TSK_FS_META_MODE_IROTH);
324
325 if ((attr & FATFS_ATTR_HIDDEN) == 0)
326 mode |=
327 (TSK_FS_META_MODE_IWUSR | TSK_FS_META_MODE_IWGRP |
328 TSK_FS_META_MODE_IWOTH);
329
330 return mode;
331 }
332
333 TSK_RETVAL_ENUM
fatxxfs_dinode_copy(FATFS_INFO * a_fatfs,TSK_INUM_T a_inum,FATFS_DENTRY * a_dentry,uint8_t a_cluster_is_alloc,TSK_FS_FILE * a_fs_file)334 fatxxfs_dinode_copy(FATFS_INFO *a_fatfs, TSK_INUM_T a_inum,
335 FATFS_DENTRY *a_dentry, uint8_t a_cluster_is_alloc, TSK_FS_FILE *a_fs_file)
336 {
337 const char *func_name = "fatxxfs_dinode_copy";
338 int i;
339 TSK_FS_INFO *fs = (TSK_FS_INFO *) & a_fatfs->fs_info;
340 TSK_FS_META *fs_meta = a_fs_file->meta;
341 FATXXFS_DENTRY *dentry = (FATXXFS_DENTRY*)a_dentry;
342 TSK_DADDR_T *addr_ptr;
343 uint32_t flags = 0;
344
345 if (fs_meta->content_len < FATFS_FILE_CONTENT_LEN) {
346 if ((fs_meta =
347 tsk_fs_meta_realloc(fs_meta,
348 FATFS_FILE_CONTENT_LEN)) == NULL) {
349 return TSK_ERR;
350 }
351 }
352
353 fs_meta->attr_state = TSK_FS_META_ATTR_EMPTY;
354 if (fs_meta->attr) {
355 tsk_fs_attrlist_markunused(fs_meta->attr);
356 }
357
358 fs_meta->mode = (TSK_FS_META_MODE_ENUM)attr2mode(dentry->attrib);
359 fs_meta->type = attr2type(dentry->attrib);
360
361 fs_meta->addr = a_inum;
362
363 if (a_cluster_is_alloc) {
364 if(FATXXFS_IS_DELETED(dentry->name, a_fatfs)){
365 flags = TSK_FS_META_FLAG_UNALLOC;
366 }
367 else{
368 flags = TSK_FS_META_FLAG_ALLOC;
369 }
370 }
371 else {
372 flags = TSK_FS_META_FLAG_UNALLOC;
373 }
374
375 flags |= (dentry->name[0] == FATXXFS_SLOT_EMPTY ?
376 TSK_FS_META_FLAG_UNUSED : TSK_FS_META_FLAG_USED);
377
378 fs_meta->flags = (TSK_FS_META_FLAG_ENUM)flags;
379
380 if ((dentry->attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) {
381 /* LFN entries don't have these values */
382 fs_meta->nlink = 0;
383 fs_meta->size = 0;
384 fs_meta->mtime = 0;
385 fs_meta->atime = 0;
386 fs_meta->ctime = 0;
387 fs_meta->crtime = 0;
388 fs_meta->mtime_nano = fs_meta->atime_nano = fs_meta->ctime_nano =
389 fs_meta->crtime_nano = 0;
390 }
391 else {
392 /* There is no notion of link in FAT, just deleted or not */
393 if(FATXXFS_IS_DELETED(dentry->name, a_fatfs)){
394 fs_meta->nlink = 0;
395 }
396 else{
397 fs_meta->nlink = 1;
398 }
399 fs_meta->size = (TSK_OFF_T) tsk_getu32(fs->endian, dentry->size);
400
401 /* If these are valid dates, then convert to a unix date format */
402 if (FATFS_ISDATE(tsk_getu16(fs->endian, dentry->wdate)))
403 fs_meta->mtime =
404 fatfs_dos_2_unix_time(tsk_getu16(fs->endian, dentry->wdate),
405 tsk_getu16(fs->endian, dentry->wtime), 0);
406 else
407 fs_meta->mtime = 0;
408 fs_meta->mtime_nano = 0;
409
410 if (FATFS_ISDATE(tsk_getu16(fs->endian, dentry->adate)))
411 fs_meta->atime =
412 fatfs_dos_2_unix_time(tsk_getu16(fs->endian, dentry->adate), 0, 0);
413 else
414 fs_meta->atime = 0;
415 fs_meta->atime_nano = 0;
416
417
418 /* cdate is the creation date in FAT and there is no change,
419 * so we just put in into change and set create to 0. The other
420 * front-end code knows how to handle it and display it
421 */
422 if (FATFS_ISDATE(tsk_getu16(fs->endian, dentry->cdate))) {
423 fs_meta->crtime =
424 fatfs_dos_2_unix_time(tsk_getu16(fs->endian, dentry->cdate),
425 tsk_getu16(fs->endian, dentry->ctime), dentry->ctimeten);
426 fs_meta->crtime_nano = fatfs_dos_2_nanosec(dentry->ctimeten);
427 }
428 else {
429 fs_meta->crtime = 0;
430 fs_meta->crtime_nano = 0;
431 }
432
433 // FAT does not have a changed time
434 fs_meta->ctime = 0;
435 fs_meta->ctime_nano = 0;
436 }
437
438 /* Values that do not exist in FAT */
439 fs_meta->uid = 0;
440 fs_meta->gid = 0;
441 fs_meta->seq = 0;
442
443
444 /* We will be copying a name, so allocate a structure */
445 if (fs_meta->name2 == NULL) {
446 if ((fs_meta->name2 = (TSK_FS_META_NAME_LIST *)
447 tsk_malloc(sizeof(TSK_FS_META_NAME_LIST))) == NULL)
448 return TSK_ERR;
449 fs_meta->name2->next = NULL;
450 }
451
452 /* If we have a LFN entry, then we need to convert the three
453 * parts of the name to UTF-8 and copy it into the name structure .
454 */
455 if ((dentry->attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) {
456 FATXXFS_DENTRY_LFN *lfn = (FATXXFS_DENTRY_LFN *) dentry;
457
458 /* Convert the first part of the name */
459 UTF8 *name8 = (UTF8 *) fs_meta->name2->name;
460 UTF16 *name16 = (UTF16 *) lfn->part1;
461
462 int retVal = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &name16,
463 (UTF16 *) & lfn->part1[10],
464 &name8,
465 (UTF8 *) ((uintptr_t) fs_meta->name2->name +
466 sizeof(fs_meta->name2->name)),
467 TSKlenientConversion);
468
469 if (retVal != TSKconversionOK) {
470 tsk_error_reset();
471 tsk_error_set_errno(TSK_ERR_FS_UNICODE);
472 tsk_error_set_errstr
473 ("%s: Error converting FAT LFN (1) to UTF8: %d",
474 func_name, retVal);
475 *name8 = '\0';
476
477 return TSK_COR;
478 }
479
480 /* Convert the second part of the name */
481 name16 = (UTF16 *) lfn->part2;
482 retVal = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &name16,
483 (UTF16 *) & lfn->part2[12],
484 &name8,
485 (UTF8 *) ((uintptr_t) fs_meta->name2->name +
486 sizeof(fs_meta->name2->name)), TSKlenientConversion);
487
488 if (retVal != TSKconversionOK) {
489 tsk_error_reset();
490 tsk_error_set_errno(TSK_ERR_FS_UNICODE);
491 tsk_error_set_errstr
492 ("%s: Error converting FAT LFN (2) to UTF8: %d",
493 func_name, retVal);
494 *name8 = '\0';
495
496 return TSK_COR;
497 }
498
499 /* Convert the third part of the name */
500 name16 = (UTF16 *) lfn->part3;
501 retVal = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &name16,
502 (UTF16 *) & lfn->part3[4],
503 &name8,
504 (UTF8 *) ((uintptr_t) fs_meta->name2->name +
505 sizeof(fs_meta->name2->name)), TSKlenientConversion);
506
507 if (retVal != TSKconversionOK) {
508 tsk_error_reset();
509 tsk_error_set_errno(TSK_ERR_FS_UNICODE);
510 tsk_error_set_errstr
511 ("%s: Error converting FAT LFN (3) to UTF8: %d",
512 func_name, retVal);
513 *name8 = '\0';
514
515 return TSK_COR;
516 }
517
518 /* Make sure it is NULL Terminated */
519 if ((uintptr_t) name8 >
520 (uintptr_t) fs_meta->name2->name +
521 sizeof(fs_meta->name2->name))
522 fs_meta->name2->name[sizeof(fs_meta->name2->name) - 1] = '\0';
523 else
524 *name8 = '\0';
525 }
526 /* If the entry is for a volume label, then copy the label.
527 */
528 else if ((dentry->attrib & FATFS_ATTR_VOLUME) == FATFS_ATTR_VOLUME) {
529 int a;
530
531 i = 0;
532 for (a = 0; a < 8; a++) {
533 if ((dentry->name[a] != 0x00) && (dentry->name[a] != 0xff))
534 fs_meta->name2->name[i++] = dentry->name[a];
535 }
536 for (a = 0; a < 3; a++) {
537 if ((dentry->ext[a] != 0x00) && (dentry->ext[a] != 0xff))
538 fs_meta->name2->name[i++] = dentry->ext[a];
539 }
540 fs_meta->name2->name[i] = '\0';
541
542 /* clean up non-ASCII because we are
543 * copying it into a buffer that is supposed to be UTF-8 and
544 * we don't know what encoding it is actually in or if it is
545 * simply junk. */
546 fatfs_cleanup_ascii(fs_meta->name2->name);
547 }
548 /* If the entry is a normal short entry, then copy the name
549 * and add the '.' for the extension
550 */
551 else {
552 for (i = 0; (i < 8) && (dentry->name[i] != 0) && (dentry->name[i] != ' ');
553 i++) {
554 if ((i == 0) && (dentry->name[0] == FATXXFS_SLOT_DELETED))
555 fs_meta->name2->name[0] = '_';
556 else if ((dentry->lowercase & FATXXFS_CASE_LOWER_BASE) &&
557 (dentry->name[i] >= 'A') && (dentry->name[i] <= 'Z'))
558 fs_meta->name2->name[i] = dentry->name[i] + 32;
559 else
560 fs_meta->name2->name[i] = dentry->name[i];
561 }
562
563 if ((dentry->ext[0]) && (dentry->ext[0] != ' ')) {
564 int a;
565 fs_meta->name2->name[i++] = '.';
566 for (a = 0;
567 (a < 3) && (dentry->ext[a] != 0) && (dentry->ext[a] != ' ');
568 a++, i++) {
569 if ((dentry->lowercase & FATXXFS_CASE_LOWER_EXT)
570 && (dentry->ext[a] >= 'A') && (dentry->ext[a] <= 'Z'))
571 fs_meta->name2->name[i] = dentry->ext[a] + 32;
572 else
573 fs_meta->name2->name[i] = dentry->ext[a];
574 }
575 }
576 fs_meta->name2->name[i] = '\0';
577
578 /* clean up non-ASCII because we are
579 * copying it into a buffer that is supposed to be UTF-8 and
580 * we don't know what encoding it is actually in or if it is
581 * simply junk. */
582 fatfs_cleanup_ascii(fs_meta->name2->name);
583 }
584
585 /* Clean up name to remove control characters */
586 i = 0;
587 while (fs_meta->name2->name[i] != '\0') {
588 if (TSK_IS_CNTRL(fs_meta->name2->name[i]))
589 fs_meta->name2->name[i] = '^';
590 i++;
591 }
592
593 /* get the starting cluster */
594 addr_ptr = (TSK_DADDR_T *) fs_meta->content_ptr;
595 if ((dentry->attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) {
596 addr_ptr[0] = 0;
597 }
598 else {
599 addr_ptr[0] = FATXXFS_DENTRY_CLUST(fs, dentry) & a_fatfs->mask;
600 }
601
602 /* FAT does not store a size for its directories so make one based
603 * on the number of allocated sectors
604 */
605 if ((dentry->attrib & FATFS_ATTR_DIRECTORY) &&
606 ((dentry->attrib & FATFS_ATTR_LFN) != FATFS_ATTR_LFN)) {
607 if (fs_meta->flags & TSK_FS_META_FLAG_ALLOC) {
608 TSK_LIST *list_seen = NULL;
609
610 /* count the total number of clusters in this file */
611 TSK_DADDR_T clust = FATXXFS_DENTRY_CLUST(fs, dentry);
612 int cnum = 0;
613
614 while ((clust) && (0 == FATFS_ISEOF(clust, a_fatfs->mask))) {
615 TSK_DADDR_T nxt;
616
617 /* Make sure we do not get into an infinite loop */
618 if (tsk_list_find(list_seen, clust)) {
619 if (tsk_verbose)
620 tsk_fprintf(stderr,
621 "Loop found while determining directory size\n");
622 break;
623 }
624 if (tsk_list_add(&list_seen, clust)) {
625 tsk_list_free(list_seen);
626 list_seen = NULL;
627 return TSK_ERR;
628 }
629
630 cnum++;
631
632 if (fatfs_getFAT(a_fatfs, clust, &nxt))
633 break;
634 else
635 clust = nxt;
636 }
637
638 tsk_list_free(list_seen);
639 list_seen = NULL;
640
641 fs_meta->size =
642 (TSK_OFF_T) ((cnum * a_fatfs->csize) << a_fatfs->ssize_sh);
643 }
644 /* if the dir is unallocated, then assume 0 or cluster size
645 * Ideally, we would have a smart algo here to do recovery
646 * and look for dentries. However, we do not have that right
647 * now and if we do not add this special check then it can
648 * assume that an allocated file cluster chain belongs to the
649 * directory */
650 else {
651 // if the first cluster is allocated, then set size to be 0
652 if (fatxxfs_is_cluster_alloc(a_fatfs, FATXXFS_DENTRY_CLUST(fs,
653 dentry)) == 1)
654 fs_meta->size = 0;
655 else
656 fs_meta->size = a_fatfs->csize << a_fatfs->ssize_sh;
657 }
658 }
659
660 return TSK_OK;
661 }
662
663 /**
664 * \internal
665 * Populate the TSK_FS_META object of a TSK_FS_FILE object for a
666 * given inode address.
667 *
668 * @param [in] a_fs File system that contains the inode.
669 * @param [out] a_fs_file The file corresponding to the inode.
670 * @param [in] a_inum The inode address.
671 * @returns 1 if an error occurs or if the inode address is not
672 * for a valid inode, 0 otherwise.
673 */
674 uint8_t
fatxxfs_inode_lookup(FATFS_INFO * a_fatfs,TSK_FS_FILE * a_fs_file,TSK_INUM_T a_inum)675 fatxxfs_inode_lookup(FATFS_INFO *a_fatfs, TSK_FS_FILE *a_fs_file,
676 TSK_INUM_T a_inum)
677 {
678 const char *func_name = "fatxxfs_inode_lookup";
679 TSK_DADDR_T sector = 0;
680 int8_t ret_val = 0;
681 FATFS_DATA_UNIT_ALLOC_STATUS_ENUM sector_alloc_status = FATFS_DATA_UNIT_ALLOC_STATUS_UNKNOWN;
682 FATFS_DENTRY dentry;
683 TSK_RETVAL_ENUM copy_result = TSK_OK;
684
685 tsk_error_reset();
686 if (fatfs_ptr_arg_is_null(a_fatfs, "a_fatfs", func_name) ||
687 fatfs_ptr_arg_is_null(a_fs_file, "a_fs_file", func_name) ||
688 !fatfs_inum_arg_is_in_range(a_fatfs, a_inum, func_name)) {
689 return 1;
690 }
691
692 sector = FATFS_INODE_2_SECT(a_fatfs, a_inum);
693 if (sector > a_fatfs->fs_info.last_block) {
694 tsk_error_reset();
695 tsk_error_set_errno(TSK_ERR_FS_INODE_NUM);
696 tsk_error_set_errstr("%s: Inode %" PRIuINUM
697 " in sector too big for image: %" PRIuDADDR, func_name, a_inum, sector);
698 return 1;
699 }
700
701 if (fatfs_dentry_load(a_fatfs, &dentry, a_inum) != 0) {
702 return 1;
703 }
704
705 ret_val = fatfs_is_sectalloc(a_fatfs, sector);
706 if (ret_val == -1) {
707 return 1;
708 }
709 else {
710 sector_alloc_status = (FATFS_DATA_UNIT_ALLOC_STATUS_ENUM)ret_val;
711 }
712
713 /* Note that only the sector allocation status is used to choose
714 * between the basic or in-depth version of the inode validity
715 * test. In other places in the code information about whether or not
716 * the sector that contains the inode is part of a folder is used to
717 * make this decision. Here, that information is not available. Thus,
718 * the test here is less reliable and may result in some false
719 * positives. */
720 if (!fatxxfs_is_dentry(a_fatfs, &dentry, sector_alloc_status, sector_alloc_status)) {
721 tsk_error_reset();
722 tsk_error_set_errno(TSK_ERR_FS_INODE_NUM);
723 tsk_error_set_errstr("%s: %" PRIuINUM
724 " is not an inode", func_name, a_inum);
725 return 1;
726 }
727
728 copy_result = fatxxfs_dinode_copy(a_fatfs, a_inum, &dentry, (uint8_t)sector_alloc_status, a_fs_file);
729 if (copy_result == TSK_OK) {
730 return 0;
731 }
732 else if (copy_result == TSK_COR) {
733 /* If there was a Unicode conversion error,
734 * then still return the inode. */
735 if (tsk_verbose) {
736 tsk_error_print(stderr);
737 }
738 tsk_error_reset();
739 return 0;
740 }
741 else {
742 return 1;
743 }
744 }
745
746 /**
747 * Output the file attributes of an exFAT file directory entry in
748 * human-readable form.
749 *
750 * @param a_fatfs Source file system for the directory entry.
751 * @param a_inum Inode address associated with the directory entry.
752 * @param a_hFile Handle of the file to which to write.
753 * @return 0 on success, 1 on failure, per TSK convention
754 */
755 uint8_t
fatxxfs_istat_attr_flags(FATFS_INFO * a_fatfs,TSK_INUM_T a_inum,FILE * a_hFile)756 fatxxfs_istat_attr_flags(FATFS_INFO *a_fatfs, TSK_INUM_T a_inum, FILE *a_hFile)
757 {
758 const char *func_name = "fatxxfs_istat_attr_flags";
759 FATXXFS_DENTRY dentry;
760
761 tsk_error_reset();
762 if (fatfs_ptr_arg_is_null(a_fatfs, "a_fatfs", func_name) ||
763 fatfs_ptr_arg_is_null(a_hFile, "a_hFile", func_name) ||
764 !fatfs_inum_arg_is_in_range(a_fatfs, a_inum, func_name)) {
765 return 1;
766 }
767
768 if (fatfs_dentry_load(a_fatfs, (FATFS_DENTRY*)(&dentry), a_inum)) {
769 return 1;
770 }
771
772 if ((dentry.attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) {
773 tsk_fprintf(a_hFile, "Long File Name\n");
774 }
775 else {
776 if (dentry.attrib & FATFS_ATTR_DIRECTORY)
777 tsk_fprintf(a_hFile, "Directory");
778 else if (dentry.attrib & FATFS_ATTR_VOLUME)
779 tsk_fprintf(a_hFile, "Volume Label");
780 else
781 tsk_fprintf(a_hFile, "File");
782
783 if (dentry.attrib & FATFS_ATTR_READONLY)
784 tsk_fprintf(a_hFile, ", Read Only");
785 if (dentry.attrib & FATFS_ATTR_HIDDEN)
786 tsk_fprintf(a_hFile, ", Hidden");
787 if (dentry.attrib & FATFS_ATTR_SYSTEM)
788 tsk_fprintf(a_hFile, ", System");
789 if (dentry.attrib & FATFS_ATTR_ARCHIVE)
790 tsk_fprintf(a_hFile, ", Archive");
791
792 tsk_fprintf(a_hFile, "\n");
793 }
794
795 return 0;
796 }
797
798 uint8_t
fatxxfs_inode_walk_should_skip_dentry(FATFS_INFO * a_fatfs,TSK_INUM_T a_inum,FATFS_DENTRY * a_dentry,unsigned int a_selection_flags,int a_cluster_is_alloc)799 fatxxfs_inode_walk_should_skip_dentry(FATFS_INFO *a_fatfs, TSK_INUM_T a_inum,
800 FATFS_DENTRY *a_dentry, unsigned int a_selection_flags,
801 int a_cluster_is_alloc)
802 {
803 const char *func_name = "fatxxfs_inode_walk_should_skip_dentry";
804 FATXXFS_DENTRY *dentry = (FATXXFS_DENTRY*)a_dentry;
805 unsigned int dentry_flags = 0;
806
807 assert(a_fatfs != NULL);
808 assert(fatfs_inum_is_in_range(a_fatfs, a_inum));
809 assert(a_dentry != NULL);
810
811 tsk_error_reset();
812 if (fatfs_ptr_arg_is_null(a_fatfs, "a_fatfs", func_name) ||
813 !fatfs_inum_arg_is_in_range(a_fatfs, a_inum, func_name) ||
814 fatfs_ptr_arg_is_null(a_dentry, "a_dentry", func_name)) {
815 return 1;
816 }
817
818 /* If this is a long file name entry, then skip it and
819 * wait for the short name. */
820 if ((dentry->attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) {
821 return 1;
822 }
823
824 /* Skip the "." and ".." entries because they are redundant. */
825 if (((dentry->attrib & FATFS_ATTR_DIRECTORY) == FATFS_ATTR_DIRECTORY) &&
826 (dentry->name[0] == '.')) {
827 return 1;
828 }
829
830 /* Compare directory entry allocation status with the inode selection
831 * flags. Allocation status is determined first by the allocation status
832 * of the sector that contains the entry, then by the deleted status of
833 * the file. This is necessary because when a directory is deleted, its
834 * contents are not always marked as unallocated. */
835 if (a_cluster_is_alloc == 1) {
836 if(FATXXFS_IS_DELETED(dentry->name, a_fatfs)){
837 dentry_flags = TSK_FS_META_FLAG_UNALLOC;
838 }
839 else{
840 dentry_flags = TSK_FS_META_FLAG_ALLOC;
841 }
842 }
843 else {
844 dentry_flags = TSK_FS_META_FLAG_UNALLOC;
845 }
846
847 if ((a_selection_flags & dentry_flags) != dentry_flags) {
848 return 1;
849 }
850
851 /* If the processing flags call for only processing orphan files, check
852 * whether or not this inode is in list of non-orphan files found via name
853 * walk. */
854 if ((dentry_flags & TSK_FS_META_FLAG_UNALLOC) &&
855 (a_selection_flags & TSK_FS_META_FLAG_ORPHAN) &&
856 (tsk_fs_dir_find_inum_named(&(a_fatfs->fs_info), a_inum))) {
857 return 1;
858 }
859
860 return 0;
861 }
862