1 /* 2 * Brian Carrier [carrier <at> sleuthkit [dot] org] 3 * Copyright (c) 2006-2016 Brian Carrier, Basis Technology. All rights reserved 4 * Copyright (c) 2005 Brian Carrier. All rights reserved 5 * 6 * This software is distributed under the Common Public License 1.0 7 * 8 */ 9 10 /** \file vmdk.c 11 * Internal code for TSK to interface with libvmdk. 12 */ 13 14 #include "tsk_img_i.h" 15 16 #if HAVE_LIBVMDK 17 #include "vmdk.h" 18 19 #define TSK_VMDK_ERROR_STRING_SIZE 512 20 21 22 /** 23 * Get error string from libvmdk and make buffer empty if that didn't work. 24 * @returns 1 if error message was not set 25 */ 26 static uint8_t 27 getError(libvmdk_error_t * vmdk_error, 28 char error_string[TSK_VMDK_ERROR_STRING_SIZE]) 29 { 30 int retval; 31 error_string[0] = '\0'; 32 retval = libvmdk_error_backtrace_sprint(vmdk_error, 33 error_string, TSK_VMDK_ERROR_STRING_SIZE); 34 if (retval) 35 return 1; 36 return 0; 37 } 38 39 40 static ssize_t 41 vmdk_image_read(TSK_IMG_INFO * img_info, TSK_OFF_T offset, char *buf, 42 size_t len) 43 { 44 char error_string[TSK_VMDK_ERROR_STRING_SIZE]; 45 libvmdk_error_t *vmdk_error = NULL; 46 47 ssize_t cnt; 48 IMG_VMDK_INFO *vmdk_info = (IMG_VMDK_INFO *) img_info; 49 50 if (tsk_verbose) 51 tsk_fprintf(stderr, 52 "vmdk_image_read: byte offset: %" PRIdOFF " len: %" PRIuSIZE 53 "\n", offset, len); 54 55 if (offset > img_info->size) { 56 tsk_error_reset(); 57 tsk_error_set_errno(TSK_ERR_IMG_READ_OFF); 58 tsk_error_set_errstr("vmdk_image_read - %" PRIdOFF, offset); 59 return -1; 60 } 61 62 tsk_take_lock(&(vmdk_info->read_lock)); 63 64 cnt = libvmdk_handle_read_buffer_at_offset(vmdk_info->handle, 65 buf, len, offset, &vmdk_error); 66 if (cnt < 0) { 67 char *errmsg = NULL; 68 tsk_error_reset(); 69 tsk_error_set_errno(TSK_ERR_IMG_READ); 70 if (getError(vmdk_error, error_string)) 71 errmsg = strerror(errno); 72 else 73 errmsg = error_string; 74 75 tsk_error_set_errstr("vmdk_image_read - offset: %" PRIdOFF 76 " - len: %" PRIuSIZE " - %s", offset, len, errmsg); 77 tsk_release_lock(&(vmdk_info->read_lock)); 78 return -1; 79 } 80 81 tsk_release_lock(&(vmdk_info->read_lock)); 82 83 return cnt; 84 } 85 86 static void 87 vmdk_image_imgstat(TSK_IMG_INFO * img_info, FILE * hFile) 88 { 89 tsk_fprintf(hFile, "IMAGE FILE INFORMATION\n"); 90 tsk_fprintf(hFile, "--------------------------------------------\n"); 91 tsk_fprintf(hFile, "Image Type:\t\tvmdk\n"); 92 tsk_fprintf(hFile, "\nSize of data in bytes:\t%" PRIdOFF "\n", 93 img_info->size); 94 tsk_fprintf(hFile, "Sector size:\t%d\n", img_info->sector_size); 95 96 return; 97 } 98 99 100 static void 101 vmdk_image_close(TSK_IMG_INFO * img_info) 102 { 103 int i; 104 char error_string[TSK_VMDK_ERROR_STRING_SIZE]; 105 libvmdk_error_t *vmdk_error = NULL; 106 char *errmsg = NULL; 107 IMG_VMDK_INFO *vmdk_info = (IMG_VMDK_INFO *) img_info; 108 109 if( libvmdk_handle_close(vmdk_info->handle, &vmdk_error ) != 0 ) 110 { 111 tsk_error_reset(); 112 tsk_error_set_errno(TSK_ERR_AUX_GENERIC); 113 if (getError(vmdk_error, error_string)) 114 errmsg = strerror(errno); 115 else 116 errmsg = error_string; 117 118 tsk_error_set_errstr("vmdk_image_close: unable to close handle - %s", errmsg); 119 } 120 121 libvmdk_handle_free(&(vmdk_info->handle), NULL); 122 if( libvmdk_handle_free(&(vmdk_info->handle), &vmdk_error ) != 1 ) 123 { 124 tsk_error_reset(); 125 tsk_error_set_errno(TSK_ERR_AUX_GENERIC); 126 if (getError(vmdk_error, error_string)) 127 errmsg = strerror(errno); 128 else 129 errmsg = error_string; 130 131 tsk_error_set_errstr("vmdk_image_close: unable to free handle - %s", errmsg); 132 } 133 134 for (i = 0; i < vmdk_info->img_info.num_img; i++) { 135 free(vmdk_info->img_info.images[i]); 136 } 137 free(vmdk_info->img_info.images); 138 139 tsk_deinit_lock(&(vmdk_info->read_lock)); 140 tsk_img_free(img_info); 141 } 142 143 TSK_IMG_INFO * 144 vmdk_open(int a_num_img, 145 const TSK_TCHAR * const a_images[], unsigned int a_ssize) 146 { 147 char error_string[TSK_VMDK_ERROR_STRING_SIZE]; 148 libvmdk_error_t *vmdk_error = NULL; 149 int i; 150 151 IMG_VMDK_INFO *vmdk_info = NULL; 152 TSK_IMG_INFO *img_info = NULL; 153 154 if (tsk_verbose) { 155 libvmdk_notify_set_verbose(1); 156 libvmdk_notify_set_stream(stderr, NULL); 157 } 158 159 if ((vmdk_info = 160 (IMG_VMDK_INFO *) tsk_img_malloc(sizeof(IMG_VMDK_INFO))) == 161 NULL) { 162 return NULL; 163 } 164 vmdk_info->handle = NULL; 165 img_info = (TSK_IMG_INFO *) vmdk_info; 166 167 vmdk_info->img_info.num_img = a_num_img; 168 if ((vmdk_info->img_info.images = 169 (TSK_TCHAR **) tsk_malloc(a_num_img * 170 sizeof(TSK_TCHAR *))) == NULL) { 171 tsk_img_free(vmdk_info); 172 return NULL; 173 } 174 for (i = 0; i < a_num_img; i++) { 175 if ((vmdk_info->img_info.images[i] = 176 (TSK_TCHAR *) tsk_malloc((TSTRLEN(a_images[i]) + 177 1) * sizeof(TSK_TCHAR))) == NULL) { 178 tsk_img_free(vmdk_info); 179 return NULL; 180 } 181 TSTRNCPY(vmdk_info->img_info.images[i], a_images[i], 182 TSTRLEN(a_images[i]) + 1); 183 } 184 185 if (libvmdk_handle_initialize(&(vmdk_info->handle), &vmdk_error) != 1) { 186 tsk_error_reset(); 187 tsk_error_set_errno(TSK_ERR_IMG_OPEN); 188 189 getError(vmdk_error, error_string); 190 tsk_error_set_errstr("vmdk_open file: %" PRIttocTSK 191 ": Error initializing handle (%s)", a_images[0], error_string); 192 libvmdk_error_free(&vmdk_error); 193 194 tsk_img_free(vmdk_info); 195 196 if (tsk_verbose != 0) { 197 tsk_fprintf(stderr, "Unable to create vmdk handle\n"); 198 } 199 return (NULL); 200 } 201 #if defined( TSK_WIN32 ) 202 if (libvmdk_handle_open_wide(vmdk_info->handle, 203 (const wchar_t *) vmdk_info->img_info.images[0], 204 LIBVMDK_OPEN_READ, &vmdk_error) != 1) 205 #else 206 if (libvmdk_handle_open(vmdk_info->handle, 207 (const char *) vmdk_info->img_info.images[0], 208 LIBVMDK_OPEN_READ, &vmdk_error) != 1) 209 #endif 210 { 211 tsk_error_reset(); 212 tsk_error_set_errno(TSK_ERR_IMG_OPEN); 213 214 getError(vmdk_error, error_string); 215 tsk_error_set_errstr("vmdk_open file: %" PRIttocTSK 216 ": Error opening (%s)", a_images[0], error_string); 217 libvmdk_error_free(&vmdk_error); 218 219 tsk_img_free(vmdk_info); 220 221 if (tsk_verbose != 0) { 222 tsk_fprintf(stderr, "Error opening vmdk file\n"); 223 } 224 return (NULL); 225 } 226 if( libvmdk_handle_open_extent_data_files(vmdk_info->handle, &vmdk_error ) != 1 ) 227 { 228 tsk_error_reset(); 229 tsk_error_set_errno(TSK_ERR_IMG_OPEN); 230 231 getError(vmdk_error, error_string); 232 tsk_error_set_errstr("vmdk_open file: %" PRIttocTSK 233 ": Error opening extent data files for image (%s)", a_images[0], 234 error_string); 235 libvmdk_error_free(&vmdk_error); 236 237 tsk_img_free(vmdk_info); 238 239 if (tsk_verbose != 0) { 240 tsk_fprintf(stderr, "Error opening vmdk extent data files\n"); 241 } 242 return (NULL); 243 } 244 if (libvmdk_handle_get_media_size(vmdk_info->handle, 245 (size64_t *) & (img_info->size), &vmdk_error) != 1) { 246 tsk_error_reset(); 247 tsk_error_set_errno(TSK_ERR_IMG_OPEN); 248 249 getError(vmdk_error, error_string); 250 tsk_error_set_errstr("vmdk_open file: %" PRIttocTSK 251 ": Error getting size of image (%s)", a_images[0], 252 error_string); 253 libvmdk_error_free(&vmdk_error); 254 255 tsk_img_free(vmdk_info); 256 257 if (tsk_verbose != 0) { 258 tsk_fprintf(stderr, "Error getting size of vmdk file\n"); 259 } 260 return (NULL); 261 } 262 263 if (a_ssize != 0) { 264 img_info->sector_size = a_ssize; 265 } 266 else { 267 img_info->sector_size = 512; 268 } 269 img_info->itype = TSK_IMG_TYPE_VMDK_VMDK; 270 img_info->read = &vmdk_image_read; 271 img_info->close = &vmdk_image_close; 272 img_info->imgstat = &vmdk_image_imgstat; 273 274 // initialize the read lock 275 tsk_init_lock(&(vmdk_info->read_lock)); 276 277 return (img_info); 278 } 279 280 #endif /* HAVE_LIBVMDK */ 281