1 /*
2 * Brian Carrier [carrier <at> sleuthkit [dot] org]
3 * Copyright (c) 2006-2011 Brian Carrier, Basis Technology. All rights reserved
4 *
5 * This software is distributed under the Common Public License 1.0
6 */
7
8 /**
9 * \file aff.c
10 * Internal code to interface with afflib to read and open AFF image files
11 */
12
13 #include "tsk_img_i.h"
14
15 #if HAVE_LIBAFFLIB
16
17 typedef int bool;
18
19 #include "aff.h"
20
21 /* Note: The routine -assumes- we are under a lock on &(img_info->cache_lock)) */
22 static ssize_t
aff_read(TSK_IMG_INFO * img_info,TSK_OFF_T offset,char * buf,size_t len)23 aff_read(TSK_IMG_INFO * img_info, TSK_OFF_T offset, char *buf, size_t len)
24 {
25 ssize_t cnt;
26 IMG_AFF_INFO *aff_info = (IMG_AFF_INFO *) img_info;
27
28 if (tsk_verbose)
29 tsk_fprintf(stderr,
30 "aff_read: byte offset: %" PRIdOFF " len: %" PRId64
31 "\n", offset, len);
32
33 if (offset > img_info->size) {
34 tsk_error_reset();
35 tsk_error_set_errno(TSK_ERR_IMG_READ_OFF);
36 tsk_error_set_errstr("aff_read - %" PRIdOFF, offset);
37 return -1;
38 }
39
40 if (aff_info->seek_pos != offset) {
41 if (af_seek(aff_info->af_file, offset, SEEK_SET) != (uint64_t)offset) {
42 tsk_error_reset();
43 // @@@ ADD more specific error messages
44 tsk_error_set_errno(TSK_ERR_IMG_SEEK);
45 tsk_error_set_errstr("aff_read - %" PRIdOFF " - %s", offset,
46 strerror(errno));
47 return -1;
48
49 }
50 aff_info->seek_pos = offset;
51 }
52
53 cnt = af_read(aff_info->af_file, (unsigned char *) buf, len);
54 if (cnt < 0) {
55 // @@@ Add more specific error message
56 tsk_error_reset();
57 tsk_error_set_errno(TSK_ERR_IMG_READ);
58 tsk_error_set_errstr("aff_read - offset: %" PRIdOFF " - len: %"
59 PRIuSIZE " - %s", offset, len, strerror(errno));
60 return -1;
61 }
62
63 /* AFF will return 0 if the page does not exist -- fill the
64 * buffer with zeros in this case */
65 if (cnt == 0) {
66 // @@@ We could improve this if there is an AFF call
67 // to see if the data exists or not
68 if ((af_eof(aff_info->af_file) == 0) &&
69 (offset + (TSK_OFF_T)len < img_info->size)) {
70 memset(buf, 0, len);
71 cnt = len;
72 }
73 }
74
75 aff_info->seek_pos += cnt;
76 return cnt;
77 }
78
79 static void
aff_imgstat(TSK_IMG_INFO * img_info,FILE * hFile)80 aff_imgstat(TSK_IMG_INFO * img_info, FILE * hFile)
81 {
82 IMG_AFF_INFO *aff_info = (IMG_AFF_INFO *) img_info;
83 unsigned char buf[512];
84 size_t buf_len = 512;
85
86
87 tsk_fprintf(hFile, "IMAGE FILE INFORMATION\n");
88 tsk_fprintf(hFile, "--------------------------------------------\n");
89 tsk_fprintf(hFile, "Image Type: ");
90 switch (aff_info->type) {
91 case AF_IDENTIFY_AFF:
92 tsk_fprintf(hFile, "AFF\n");
93 break;
94 case AF_IDENTIFY_AFD:
95 tsk_fprintf(hFile, "AFD\n");
96 break;
97 case AF_IDENTIFY_AFM:
98 tsk_fprintf(hFile, "AFM\n");
99 break;
100 default:
101 tsk_fprintf(hFile, "AFFLIB (%d)\n", aff_info->type);
102 break;
103 }
104
105 tsk_fprintf(hFile, "\nSize in bytes: %" PRIdOFF "\n", img_info->size);
106
107 // we won't have the rest of the info for the non-AFF formats.
108 if (img_info->itype == TSK_IMG_TYPE_AFF_ANY)
109 return;
110
111 tsk_fprintf(hFile, "\nMD5: ");
112 if (af_get_seg(aff_info->af_file, AF_MD5, NULL, buf, &buf_len) == 0) {
113 int i;
114 for (i = 0; i < 16; i++) {
115 tsk_fprintf(hFile, "%x", buf[i]);
116 }
117 tsk_fprintf(hFile, "\n");
118 }
119 else {
120 tsk_fprintf(hFile, "Segment not found\n");
121 }
122
123 buf_len = 512;
124 tsk_fprintf(hFile, "SHA1: ");
125 if (af_get_seg(aff_info->af_file, AF_SHA1, NULL, buf, &buf_len) == 0) {
126 int i;
127 for (i = 0; i < 20; i++) {
128 tsk_fprintf(hFile, "%x", buf[i]);
129 }
130 tsk_fprintf(hFile, "\n");
131 }
132 else {
133 tsk_fprintf(hFile, "Segment not found\n");
134 }
135
136 /* Creator segment */
137 buf_len = 512;
138 if (af_get_seg(aff_info->af_file, AF_CREATOR, NULL, buf,
139 &buf_len) == 0) {
140 buf[buf_len] = '\0';
141 tsk_fprintf(hFile, "Creator: %s\n", buf);
142 }
143
144 buf_len = 512;
145 if (af_get_seg(aff_info->af_file, AF_CASE_NUM, NULL, buf,
146 &buf_len) == 0) {
147 buf[buf_len] = '\0';
148 tsk_fprintf(hFile, "Case Number: %s\n", buf);
149 }
150
151 buf_len = 512;
152 if (af_get_seg(aff_info->af_file, AF_IMAGE_GID, NULL, buf,
153 &buf_len) == 0) {
154 unsigned int i;
155 tsk_fprintf(hFile, "Image GID: ");
156 for (i = 0; i < buf_len; i++) {
157 tsk_fprintf(hFile, "%X", buf[i]);
158 }
159 tsk_fprintf(hFile, "\n");
160 }
161
162 buf_len = 512;
163 if (af_get_seg(aff_info->af_file, AF_ACQUISITION_DATE, NULL, buf,
164 &buf_len) == 0) {
165 buf[buf_len] = '\0';
166 tsk_fprintf(hFile, "Acquisition Date: %s\n", buf);
167 }
168
169 buf_len = 512;
170 if (af_get_seg(aff_info->af_file, AF_ACQUISITION_NOTES, NULL, buf,
171 &buf_len) == 0) {
172 buf[buf_len] = '\0';
173 tsk_fprintf(hFile, "Acquisition Notes: %s\n", buf);
174 }
175
176 buf_len = 512;
177 if (af_get_seg(aff_info->af_file, AF_ACQUISITION_DEVICE, NULL, buf,
178 &buf_len) == 0) {
179 buf[buf_len] = '\0';
180 tsk_fprintf(hFile, "Acquisition Device: %s\n", buf);
181 }
182
183 buf_len = 512;
184 if (af_get_seg(aff_info->af_file, AF_AFFLIB_VERSION, NULL, buf,
185 &buf_len) == 0) {
186 buf[buf_len] = '\0';
187 tsk_fprintf(hFile, "AFFLib Version: %s\n", buf);
188 }
189
190 buf_len = 512;
191 if (af_get_seg(aff_info->af_file, AF_DEVICE_MANUFACTURER, NULL, buf,
192 &buf_len) == 0) {
193 buf[buf_len] = '\0';
194 tsk_fprintf(hFile, "Device Manufacturer: %s\n", buf);
195 }
196
197 buf_len = 512;
198 if (af_get_seg(aff_info->af_file, AF_DEVICE_MODEL, NULL, buf,
199 &buf_len) == 0) {
200 buf[buf_len] = '\0';
201 tsk_fprintf(hFile, "Device Model: %s\n", buf);
202 }
203
204 buf_len = 512;
205 if (af_get_seg(aff_info->af_file, AF_DEVICE_SN, NULL, buf,
206 &buf_len) == 0) {
207 buf[buf_len] = '\0';
208 tsk_fprintf(hFile, "Device SN: %s\n", buf);
209 }
210
211 return;
212 }
213
214 static void
aff_close(TSK_IMG_INFO * img_info)215 aff_close(TSK_IMG_INFO * img_info)
216 {
217 int i;
218 IMG_AFF_INFO *aff_info = (IMG_AFF_INFO *) img_info;
219 af_close(aff_info->af_file);
220 for (i = 0; i < img_info->num_img; i++) {
221 if (img_info->images[i])
222 free(img_info->images[i]);
223 }
224 free(img_info->images);
225 tsk_img_free(aff_info);
226 }
227
228
229 TSK_IMG_INFO *
aff_open(const TSK_TCHAR * const images[],unsigned int a_ssize)230 aff_open(const TSK_TCHAR * const images[], unsigned int a_ssize)
231 {
232 IMG_AFF_INFO *aff_info;
233 TSK_IMG_INFO *img_info;
234 int type;
235 char *image;
236
237 #ifdef TSK_WIN32
238 // convert wchar_t* image path to char* to conform to
239 // the AFFLIB API
240 UTF16 *utf16 = (UTF16 *) images[0];
241 size_t ilen = wcslen(utf16);
242 size_t olen = ilen * 4 + 1;
243 UTF8 *utf8 = (UTF8 *) tsk_malloc(olen);
244
245 image = (char *) utf8;
246 if (image == NULL)
247 return NULL;
248 TSKConversionResult retval =
249 tsk_UTF16toUTF8_lclorder((const UTF16 **) &utf16,
250 &utf16[ilen], &utf8,
251 &utf8[olen], TSKlenientConversion);
252 *utf8 = '\0';
253 if (retval != TSKconversionOK) {
254 tsk_error_reset();
255 tsk_error_set_errno(TSK_ERR_FS_UNICODE);
256 tsk_error_set_errstr("aff_open file: %" PRIttocTSK
257 ": Error converting path to UTF-8 %d\n", images[0], retval);
258 free(image);
259 return NULL;
260 }
261 utf8 = (UTF8 *) image;
262 while (*utf8) {
263 if (*utf8 > 127) {
264 tsk_error_reset();
265 tsk_error_set_errno(TSK_ERR_FS_UNICODE);
266 tsk_error_set_errstr("aff_open file: %" PRIttocTSK
267 ": Non-Latin paths are not supported for AFF images\n",
268 images[0]);
269 free(image);
270 return NULL;
271 }
272 utf8++;
273 }
274 #else
275 image = (char *) tsk_malloc(strlen(images[0]) + 1);
276 if (image == NULL)
277 return NULL;
278 strncpy(image, images[0], strlen(images[0]) + 1);
279 #endif
280
281 if ((aff_info =
282 (IMG_AFF_INFO *) tsk_img_malloc(sizeof(IMG_AFF_INFO))) ==
283 NULL) {
284 free(image);
285 return NULL;
286 }
287
288 img_info = (TSK_IMG_INFO *) aff_info;
289 img_info->read = aff_read;
290 img_info->close = aff_close;
291 img_info->imgstat = aff_imgstat;
292
293 // Save the image path in TSK_IMG_INFO - this is mostly for consistency with the other
294 // image types and is not currently used
295 img_info->num_img = 1;
296 img_info->images =
297 (TSK_TCHAR **)tsk_malloc(sizeof(TSK_TCHAR *) * img_info->num_img);
298 if (img_info->images == NULL) {
299 free(image);
300 return NULL;
301 }
302 size_t len = TSTRLEN(images[0]);
303 img_info->images[0] =
304 (TSK_TCHAR *)tsk_malloc(sizeof(TSK_TCHAR) * (len + 1));
305 if (img_info->images[0] == NULL) {
306 free(img_info->images);
307 free(image);
308 return NULL;
309 }
310 TSTRNCPY(img_info->images[0], images[0], len + 1);
311
312 img_info->sector_size = 512;
313 if (a_ssize)
314 img_info->sector_size = a_ssize;
315
316 type = af_identify_file_type(image, 1);
317 if ((type == AF_IDENTIFY_ERR) || (type == AF_IDENTIFY_NOEXIST)) {
318 if (tsk_verbose) {
319 tsk_fprintf(stderr,
320 "aff_open: Error determining type of file: %" PRIttocTSK
321 "\n", images[0]);
322 perror("aff_open");
323 }
324 tsk_error_reset();
325 tsk_error_set_errno(TSK_ERR_IMG_OPEN);
326 tsk_error_set_errstr("aff_open file: %" PRIttocTSK
327 ": Error checking type", images[0]);
328 tsk_img_free(aff_info);
329 free(image);
330 return NULL;
331 }
332 else if (type == AF_IDENTIFY_AFF) {
333 img_info->itype = TSK_IMG_TYPE_AFF_AFF;
334 }
335 else if (type == AF_IDENTIFY_AFD) {
336 img_info->itype = TSK_IMG_TYPE_AFF_AFD;
337 }
338 else if (type == AF_IDENTIFY_AFM) {
339 img_info->itype = TSK_IMG_TYPE_AFF_AFM;
340 }
341 else {
342 img_info->itype = TSK_IMG_TYPE_AFF_ANY;
343 }
344
345 aff_info->af_file = af_open(image, O_RDONLY | O_BINARY, 0);
346 if (!aff_info->af_file) {
347 // @@@ Need to check here if the open failed because of an incorrect password.
348 tsk_error_reset();
349 tsk_error_set_errno(TSK_ERR_IMG_OPEN);
350 tsk_error_set_errstr("aff_open file: %" PRIttocTSK
351 ": Error opening - %s", images[0], strerror(errno));
352 tsk_img_free(aff_info);
353 if (tsk_verbose) {
354 tsk_fprintf(stderr, "Error opening AFF/AFD/AFM file\n");
355 perror("aff_open");
356 }
357 free(image);
358 return NULL;
359 }
360 // verify that a password was given and we can read encrypted data.
361 if (af_cannot_decrypt(aff_info->af_file)) {
362 tsk_error_reset();
363 tsk_error_set_errno(TSK_ERR_IMG_PASSWD);
364 tsk_error_set_errstr("aff_open file: %" PRIttocTSK, images[0]);
365 tsk_img_free(aff_info);
366 if (tsk_verbose) {
367 tsk_fprintf(stderr,
368 "Error opening AFF/AFD/AFM file (incorrect password)\n");
369 }
370 free(image);
371 return NULL;
372 }
373
374 aff_info->type = type;
375
376 img_info->size = af_imagesize(aff_info->af_file);
377
378 af_seek(aff_info->af_file, 0, SEEK_SET);
379 aff_info->seek_pos = 0;
380 free(image);
381 return img_info;
382 }
383 #endif
384