/src/sleuthkit/tsk/vs/mm_open.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * The Sleuth Kit |
3 | | * |
4 | | * Brian Carrier [carrier <at> sleuthkit [dot] org] |
5 | | * Copyright (c) 2003-2011 Brian Carrier. All rights reserved |
6 | | * |
7 | | * tsk_vs_open - wrapper function for specific partition type |
8 | | * |
9 | | * This software is distributed under the Common Public License 1.0 |
10 | | */ |
11 | | |
12 | | /** |
13 | | * \file mm_open.c |
14 | | * Contains general code to open volume systems. |
15 | | */ |
16 | | |
17 | | #include "tsk_vs_i.h" |
18 | | #include "tsk/util/detect_encryption.h" |
19 | | |
20 | | |
21 | | /** |
22 | | * \ingroup vslib |
23 | | * |
24 | | * Open a disk image and process the media management system |
25 | | * data. This calls VS specific code to determine the type and |
26 | | * collect data. |
27 | | * |
28 | | * @param img_info The opened disk image. |
29 | | * @param offset Byte offset in the disk image to start analyzing from. |
30 | | * @param type Type of volume system (including auto detect) |
31 | | * |
32 | | * @return NULL on error. |
33 | | */ |
34 | | TSK_VS_INFO * |
35 | | tsk_vs_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset, |
36 | | TSK_VS_TYPE_ENUM type) |
37 | 13.2k | { |
38 | 13.2k | if (img_info == NULL) { |
39 | | /* Opening the image file(s) failed, if attempted. */ |
40 | 0 | tsk_error_reset(); |
41 | 0 | tsk_error_set_errno(TSK_ERR_IMG_NOFILE); |
42 | 0 | tsk_error_set_errstr("mm_open"); |
43 | 0 | return NULL; |
44 | 0 | } |
45 | | |
46 | 13.2k | if (img_info->itype == TSK_IMG_TYPE_LOGICAL) { |
47 | 0 | tsk_error_reset(); |
48 | 0 | tsk_error_set_errno(TSK_ERR_VS_UNSUPTYPE); |
49 | 0 | tsk_error_set_errstr("Logical image type can not have a volume system"); |
50 | 0 | return NULL; |
51 | 0 | } |
52 | | |
53 | | /* Autodetect mode |
54 | | * We need to try all of them in case there are multiple |
55 | | * installations |
56 | | * |
57 | | * NOte that errors that are encountered during the testing process |
58 | | * will not be reported |
59 | | */ |
60 | 13.2k | if (type == TSK_VS_TYPE_DETECT) { |
61 | 0 | TSK_VS_INFO *vs, *prev_vs = NULL; |
62 | 0 | char *prev_type = NULL; |
63 | |
|
64 | 0 | if ((vs = tsk_vs_dos_open(img_info, offset, 1)) != NULL) { |
65 | 0 | prev_type = "DOS"; |
66 | 0 | prev_vs = vs; |
67 | 0 | } |
68 | 0 | else { |
69 | 0 | tsk_error_reset(); |
70 | 0 | } |
71 | |
|
72 | 0 | if ((vs = tsk_vs_bsd_open(img_info, offset)) != NULL) { |
73 | | // if (prev_type == NULL) { |
74 | | // In this case, BSD takes priority because BSD partitions start off with |
75 | | // the DOS magic value in the first sector with the boot code. |
76 | 0 | prev_type = "BSD"; |
77 | 0 | prev_vs = vs; |
78 | | /* |
79 | | } |
80 | | else { |
81 | | prev_vs->close(prev_vs); |
82 | | vs->close(vs); |
83 | | tsk_error_reset(); |
84 | | tsk_error_set_errno(TSK_ERR_VS_UNKTYPE); |
85 | | tsk_error_set_errstr( |
86 | | "BSD or %s at %" PRIuDADDR, prev_type, offset); |
87 | | tsk_errstr2[0] = '\0'; |
88 | | return NULL; |
89 | | } |
90 | | */ |
91 | 0 | } |
92 | 0 | else { |
93 | 0 | tsk_error_reset(); |
94 | 0 | } |
95 | |
|
96 | 0 | if ((vs = tsk_vs_gpt_open(img_info, offset)) != NULL) { |
97 | |
|
98 | 0 | if ((prev_type != NULL) && (strcmp(prev_type, "DOS") == 0) && (vs->is_backup)) { |
99 | | /* In this case we've found a DOS partition and a backup GPT partition. |
100 | | * The DOS partition takes priority in this case (and are already in prev_type and prev_vs) */ |
101 | 0 | vs->close(vs); |
102 | 0 | if (tsk_verbose) |
103 | 0 | tsk_fprintf(stderr, |
104 | 0 | "mm_open: Ignoring secondary GPT Partition\n"); |
105 | 0 | } |
106 | 0 | else { |
107 | 0 | if (prev_type != NULL) { |
108 | | |
109 | | /* GPT drives have a DOS Safety partition table. |
110 | | * Test to see if the GPT has a safety partiiton |
111 | | * and then we can igore the DOS */ |
112 | 0 | if (strcmp(prev_type, "DOS") == 0) { |
113 | 0 | TSK_VS_PART_INFO *tmp_set; |
114 | 0 | for (tmp_set = prev_vs->part_list; tmp_set; |
115 | 0 | tmp_set = tmp_set->next) { |
116 | 0 | if ((tmp_set->desc) |
117 | 0 | && (strncmp(tmp_set->desc, "GPT Safety", |
118 | 0 | 10) == 0) |
119 | 0 | && (tmp_set->start <= 63)) { |
120 | |
|
121 | 0 | if (tsk_verbose) |
122 | 0 | tsk_fprintf(stderr, |
123 | 0 | "mm_open: Ignoring DOS Safety GPT Partition\n"); |
124 | 0 | prev_type = NULL; |
125 | 0 | prev_vs->close(prev_vs); |
126 | 0 | prev_vs = NULL; |
127 | 0 | break; |
128 | 0 | } |
129 | 0 | } |
130 | 0 | } |
131 | | |
132 | | /* If we never found the safety, then we have a conflict. */ |
133 | 0 | if (prev_type != NULL) { |
134 | 0 | prev_vs->close(prev_vs); |
135 | 0 | vs->close(vs); |
136 | 0 | tsk_error_reset(); |
137 | 0 | tsk_error_set_errno(TSK_ERR_VS_MULTTYPE); |
138 | 0 | tsk_error_set_errstr("GPT or %s at %" PRIuDADDR, prev_type, |
139 | 0 | offset); |
140 | 0 | return NULL; |
141 | 0 | } |
142 | 0 | } |
143 | 0 | prev_type = "GPT"; |
144 | 0 | prev_vs = vs; |
145 | 0 | } |
146 | 0 | } |
147 | 0 | else { |
148 | 0 | tsk_error_reset(); |
149 | 0 | } |
150 | | |
151 | 0 | if ((vs = tsk_vs_sun_open(img_info, offset)) != NULL) { |
152 | 0 | if (prev_type == NULL) { |
153 | 0 | prev_type = "Sun"; |
154 | 0 | prev_vs = vs; |
155 | 0 | } |
156 | 0 | else { |
157 | 0 | prev_vs->close(prev_vs); |
158 | 0 | vs->close(vs); |
159 | 0 | tsk_error_reset(); |
160 | 0 | tsk_error_set_errno(TSK_ERR_VS_MULTTYPE); |
161 | 0 | tsk_error_set_errstr("Sun or %s at %" PRIuDADDR, prev_type, |
162 | 0 | offset); |
163 | 0 | return NULL; |
164 | 0 | } |
165 | 0 | } |
166 | 0 | else { |
167 | 0 | tsk_error_reset(); |
168 | 0 | } |
169 | | |
170 | 0 | if ((vs = tsk_vs_mac_open(img_info, offset)) != NULL) { |
171 | 0 | if (prev_type == NULL) { |
172 | 0 | prev_type = "Mac"; |
173 | 0 | prev_vs = vs; |
174 | 0 | } |
175 | 0 | else { |
176 | 0 | prev_vs->close(prev_vs); |
177 | 0 | vs->close(vs); |
178 | 0 | tsk_error_reset(); |
179 | 0 | tsk_error_set_errno(TSK_ERR_VS_MULTTYPE); |
180 | 0 | tsk_error_set_errstr("Mac or %s at %" PRIuDADDR, prev_type, |
181 | 0 | offset); |
182 | 0 | return NULL; |
183 | 0 | } |
184 | 0 | } |
185 | 0 | else { |
186 | 0 | tsk_error_reset(); |
187 | 0 | } |
188 | | |
189 | 0 | if (prev_vs == NULL) { |
190 | 0 | tsk_error_reset(); |
191 | | |
192 | | // Check whether the volume system appears to be encrypted. |
193 | | // Note that detectDiskEncryption does not do an entropy calculation - high entropy |
194 | | // files will be reported by tsk_fs_open_img(). |
195 | 0 | encryption_detected_result* result = detectDiskEncryption(img_info, offset); |
196 | 0 | if (result != NULL) { |
197 | 0 | if (result->encryptionType == ENCRYPTION_DETECTED_SIGNATURE) { |
198 | 0 | tsk_error_set_errno(TSK_ERR_VS_ENCRYPTED); |
199 | 0 | tsk_error_set_errstr("%s", result->desc); |
200 | 0 | } |
201 | 0 | free(result); |
202 | 0 | result = NULL; |
203 | 0 | } |
204 | 0 | else { |
205 | 0 | tsk_error_set_errno(TSK_ERR_VS_UNKTYPE); |
206 | 0 | } |
207 | 0 | return NULL; |
208 | 0 | } |
209 | | |
210 | 0 | return prev_vs; |
211 | 0 | } |
212 | | |
213 | | // Not autodetect |
214 | 13.2k | else { |
215 | | |
216 | 13.2k | switch (type) { |
217 | 1.27k | case TSK_VS_TYPE_DOS: |
218 | 1.27k | return tsk_vs_dos_open(img_info, offset, 0); |
219 | 591 | case TSK_VS_TYPE_MAC: |
220 | 591 | return tsk_vs_mac_open(img_info, offset); |
221 | 0 | case TSK_VS_TYPE_BSD: |
222 | 0 | return tsk_vs_bsd_open(img_info, offset); |
223 | 596 | case TSK_VS_TYPE_SUN: |
224 | 596 | return tsk_vs_sun_open(img_info, offset); |
225 | 10.7k | case TSK_VS_TYPE_GPT: |
226 | 10.7k | return tsk_vs_gpt_open(img_info, offset); |
227 | 0 | case TSK_VS_TYPE_APFS: // Not supported yet |
228 | 0 | case TSK_VS_TYPE_LVM: // Not supported yet |
229 | 0 | case TSK_VS_TYPE_UNSUPP: |
230 | 0 | default: |
231 | 0 | tsk_error_reset(); |
232 | 0 | tsk_error_set_errno(TSK_ERR_VS_UNSUPTYPE); |
233 | 0 | tsk_error_set_errstr("%d", type); |
234 | 0 | return NULL; |
235 | 13.2k | } |
236 | 13.2k | } |
237 | 13.2k | } |
238 | | |
239 | | /** |
240 | | * \ingroup vslib |
241 | | * Closes an open volume system |
242 | | * @param a_vs Pointer to the open volume system structure. |
243 | | */ |
244 | | void |
245 | | tsk_vs_close(TSK_VS_INFO * a_vs) |
246 | 2.77k | { |
247 | 2.77k | if (a_vs == NULL) { |
248 | 0 | return; |
249 | 0 | } |
250 | 2.77k | a_vs->close((TSK_VS_INFO *) a_vs); |
251 | 2.77k | } |