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