1 /* 2 * Sleuth Kit Data Model 3 * 4 * Copyright 2011-2018 Basis Technology Corp. 5 * Contact: carrier <at> sleuthkit <dot> org 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 package org.sleuthkit.datamodel; 20 21 import java.io.BufferedReader; 22 import java.io.FileReader; 23 import java.io.IOException; 24 import java.text.DateFormat; 25 import java.text.SimpleDateFormat; 26 import java.util.ArrayList; 27 import java.util.Arrays; 28 import java.util.GregorianCalendar; 29 import java.util.HashMap; 30 import java.util.HashSet; 31 import java.util.List; 32 import java.util.Map; 33 import java.util.Set; 34 import java.util.TimeZone; 35 import java.util.UUID; 36 import java.util.concurrent.locks.ReadWriteLock; 37 import java.util.concurrent.locks.ReentrantReadWriteLock; 38 import org.sleuthkit.datamodel.TskData.TSK_FS_ATTR_TYPE_ENUM; 39 40 /** 41 * A utility class that provides a interface to the SleuthKit via JNI. Supports 42 * case management, add image process, reading data off content objects Setting 43 * up Hash database parameters and updating / reading values 44 * 45 * Caches image and filesystem handles and reuses them for the duration of the 46 * application 47 */ 48 public class SleuthkitJNI { 49 50 /** 51 * Lock to protect against the TSK data structures being closed while 52 * another thread is in the C++ code. Do not use this lock after obtaining 53 * HandleCache.cacheLock. Additionally, the only code that should acquire 54 * the write lock is CaseDbHandle.free(). 55 */ 56 private static final ReadWriteLock tskLock = new ReentrantReadWriteLock(); 57 58 /* 59 * Loads the SleuthKit libraries. 60 */ 61 static { LibraryUtils.loadSleuthkitJNI()62 LibraryUtils.loadSleuthkitJNI(); 63 } 64 65 /** 66 * Constructor for the utility class that provides a interface to the 67 * SleuthKit via JNI. 68 */ SleuthkitJNI()69 private SleuthkitJNI() { 70 } 71 72 /** 73 * Utility class to hold the handles for a single case. 74 */ 75 private static class CaseHandles { 76 /* 77 * A SleuthKit image handle cache implemented as a mappng of 78 * concatenated image file paths to image handles. 79 */ 80 private final Map<String, Long> imageHandleCache = new HashMap<>(); 81 82 /* 83 * A SleuthKit file system handles cache implemented as a mapping of 84 * image handles to image offset and file system handle pairs. 85 */ 86 private final Map<Long, Map<Long, Long>> fsHandleCache = new HashMap<>(); 87 88 /* 89 * The collection of open file handles. We will only allow requests 90 * through to the C code if the file handle exists in this collection. 91 */ 92 private final Set<Long> fileHandleCache = new HashSet<>(); 93 94 private final Map<Long, List<Long>> fileSystemToFileHandles = new HashMap<>(); 95 CaseHandles()96 private CaseHandles() { 97 // Nothing to do here 98 } 99 } 100 101 /** 102 * Cache of all handles allocated in the JNI layer. Used for: (a) quick 103 * lookup of frequently used handles (e.g. file system and image) (b) 104 * ensuring all handles passed in by clients of SleuthkitJNI are valid. (c) 105 * consistent cleanup of handles on closure. 106 */ 107 private static class HandleCache { 108 109 /* 110 * A monitor used to guard access to cached Sleuthkit JNI handles. 111 */ 112 private static final Object cacheLock = new Object(); 113 114 private static final Map<Long, CaseHandles> caseHandlesCache = new HashMap<>(); 115 116 private static final String INVALID_FILE_HANDLE = "Invalid file handle."; //NON-NLS 117 118 /** 119 * Create the empty cache for a new case 120 * 121 * @param caseDbPointer 122 */ createCaseHandleCache(long caseDbPointer)123 private static void createCaseHandleCache(long caseDbPointer) { 124 caseHandlesCache.put(caseDbPointer, new CaseHandles()); 125 } 126 127 /** 128 * If there is one case open return its handle. 129 * This is to support deprecated methods that don't have a case parameter. 130 * 131 * @return the open case pointer 132 * 133 * @throws TskCoreException If there are no cases open or if multiple cases are open 134 */ getDefaultCaseDbPointer()135 private static long getDefaultCaseDbPointer() throws TskCoreException { 136 synchronized (cacheLock) { 137 if (caseHandlesCache.keySet().size() > 1) { 138 throw new TskCoreException("Can not get default case handle with multiple open cases"); 139 } else if (caseHandlesCache.keySet().isEmpty()) { 140 throw new TskCoreException("Can not get default case handle with no open case"); 141 } 142 143 return (caseHandlesCache.keySet().iterator().next()); 144 } 145 } 146 147 /** 148 * Gets the case handle cache for a given case. 149 * 150 * @param caseDbPointer 151 * 152 * @return the case handle cache 153 */ getCaseHandles(long caseDbPointer)154 private static CaseHandles getCaseHandles(long caseDbPointer) { 155 synchronized (cacheLock) { 156 return caseHandlesCache.get(caseDbPointer); 157 } 158 } 159 160 /** 161 * Removes the case handle cache for a given case. 162 * 163 * @param caseDbPointer 164 */ removeCaseHandlesCache(long caseDbPointer)165 private static void removeCaseHandlesCache(long caseDbPointer) { 166 synchronized (cacheLock) { 167 if (caseHandlesCache.containsKey(caseDbPointer)) { 168 caseHandlesCache.get(caseDbPointer).fsHandleCache.clear(); 169 caseHandlesCache.get(caseDbPointer).imageHandleCache.clear(); 170 caseHandlesCache.get(caseDbPointer).fileHandleCache.clear(); 171 caseHandlesCache.get(caseDbPointer).fileSystemToFileHandles.clear(); 172 caseHandlesCache.remove(caseDbPointer); 173 } 174 } 175 } 176 177 /** 178 * Searches all the open caches for an image handle. 179 * 180 * @param imgHandle 181 * 182 * @return true if the handle is found in any cache, false otherwise 183 */ isImageInAnyCache(long imgHandle)184 private static boolean isImageInAnyCache(long imgHandle) { 185 synchronized (cacheLock) { 186 for (long caseDbPointer:caseHandlesCache.keySet()) { 187 if (caseHandlesCache.get(caseDbPointer).fsHandleCache.keySet().contains(imgHandle)) { 188 return true; 189 } 190 } 191 return false; 192 } 193 } 194 195 /** 196 * Add a new file handle to the cache. 197 * 198 * @param fileHandle The new file handle. 199 * @param fsHandle The file system handle in which the file lives. 200 */ addFileHandle(long caseDbPointer, long fileHandle, long fsHandle)201 private static void addFileHandle(long caseDbPointer, long fileHandle, long fsHandle) { 202 synchronized (cacheLock) { 203 // Add to collection of open file handles. 204 getCaseHandles(caseDbPointer).fileHandleCache.add(fileHandle); 205 206 // Add to map of file system to file handles. 207 if (getCaseHandles(caseDbPointer).fileSystemToFileHandles.containsKey(fsHandle)) { 208 getCaseHandles(caseDbPointer).fileSystemToFileHandles.get(fsHandle).add(fileHandle); 209 } else { 210 getCaseHandles(caseDbPointer).fileSystemToFileHandles.put(fsHandle, new ArrayList<Long>(Arrays.asList(fileHandle))); 211 } 212 } 213 } 214 215 /** 216 * Removes a file handle from the cache for the given case 217 * 218 * @param fileHandle 219 * @param skCase Can be null. If so, the first matching handle will be removed. 220 */ removeFileHandle(long fileHandle, SleuthkitCase skCase)221 private static void removeFileHandle(long fileHandle, SleuthkitCase skCase) { 222 synchronized (cacheLock) { 223 // Remove from collection of open file handles. 224 if (skCase != null) { 225 getCaseHandles(skCase.getCaseHandle().caseDbPointer).fileHandleCache.remove(fileHandle); 226 } else { 227 // If we don't know what case the handle is from, delete the first one we find 228 for (long caseDbPointer:caseHandlesCache.keySet()) { 229 if (caseHandlesCache.get(caseDbPointer).fileHandleCache.contains(fileHandle)) { 230 caseHandlesCache.get(caseDbPointer).fileHandleCache.remove(fileHandle); 231 return; 232 } 233 } 234 } 235 } 236 } 237 238 /** 239 * Searches all the open caches for a file handle. 240 * 241 * @param fileHandle 242 * 243 * @return true if the handle is found in any cache, false otherwise 244 */ isValidFileHandle(long fileHandle)245 private static boolean isValidFileHandle(long fileHandle) { 246 synchronized (cacheLock) { 247 for (long caseDbPointer:caseHandlesCache.keySet()) { 248 if (caseHandlesCache.get(caseDbPointer).fileHandleCache.contains(fileHandle)) { 249 return true; 250 } 251 } 252 return false; 253 } 254 } 255 closeHandlesAndClearCache(long caseDbPointer)256 private static void closeHandlesAndClearCache(long caseDbPointer) throws TskCoreException { 257 synchronized (cacheLock) { 258 /* 259 * Close any cached file system handles. 260 */ 261 for (Map<Long, Long> imageToFsMap : getCaseHandles(caseDbPointer).fsHandleCache.values()) { 262 for (Long fsHandle : imageToFsMap.values()) { 263 // First close all open file handles for the file system. 264 if (getCaseHandles(caseDbPointer).fileSystemToFileHandles.containsKey(fsHandle)) { 265 for (Long fileHandle : getCaseHandles(caseDbPointer).fileSystemToFileHandles.get(fsHandle)) { 266 closeFile(fileHandle); 267 } 268 } 269 // Then close the file system handle. 270 closeFsNat(fsHandle); 271 } 272 } 273 274 /* 275 * Close any cached image handles. 276 */ 277 for (Long imageHandle : getCaseHandles(caseDbPointer).imageHandleCache.values()) { 278 closeImgNat(imageHandle); 279 } 280 281 removeCaseHandlesCache(caseDbPointer); 282 } 283 284 } 285 } 286 287 /** 288 * Encapsulates a handle to a SleuthKit case database with support for 289 * adding images to the database. 290 */ 291 public static class CaseDbHandle { 292 293 /* 294 * A pointer to a TskCaseDb object. 295 */ 296 private final long caseDbPointer; 297 298 /** 299 * Constructs an object that encapsulates a handle to a SleuthKit case 300 * database with support for adding images to the database. 301 * 302 * @param caseDbPointer A pointer to a TskCaseDb object. 303 */ CaseDbHandle(long caseDbPointer)304 private CaseDbHandle(long caseDbPointer) { 305 this.caseDbPointer = caseDbPointer; 306 HandleCache.createCaseHandleCache(caseDbPointer); 307 } 308 309 /** 310 * Closes the case database and any open image and file system handles. 311 * 312 * @throws TskCoreException if there is a problem competing the 313 * operation. 314 */ free()315 void free() throws TskCoreException { 316 tskLock.writeLock().lock(); 317 try { 318 HandleCache.closeHandlesAndClearCache(caseDbPointer); 319 SleuthkitJNI.closeCaseDbNat(caseDbPointer); 320 } finally { 321 tskLock.writeLock().unlock(); 322 } 323 } 324 325 /** 326 * Adds an image to the case database. For finer-grained control of the 327 * process of adding the image, call CaseDbHandle.initAddImageProcess 328 * instead. 329 * 330 * @param deviceObjId The object id of the device associated with 331 * the image. 332 * @param imageFilePaths The image file paths. 333 * @param timeZone The time zone for the image. 334 * @param addFileSystems Pass true to attempt to add file systems 335 * within the image to the case database. 336 * @param addUnallocSpace Pass true to create virtual files for 337 * unallocated space. Ignored if addFileSystems 338 * is false. 339 * @param skipFatFsOrphans Pass true to skip processing of orphan files 340 * for FAT file systems. Ignored if 341 * addFileSystems is false. 342 * 343 * @return The object id of the image. 344 * 345 * @throws TskCoreException if there is an error adding the image to 346 * case database. 347 */ addImageInfo(long deviceObjId, List<String> imageFilePaths, String timeZone, SleuthkitCase skCase)348 long addImageInfo(long deviceObjId, List<String> imageFilePaths, String timeZone, SleuthkitCase skCase) throws TskCoreException { 349 try { 350 long tskAutoDbPointer = initializeAddImgNat(caseDbPointer, timezoneLongToShort(timeZone), false, false, false); 351 runOpenAndAddImgNat(tskAutoDbPointer, UUID.randomUUID().toString(), imageFilePaths.toArray(new String[0]), imageFilePaths.size(), timeZone); 352 long id = commitAddImgNat(tskAutoDbPointer); 353 skCase.addDataSourceToHasChildrenMap(); 354 return id; 355 } catch (TskDataException ex) { 356 throw new TskCoreException("Error adding image to case database", ex); 357 } 358 } 359 360 /** 361 * Initializes a multi-step process for adding an image to the case 362 * database. 363 * 364 * @param timeZone The time zone of the image. 365 * @param addUnallocSpace Pass true to create virtual files for 366 * unallocated space. 367 * @param skipFatFsOrphans Pass true to skip processing of orphan files 368 * for FAT file systems. 369 * @param imageCopyPath Path to which a copy of the image should be 370 * written. Use the empty string to disable 371 * image writing. 372 * 373 * @return An object that can be used to exercise fine-grained control 374 * of the process of adding the image to the case database. 375 */ initAddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFatFsOrphans, String imageCopyPath, SleuthkitCase skCase)376 AddImageProcess initAddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFatFsOrphans, String imageCopyPath, SleuthkitCase skCase) { 377 return new AddImageProcess(timeZone, addUnallocSpace, skipFatFsOrphans, imageCopyPath, skCase); 378 } 379 380 /** 381 * Encapsulates a multi-step process to add an image to the case 382 * database. 383 */ 384 public class AddImageProcess { 385 386 private final String timeZone; 387 private final boolean addUnallocSpace; 388 private final boolean skipFatFsOrphans; 389 private final String imageWriterPath; 390 private volatile long tskAutoDbPointer; 391 private boolean isCanceled; 392 private final SleuthkitCase skCase; 393 394 /** 395 * Constructs an object that encapsulates a multi-step process to 396 * add an image to the case database. 397 * 398 * @param timeZone The time zone of the image. 399 * @param addUnallocSpace Pass true to create virtual files for 400 * unallocated space. 401 * @param skipFatFsOrphans Pass true to skip processing of orphan 402 * files for FAT file systems. 403 * @param imageWriterPath Path that a copy of the image should be 404 * written to. Use empty string to disable 405 * image writing 406 */ AddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFatFsOrphans, String imageWriterPath, SleuthkitCase skCase)407 private AddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFatFsOrphans, String imageWriterPath, SleuthkitCase skCase) { 408 this.timeZone = timeZone; 409 this.addUnallocSpace = addUnallocSpace; 410 this.skipFatFsOrphans = skipFatFsOrphans; 411 this.imageWriterPath = imageWriterPath; 412 tskAutoDbPointer = 0; 413 this.isCanceled = false; 414 this.skCase = skCase; 415 } 416 417 /** 418 * Starts the process of adding an image to the case database. 419 * Either AddImageProcess.commit or AddImageProcess.revert MUST be 420 * called after calling AddImageProcess.run. 421 * 422 * @param deviceId An ASCII-printable identifier for the 423 * device associated with the image that 424 * should be unique across multiple cases 425 * (e.g., a UUID). 426 * @param imageFilePaths Full path(s) to the image file(s). 427 * @param sectorSize The sector size (use '0' for autodetect). 428 * 429 * @throws TskCoreException if a critical error occurs within the 430 * SleuthKit. 431 * @throws TskDataException if a non-critical error occurs within 432 * the SleuthKit (should be OK to continue 433 * the process) 434 */ run(String deviceId, String[] imageFilePaths, int sectorSize)435 public void run(String deviceId, String[] imageFilePaths, int sectorSize) throws TskCoreException, TskDataException { 436 getTSKReadLock(); 437 try { 438 long imageHandle = 0; 439 440 synchronized (this) { 441 if (0 != tskAutoDbPointer) { 442 throw new TskCoreException("Add image process already started"); 443 } 444 if (!isCanceled) { //with isCanceled being guarded by this it will have the same value everywhere in this synchronized block 445 imageHandle = openImage(imageFilePaths, sectorSize, false, caseDbPointer); 446 tskAutoDbPointer = initAddImgNat(caseDbPointer, timezoneLongToShort(timeZone), addUnallocSpace, skipFatFsOrphans); 447 } 448 if (0 == tskAutoDbPointer) { 449 throw new TskCoreException("initAddImgNat returned a NULL TskAutoDb pointer"); 450 } 451 } 452 if (imageHandle != 0) { 453 runAddImgNat(tskAutoDbPointer, deviceId, imageHandle, timeZone, imageWriterPath); 454 } 455 } finally { 456 releaseTSKReadLock(); 457 } 458 } 459 460 /** 461 * Stops the process of adding the image to the case database that 462 * was started by calling AddImageProcess.run. 463 * AddImageProcess.revert should be called after calling 464 * AddImageProcess.stop. 465 * 466 * @throws TskCoreException if a critical error occurs within the 467 * SleuthKit. 468 */ stop()469 public synchronized void stop() throws TskCoreException { 470 getTSKReadLock(); 471 try { 472 isCanceled = true; 473 if (tskAutoDbPointer != 0) { 474 stopAddImgNat(tskAutoDbPointer); 475 } 476 } finally { 477 releaseTSKReadLock(); 478 } 479 } 480 481 /** 482 * Rolls back the process of adding an image to the case database 483 * that was started by calling AddImageProcess.run. 484 * 485 * @throws TskCoreException if a critical error occurs within the 486 * SleuthKit. 487 */ revert()488 public synchronized void revert() throws TskCoreException { 489 getTSKReadLock(); 490 try { 491 if (tskAutoDbPointer == 0) { 492 throw new TskCoreException("AddImgProcess::revert: AutoDB pointer is NULL"); 493 } 494 495 revertAddImgNat(tskAutoDbPointer); 496 // the native code deleted the object 497 tskAutoDbPointer = 0; 498 } finally { 499 releaseTSKReadLock(); 500 } 501 } 502 503 /** 504 * Completes the process of adding an image to the case database 505 * that was started by calling AddImageProcess.run. 506 * 507 * @return The object id of the image that was added. 508 * 509 * @throws TskCoreException if a critical error occurs within the 510 * SleuthKit. 511 */ commit()512 public synchronized long commit() throws TskCoreException { 513 getTSKReadLock(); 514 try { 515 if (tskAutoDbPointer == 0) { 516 throw new TskCoreException("AddImgProcess::commit: AutoDB pointer is NULL"); 517 } 518 519 long id = commitAddImgNat(tskAutoDbPointer); 520 521 skCase.addDataSourceToHasChildrenMap(); 522 523 // the native code deleted the object 524 tskAutoDbPointer = 0; 525 return id; 526 } finally { 527 releaseTSKReadLock(); 528 } 529 } 530 531 /** 532 * Gets the file system directory currently being processed by the 533 * SleuthKit. 534 * 535 * @return The directory 536 */ currentDirectory()537 public synchronized String currentDirectory() { 538 return tskAutoDbPointer == 0 ? "" : getCurDirNat(tskAutoDbPointer); //NON-NLS 539 } 540 541 /** 542 * Starts the process of adding an image to the case database. 543 * Either commit() or revert() MUST be called after calling run(). 544 * 545 * @param imageFilePaths Full path(s) to the image file(s). 546 * 547 * @throws TskCoreException if a critical error occurs within the 548 * SleuthKit. 549 * @throws TskDataException if a non-critical error occurs within 550 * the SleuthKit (should be OK to continue 551 * the process) 552 * 553 * @deprecated Use run(String dataSourceId, String[] imageFilePaths) 554 * instead 555 */ 556 @Deprecated run(String[] imageFilePaths)557 public void run(String[] imageFilePaths) throws TskCoreException, TskDataException { 558 run(null, imageFilePaths, 0); 559 } 560 561 /** 562 * Starts the process of adding an image to the case database. 563 * Either AddImageProcess.commit or AddImageProcess.revert MUST be 564 * called after calling AddImageProcess.run. 565 * 566 * @param deviceId An ASCII-printable identifier for the 567 * device associated with the image that 568 * should be unique across multiple cases 569 * (e.g., a UUID). 570 * @param imageFilePaths Full path(s) to the image file(s). 571 * 572 * @throws TskCoreException if a critical error occurs within the 573 * SleuthKit. 574 * @throws TskDataException if a non-critical error occurs within 575 * the SleuthKit (should be OK to continue 576 * the process) 577 */ run(String deviceId, String[] imageFilePaths)578 public void run(String deviceId, String[] imageFilePaths) throws TskCoreException, TskDataException { 579 run(deviceId, imageFilePaths, 0); 580 } 581 } 582 583 } 584 585 /** 586 * Creates a new case database. Must call .free() on CaseDbHandle instance 587 * when done. 588 * 589 * @param path Location to create the database at. 590 * 591 * @return Handle for a new TskCaseDb instance. 592 * 593 * @throws TskCoreException exception thrown if critical error occurs within 594 * TSK 595 */ newCaseDb(String path)596 static CaseDbHandle newCaseDb(String path) throws TskCoreException { 597 return new CaseDbHandle(newCaseDbNat(path)); 598 } 599 600 /** 601 * Creates a new case database. Must call .free() on CaseDbHandle instance 602 * when done. 603 * 604 * @param databaseName the name of the database to create 605 * @param info the connection info class for the database to create 606 * 607 * @return Handle for a new TskCaseDb instance. 608 * 609 * @throws TskCoreException exception thrown if critical error occurs within 610 * TSK 611 */ newCaseDb(String databaseName, CaseDbConnectionInfo info)612 static CaseDbHandle newCaseDb(String databaseName, CaseDbConnectionInfo info) throws TskCoreException { 613 return new CaseDbHandle(newCaseDbMultiNat(info.getHost(), info.getPort(), info.getUserName(), info.getPassword(), info.getDbType().ordinal(), databaseName)); 614 } 615 616 /** 617 * Opens an existing case database. Must call .free() on CaseDbHandle 618 * instance when done. 619 * 620 * @param path Location of the existing database. 621 * 622 * @return Handle for a new TskCaseDb instance. 623 * 624 * @throws TskCoreException exception thrown if critical error occurs within 625 * TSK 626 */ openCaseDb(String path)627 static CaseDbHandle openCaseDb(String path) throws TskCoreException { 628 return new CaseDbHandle(openCaseDbNat(path)); 629 } 630 631 /** 632 * Opens an existing case database. Must call .free() on CaseDbHandle 633 * instance when done. 634 * 635 * @param databaseName the name of the database to open 636 * @param info the connection info class for the database to open 637 * 638 * @return Handle for a new TskCaseDb instance. 639 * 640 * @throws TskCoreException exception thrown if critical error occurs within 641 * TSK 642 */ openCaseDb(String databaseName, CaseDbConnectionInfo info)643 static CaseDbHandle openCaseDb(String databaseName, CaseDbConnectionInfo info) throws TskCoreException { 644 return new CaseDbHandle(openCaseDbMultiNat(info.getHost(), info.getPort(), info.getUserName(), info.getPassword(), info.getDbType().ordinal(), databaseName)); 645 } 646 647 /** 648 * get the Sleuth Kit version string 649 * 650 * @return the version string 651 */ getVersion()652 public static String getVersion() { 653 return getVersionNat(); 654 } 655 656 /** 657 * Enable verbose logging and redirect stderr to the given log file. 658 * 659 * @param logPath the log file path 660 */ startVerboseLogging(String logPath)661 public static void startVerboseLogging(String logPath) { 662 startVerboseLoggingNat(logPath); 663 } 664 665 /** 666 * Open the image and return the image info pointer. 667 * 668 * @param imageFiles the paths to the images 669 * @param skCase the case this image belongs to 670 * 671 * @return the image info pointer 672 * 673 * @throws TskCoreException exception thrown if critical error occurs within 674 * TSK 675 */ openImage(String[] imageFiles, SleuthkitCase skCase)676 public static long openImage(String[] imageFiles, SleuthkitCase skCase) throws TskCoreException { 677 if (skCase == null) { 678 throw new TskCoreException("SleuthkitCase can not be null"); 679 } 680 return openImage(imageFiles, 0, true, skCase.getCaseHandle().caseDbPointer); 681 } 682 683 /** 684 * Open the image with a specified sector size and return the image info 685 * pointer. 686 * 687 * @param imageFiles the paths to the images 688 * @param sSize the sector size (use '0' for autodetect) 689 * @param skCase the case this image belongs to 690 * 691 * @return the image info pointer 692 * 693 * @throws TskCoreException exception thrown if critical error occurs within 694 * TSK 695 */ openImage(String[] imageFiles, int sSize, SleuthkitCase skCase)696 public static long openImage(String[] imageFiles, int sSize, SleuthkitCase skCase) throws TskCoreException { 697 if (skCase == null) { 698 throw new TskCoreException("SleuthkitCase can not be null"); 699 } 700 return openImage(imageFiles, sSize, true, skCase.getCaseHandle().caseDbPointer); 701 } 702 703 /** 704 * Open the image and return the image info pointer. This is a temporary 705 * measure to allow ingest of multiple local disks on the same drive letter. 706 * We need to clear the cache to make sure cached data from the first drive 707 * is not used. 708 * 709 * @param imageFiles the paths to the images 710 * @param sSize the sector size (use '0' for autodetect) 711 * @param useCache true if the image handle cache should be used, false to 712 * always go to TSK to open a fresh copy 713 * @param caseDbPointer The caseDbPointer for this case. Can be null to support deprecated methods. 714 * 715 * @return the image info pointer 716 * 717 * @throws TskCoreException exception thrown if critical error occurs within 718 * TSK 719 */ openImage(String[] imageFiles, int sSize, boolean useCache, Long caseDbPointer)720 private static long openImage(String[] imageFiles, int sSize, boolean useCache, Long caseDbPointer) throws TskCoreException { 721 722 getTSKReadLock(); 723 try { 724 long imageHandle; 725 726 StringBuilder keyBuilder = new StringBuilder(); 727 for (int i = 0; i < imageFiles.length; ++i) { 728 keyBuilder.append(imageFiles[i]); 729 } 730 final String imageKey = keyBuilder.toString(); 731 732 synchronized (HandleCache.cacheLock) { 733 Long nonNullCaseDbPointer = caseDbPointer; 734 if (nonNullCaseDbPointer == null) { 735 nonNullCaseDbPointer = HandleCache.getDefaultCaseDbPointer(); 736 } 737 738 // If we're getting a fresh copy, remove any existing cache references 739 if (!useCache && HandleCache.getCaseHandles(nonNullCaseDbPointer).imageHandleCache.containsKey(imageKey)) { 740 long tempImageHandle = HandleCache.getCaseHandles(nonNullCaseDbPointer).imageHandleCache.get(imageKey); 741 HandleCache.getCaseHandles(nonNullCaseDbPointer).fsHandleCache.remove(tempImageHandle); 742 HandleCache.getCaseHandles(nonNullCaseDbPointer).imageHandleCache.remove(imageKey); 743 } 744 745 if (useCache && HandleCache.getCaseHandles(nonNullCaseDbPointer).imageHandleCache.containsKey(imageKey)) //get from cache 746 { 747 imageHandle = HandleCache.getCaseHandles(nonNullCaseDbPointer).imageHandleCache.get(imageKey); 748 } else { 749 //open new handle and cache it 750 imageHandle = openImgNat(imageFiles, imageFiles.length, sSize); 751 HandleCache.getCaseHandles(nonNullCaseDbPointer).fsHandleCache.put(imageHandle, new HashMap<Long, Long>()); 752 HandleCache.getCaseHandles(nonNullCaseDbPointer).imageHandleCache.put(imageKey, imageHandle); 753 } 754 } 755 return imageHandle; 756 } finally { 757 releaseTSKReadLock(); 758 } 759 } 760 761 /** 762 * Get volume system Handle 763 * 764 * @param imgHandle a handle to previously opened image 765 * @param vsOffset byte offset in the image to the volume system (usually 766 * 0) 767 * 768 * @return pointer to a vsHandle structure in the sleuthkit 769 * 770 * @throws TskCoreException exception thrown if critical error occurs within 771 * TSK 772 */ openVs(long imgHandle, long vsOffset)773 public static long openVs(long imgHandle, long vsOffset) throws TskCoreException { 774 getTSKReadLock(); 775 try { 776 if(! imgHandleIsValid(imgHandle)) { 777 throw new TskCoreException("Image handle " + imgHandle + " is closed"); 778 } 779 return openVsNat(imgHandle, vsOffset); 780 } finally { 781 releaseTSKReadLock(); 782 } 783 } 784 785 //get pointers 786 /** 787 * Get volume Handle 788 * 789 * @param vsHandle pointer to the volume system structure in the sleuthkit 790 * @param volId id of the volume 791 * 792 * @return pointer to a volHandle structure in the sleuthkit 793 * 794 * @throws TskCoreException exception thrown if critical error occurs within 795 * TSK 796 */ openVsPart(long vsHandle, long volId)797 public static long openVsPart(long vsHandle, long volId) throws TskCoreException { 798 getTSKReadLock(); 799 try { 800 //returned long is ptr to vs Handle object in tsk 801 return openVolNat(vsHandle, volId); 802 } finally { 803 releaseTSKReadLock(); 804 } 805 } 806 807 /** 808 * Get file system Handle Opened handle is cached (transparently) so it does 809 * not need be reopened next time for the duration of the application 810 * 811 * @param imgHandle pointer to imgHandle in sleuthkit 812 * @param fsOffset byte offset to the file system 813 * @param skCase the case containing the file system 814 * 815 * @return pointer to a fsHandle structure in the sleuthkit 816 * 817 * @throws TskCoreException exception thrown if critical error occurs within 818 * TSK 819 */ openFs(long imgHandle, long fsOffset, SleuthkitCase skCase)820 public static long openFs(long imgHandle, long fsOffset, SleuthkitCase skCase) throws TskCoreException { 821 getTSKReadLock(); 822 try { 823 long fsHandle; 824 synchronized (HandleCache.cacheLock) { 825 long caseDbPointer; 826 if (skCase == null) { 827 caseDbPointer = HandleCache.getDefaultCaseDbPointer(); 828 } else { 829 caseDbPointer = skCase.getCaseHandle().caseDbPointer; 830 } 831 final Map<Long, Long> imgOffSetToFsHandle = HandleCache.getCaseHandles(caseDbPointer).fsHandleCache.get(imgHandle); 832 if (imgOffSetToFsHandle == null) { 833 throw new TskCoreException("Missing image offset to file system handle cache for image handle " + imgHandle); 834 } 835 if (imgOffSetToFsHandle.containsKey(fsOffset)) { 836 //return cached 837 fsHandle = imgOffSetToFsHandle.get(fsOffset); 838 } else { 839 fsHandle = openFsNat(imgHandle, fsOffset); 840 //cache it 841 imgOffSetToFsHandle.put(fsOffset, fsHandle); 842 } 843 } 844 return fsHandle; 845 } finally { 846 releaseTSKReadLock(); 847 } 848 } 849 850 /** 851 * Get file Handle 852 * 853 * @param fsHandle fsHandle pointer in the sleuthkit 854 * @param fileId id of the file 855 * @param attrType file attribute type to open 856 * @param attrId file attribute id to open 857 * @param skCase the case associated with this file 858 * 859 * @return pointer to a file structure in the sleuthkit 860 * 861 * @throws TskCoreException exception thrown if critical error occurs within 862 * TSK 863 */ openFile(long fsHandle, long fileId, TSK_FS_ATTR_TYPE_ENUM attrType, int attrId, SleuthkitCase skCase)864 public static long openFile(long fsHandle, long fileId, TSK_FS_ATTR_TYPE_ENUM attrType, int attrId, SleuthkitCase skCase) throws TskCoreException { 865 /* 866 * NOTE: previously attrId used to be stored in AbstractFile as (signed) 867 * short even though it is stored as uint16 in TSK. In extremely rare 868 * occurrences attrId can be larger than what a signed short can hold 869 * (2^15). Changes were made to AbstractFile to store attrId as integer. 870 * However, a depricated method still exists in AbstractFile to get 871 * attrId as short. In that method we convert attribute ids that are 872 * larger than 32K to a negative number. Therefore if encountered, we 873 * need to convert negative attribute id to uint16 which is what TSK is 874 * using to store attribute id. 875 */ 876 getTSKReadLock(); 877 try { 878 long fileHandle = openFileNat(fsHandle, fileId, attrType.getValue(), convertSignedToUnsigned(attrId)); 879 synchronized (HandleCache.cacheLock) { 880 long caseDbPointer; 881 if (skCase == null) { 882 caseDbPointer = HandleCache.getDefaultCaseDbPointer(); 883 } else { 884 caseDbPointer = skCase.getCaseHandle().caseDbPointer; 885 } 886 HandleCache.addFileHandle(caseDbPointer, fileHandle, fsHandle); 887 } 888 return fileHandle; 889 } finally { 890 releaseTSKReadLock(); 891 } 892 } 893 894 /** 895 * Converts signed integer to an unsigned integer. 896 * 897 * @param val value to be converter 898 * 899 * @return unsigned integer value 900 */ convertSignedToUnsigned(int val)901 private static int convertSignedToUnsigned(int val) { 902 if (val >= 0) { 903 return val; 904 } 905 906 return val & 0xffff; // convert negative value to positive value 907 } 908 909 /** 910 * Test that the given image handle is valid. 911 * @param imgHandle 912 * @return true if it is valid, false otherwise 913 */ imgHandleIsValid(long imgHandle)914 private static boolean imgHandleIsValid(long imgHandle) { 915 synchronized(HandleCache.cacheLock) { 916 return HandleCache.isImageInAnyCache(imgHandle); 917 } 918 } 919 920 //do reads 921 /** 922 * reads data from an image 923 * 924 * @param imgHandle 925 * @param readBuffer buffer to read to 926 * @param offset byte offset in the image to start at 927 * @param len amount of data to read 928 * 929 * @return the number of characters read, or -1 if the end of the stream has 930 * been reached 931 * 932 * @throws TskCoreException exception thrown if critical error occurs within 933 * TSK 934 */ readImg(long imgHandle, byte[] readBuffer, long offset, long len)935 public static int readImg(long imgHandle, byte[] readBuffer, long offset, long len) throws TskCoreException { 936 getTSKReadLock(); 937 try { 938 if(! imgHandleIsValid(imgHandle)) { 939 throw new TskCoreException("Image handle " + imgHandle + " is closed"); 940 } 941 //returned byte[] is the data buffer 942 return readImgNat(imgHandle, readBuffer, offset, len); 943 } finally { 944 releaseTSKReadLock(); 945 } 946 } 947 948 /** 949 * reads data from an volume system 950 * 951 * @param vsHandle pointer to a volume system structure in the sleuthkit 952 * @param readBuffer buffer to read to 953 * @param offset sector offset in the image to start at 954 * @param len amount of data to read 955 * 956 * @return the number of characters read, or -1 if the end of the stream has 957 * been reached 958 * 959 * @throws TskCoreException exception thrown if critical error occurs within 960 * TSK 961 */ readVs(long vsHandle, byte[] readBuffer, long offset, long len)962 public static int readVs(long vsHandle, byte[] readBuffer, long offset, long len) throws TskCoreException { 963 getTSKReadLock(); 964 try { 965 return readVsNat(vsHandle, readBuffer, offset, len); 966 } finally { 967 releaseTSKReadLock(); 968 } 969 } 970 971 /** 972 * reads data from an volume 973 * 974 * @param volHandle pointer to a volume structure in the sleuthkit 975 * @param readBuffer buffer to read to 976 * @param offset byte offset in the image to start at 977 * @param len amount of data to read 978 * 979 * @return the number of characters read, or -1 if the end of the stream has 980 * been reached 981 * 982 * @throws TskCoreException exception thrown if critical error occurs within 983 * TSK 984 */ readVsPart(long volHandle, byte[] readBuffer, long offset, long len)985 public static int readVsPart(long volHandle, byte[] readBuffer, long offset, long len) throws TskCoreException { 986 getTSKReadLock(); 987 try { 988 //returned byte[] is the data buffer 989 return readVolNat(volHandle, readBuffer, offset, len); 990 } finally { 991 releaseTSKReadLock(); 992 } 993 } 994 995 /** 996 * reads data from an file system 997 * 998 * @param fsHandle pointer to a file system structure in the sleuthkit 999 * @param readBuffer buffer to read to 1000 * @param offset byte offset in the image to start at 1001 * @param len amount of data to read 1002 * 1003 * @return the number of characters read, or -1 if the end of the stream has 1004 * been reached 1005 * 1006 * @throws TskCoreException exception thrown if critical error occurs within 1007 * TSK 1008 */ readFs(long fsHandle, byte[] readBuffer, long offset, long len)1009 public static int readFs(long fsHandle, byte[] readBuffer, long offset, long len) throws TskCoreException { 1010 getTSKReadLock(); 1011 try { 1012 //returned byte[] is the data buffer 1013 return readFsNat(fsHandle, readBuffer, offset, len); 1014 } finally { 1015 releaseTSKReadLock(); 1016 } 1017 } 1018 1019 /** 1020 * enum used to tell readFileNat whether the offset is from the beginning of 1021 * the file or from the beginning of the slack space. 1022 */ 1023 private enum TSK_FS_FILE_READ_OFFSET_TYPE_ENUM { 1024 START_OF_FILE(0), 1025 START_OF_SLACK(1); 1026 1027 private final int val; 1028 TSK_FS_FILE_READ_OFFSET_TYPE_ENUM(int val)1029 TSK_FS_FILE_READ_OFFSET_TYPE_ENUM(int val) { 1030 this.val = val; 1031 } 1032 getValue()1033 int getValue() { 1034 return val; 1035 } 1036 } 1037 1038 /** 1039 * reads data from an file 1040 * 1041 * @param fileHandle pointer to a file structure in the sleuthkit 1042 * @param readBuffer pre-allocated buffer to read to 1043 * @param offset byte offset in the image to start at 1044 * @param len amount of data to read 1045 * 1046 * @return the number of characters read, or -1 if the end of the stream has 1047 * been reached 1048 * 1049 * @throws TskCoreException exception thrown if critical error occurs within 1050 * TSK 1051 */ readFile(long fileHandle, byte[] readBuffer, long offset, long len)1052 public static int readFile(long fileHandle, byte[] readBuffer, long offset, long len) throws TskCoreException { 1053 getTSKReadLock(); 1054 try { 1055 if (!HandleCache.isValidFileHandle(fileHandle)) { 1056 throw new TskCoreException(HandleCache.INVALID_FILE_HANDLE); 1057 } 1058 1059 return readFileNat(fileHandle, readBuffer, offset, TSK_FS_FILE_READ_OFFSET_TYPE_ENUM.START_OF_FILE.getValue(), len); 1060 } finally { 1061 releaseTSKReadLock(); 1062 } 1063 } 1064 1065 /** 1066 * reads data from the slack space of a file 1067 * 1068 * @param fileHandle pointer to a file structure in the sleuthkit 1069 * @param readBuffer pre-allocated buffer to read to 1070 * @param offset byte offset in the slack to start at 1071 * @param len amount of data to read 1072 * 1073 * @return the number of characters read, or -1 if the end of the stream has 1074 * been reached 1075 * 1076 * @throws TskCoreException exception thrown if critical error occurs within 1077 * TSK 1078 */ readFileSlack(long fileHandle, byte[] readBuffer, long offset, long len)1079 public static int readFileSlack(long fileHandle, byte[] readBuffer, long offset, long len) throws TskCoreException { 1080 getTSKReadLock(); 1081 try { 1082 if (!HandleCache.isValidFileHandle(fileHandle)) { 1083 throw new TskCoreException(HandleCache.INVALID_FILE_HANDLE); 1084 } 1085 1086 return readFileNat(fileHandle, readBuffer, offset, TSK_FS_FILE_READ_OFFSET_TYPE_ENUM.START_OF_SLACK.getValue(), len); 1087 } finally { 1088 releaseTSKReadLock(); 1089 } 1090 } 1091 1092 /** 1093 * Get human readable (some what) details about a file. This is the same as 1094 * the 'istat' TSK tool 1095 * 1096 * @param fileHandle pointer to file structure in the sleuthkit 1097 * 1098 * @return text 1099 * 1100 * @throws TskCoreException if errors occurred 1101 */ getFileMetaDataText(long fileHandle)1102 public static List<String> getFileMetaDataText(long fileHandle) throws TskCoreException { 1103 getTSKReadLock(); 1104 try { 1105 if (!HandleCache.isValidFileHandle(fileHandle)) { 1106 throw new TskCoreException(HandleCache.INVALID_FILE_HANDLE); 1107 } 1108 1109 try { 1110 java.io.File tmp = java.io.File.createTempFile("tsk", ".txt"); 1111 1112 saveFileMetaDataTextNat(fileHandle, tmp.getAbsolutePath()); 1113 1114 FileReader fr = new FileReader(tmp.getAbsolutePath()); 1115 BufferedReader textReader = new BufferedReader(fr); 1116 1117 List<String> lines = new ArrayList<String>(); 1118 while (true) { 1119 String line = textReader.readLine(); 1120 if (line == null) { 1121 break; 1122 } 1123 lines.add(line); 1124 } 1125 textReader.close(); 1126 fr.close(); 1127 tmp.delete(); 1128 return lines; 1129 } catch (IOException ex) { 1130 throw new TskCoreException("Error reading istat output: " + ex.getLocalizedMessage()); 1131 } 1132 } finally { 1133 releaseTSKReadLock(); 1134 } 1135 } 1136 1137 /** 1138 * frees the fileHandle pointer 1139 * 1140 * @param fileHandle pointer to file structure in sleuthkit 1141 */ closeFile(long fileHandle)1142 public static void closeFile(long fileHandle) { 1143 closeFile(fileHandle, null); 1144 } 1145 1146 /** 1147 * frees the fileHandle pointer 1148 * 1149 * @param fileHandle pointer to file structure in sleuthkit 1150 * @param skCase the case containing the file 1151 */ closeFile(long fileHandle, SleuthkitCase skCase)1152 public static void closeFile(long fileHandle, SleuthkitCase skCase) { 1153 getTSKReadLock(); 1154 try { 1155 synchronized (HandleCache.cacheLock) { 1156 if (!HandleCache.isValidFileHandle(fileHandle)) { 1157 // File handle is not open so this is a no-op. 1158 return; 1159 } 1160 closeFileNat(fileHandle); 1161 HandleCache.removeFileHandle(fileHandle, skCase); 1162 } 1163 } finally { 1164 releaseTSKReadLock(); 1165 } 1166 } 1167 1168 /** 1169 * Create an index for a hash database. 1170 * 1171 * @param dbHandle A hash database handle. 1172 * 1173 * @throws TskCoreException if a critical error occurs within TSK core 1174 */ createLookupIndexForHashDatabase(int dbHandle)1175 public static void createLookupIndexForHashDatabase(int dbHandle) throws TskCoreException { 1176 hashDbCreateIndexNat(dbHandle); 1177 } 1178 1179 /** 1180 * Check if an index exists for a hash database. 1181 * 1182 * @param dbHandle A hash database handle. 1183 * 1184 * @return true if index exists 1185 * 1186 * @throws TskCoreException if a critical error occurs within TSK core 1187 */ hashDatabaseHasLookupIndex(int dbHandle)1188 public static boolean hashDatabaseHasLookupIndex(int dbHandle) throws TskCoreException { 1189 return hashDbIndexExistsNat(dbHandle); 1190 } 1191 1192 /** 1193 * hashDatabaseCanBeReindexed 1194 * 1195 * @param dbHandle previously opened hash db handle 1196 * 1197 * @return Does this database have a source database that is different than 1198 * the index? 1199 * 1200 * @throws TskCoreException if a critical error occurs within TSK core 1201 */ hashDatabaseCanBeReindexed(int dbHandle)1202 public static boolean hashDatabaseCanBeReindexed(int dbHandle) throws TskCoreException { 1203 return hashDbIsReindexableNat(dbHandle); 1204 } 1205 1206 /** 1207 * getHashDatabasePath 1208 * 1209 * @param dbHandle previously opened hash db handle 1210 * 1211 * @return Hash db file path 1212 * 1213 * @throws TskCoreException if a critical error occurs within TSK core 1214 */ getHashDatabasePath(int dbHandle)1215 public static String getHashDatabasePath(int dbHandle) throws TskCoreException { 1216 return hashDbPathNat(dbHandle); 1217 } 1218 1219 /** 1220 * getHashDatabaseIndexPath 1221 * 1222 * @param dbHandle previously opened hash db handle 1223 * 1224 * @return Index file path 1225 * 1226 * @throws TskCoreException if a critical error occurs within TSK core 1227 */ getHashDatabaseIndexPath(int dbHandle)1228 public static String getHashDatabaseIndexPath(int dbHandle) throws TskCoreException { 1229 return hashDbIndexPathNat(dbHandle); 1230 } 1231 1232 /** 1233 * Open a hash database for lookups 1234 * @param path Path to Hash DB or index file 1235 * @return Handle open db 1236 * @throws TskCoreException if there is an error opening the DB 1237 */ openHashDatabase(String path)1238 public static int openHashDatabase(String path) throws TskCoreException { 1239 return hashDbOpenNat(path); 1240 } 1241 1242 /** 1243 * Creates a hash database. Will be of the default TSK hash database type. 1244 * 1245 * @param path The path to the database 1246 * 1247 * @return a handle for that database 1248 * 1249 * @throws TskCoreException if a critical error occurs within TSK core 1250 */ createHashDatabase(String path)1251 public static int createHashDatabase(String path) throws TskCoreException { 1252 return hashDbNewNat(path); 1253 } 1254 1255 /** 1256 * Close the currently open lookup databases. Resets the handle counting. 1257 * 1258 * @throws TskCoreException exception thrown if critical error occurs within 1259 * TSK 1260 */ closeAllHashDatabases()1261 public static void closeAllHashDatabases() throws TskCoreException { 1262 hashDbCloseAll(); 1263 } 1264 1265 /** 1266 * Close a particular open lookup database. Existing handles are not 1267 * affected. 1268 * 1269 * @param dbHandle Handle of database to close. 1270 * 1271 * @throws TskCoreException exception thrown if critical error occurs within 1272 * TSK 1273 */ closeHashDatabase(int dbHandle)1274 public static void closeHashDatabase(int dbHandle) throws TskCoreException { 1275 hashDbClose(dbHandle); 1276 } 1277 1278 /** 1279 * Get the name of the database 1280 * 1281 * @param dbHandle Previously opened hash db handle. 1282 * 1283 * @return The display name. 1284 * 1285 * @throws TskCoreException if a critical error occurs within TSK core 1286 */ getHashDatabaseDisplayName(int dbHandle)1287 public static String getHashDatabaseDisplayName(int dbHandle) throws TskCoreException { 1288 return hashDbGetDisplayName(dbHandle); 1289 } 1290 1291 /** 1292 * Lookup the given hash value and get basic answer 1293 * 1294 * @param hash Hash value to search for. 1295 * @param dbHandle Handle of database to lookup in. 1296 * 1297 * @return True if hash was found in database. 1298 * 1299 * @throws TskCoreException 1300 */ lookupInHashDatabase(String hash, int dbHandle)1301 public static boolean lookupInHashDatabase(String hash, int dbHandle) throws TskCoreException { 1302 return hashDbLookup(hash, dbHandle); 1303 } 1304 1305 /** 1306 * Lookup hash value in DB and return details on results (more time 1307 * consuming than basic lookup) 1308 * 1309 * @param hash Hash value to search for 1310 * @param dbHandle Handle of database to lookup in. 1311 * 1312 * @return Details on hash if it was in DB or null if it was not found. 1313 * 1314 * @throws TskCoreException 1315 */ lookupInHashDatabaseVerbose(String hash, int dbHandle)1316 public static HashHitInfo lookupInHashDatabaseVerbose(String hash, int dbHandle) throws TskCoreException { 1317 return hashDbLookupVerbose(hash, dbHandle); 1318 } 1319 1320 /** 1321 * Adds a hash value to a hash database. 1322 * 1323 * @param filename Name of file (can be null) 1324 * @param md5 Text of MD5 hash (can be null) 1325 * @param sha1 Text of SHA1 hash (can be null) 1326 * @param sha256 Text of SHA256 hash (can be null) 1327 * @param comment A comment (can be null) 1328 * @param dbHandle Handle to DB 1329 * 1330 * @throws TskCoreException 1331 */ addToHashDatabase(String filename, String md5, String sha1, String sha256, String comment, int dbHandle)1332 public static void addToHashDatabase(String filename, String md5, String sha1, String sha256, String comment, int dbHandle) throws TskCoreException { 1333 hashDbAddEntryNat(filename, md5, sha1, sha256, comment, dbHandle); 1334 } 1335 addToHashDatabase(List<HashEntry> hashes, int dbHandle)1336 public static void addToHashDatabase(List<HashEntry> hashes, int dbHandle) throws TskCoreException { 1337 hashDbBeginTransactionNat(dbHandle); 1338 try { 1339 for (HashEntry entry : hashes) { 1340 hashDbAddEntryNat(entry.getFileName(), entry.getMd5Hash(), entry.getSha1Hash(), entry.getSha256Hash(), entry.getComment(), dbHandle); 1341 } 1342 hashDbCommitTransactionNat(dbHandle); 1343 } catch (TskCoreException ex) { 1344 try { 1345 hashDbRollbackTransactionNat(dbHandle); 1346 } catch (TskCoreException ex2) { 1347 ex2.initCause(ex); 1348 throw ex2; 1349 } 1350 throw ex; 1351 } 1352 } 1353 isUpdateableHashDatabase(int dbHandle)1354 public static boolean isUpdateableHashDatabase(int dbHandle) throws TskCoreException { 1355 return hashDbIsUpdateableNat(dbHandle); 1356 } 1357 hashDatabaseIsIndexOnly(int dbHandle)1358 public static boolean hashDatabaseIsIndexOnly(int dbHandle) throws TskCoreException { 1359 return hashDbIsIdxOnlyNat(dbHandle); 1360 } 1361 1362 /** 1363 * Convert this timezone from long to short form Convert timezoneLongForm 1364 * passed in from long to short form 1365 * 1366 * @param timezoneLongForm the long form (e.g., America/New_York) 1367 * 1368 * @return the short form (e.g., EST5EDT) string representation, or an empty 1369 * string if empty long form was passed in 1370 */ timezoneLongToShort(String timezoneLongForm)1371 private static String timezoneLongToShort(String timezoneLongForm) { 1372 if (timezoneLongForm == null || timezoneLongForm.isEmpty()) { 1373 return ""; 1374 } 1375 1376 String timezoneShortForm; 1377 TimeZone zone = TimeZone.getTimeZone(timezoneLongForm); 1378 int offset = zone.getRawOffset() / 1000; 1379 int hour = offset / 3600; 1380 int min = (offset % 3600) / 60; 1381 DateFormat dfm = new SimpleDateFormat("z"); 1382 dfm.setTimeZone(zone); 1383 boolean hasDaylight = zone.useDaylightTime(); 1384 String first = dfm.format(new GregorianCalendar(2010, 1, 1).getTime()).substring(0, 3); // make it only 3 letters code 1385 String second = dfm.format(new GregorianCalendar(2011, 6, 6).getTime()).substring(0, 3); // make it only 3 letters code 1386 int mid = hour * -1; 1387 timezoneShortForm = first + Integer.toString(mid); 1388 if (min != 0) { 1389 timezoneShortForm = timezoneShortForm + ":" + (min < 10 ? "0" : "") + Integer.toString(min); 1390 } 1391 if (hasDaylight) { 1392 timezoneShortForm += second; 1393 } 1394 return timezoneShortForm; 1395 } 1396 1397 /** 1398 * Fills in any gaps in the image created by image writer. 1399 * 1400 * @param imgHandle The image handle. 1401 * 1402 * @return 0 if no errors occurred; 1 otherwise. 1403 * 1404 * @throws TskCoreException exception thrown if critical error occurs within 1405 * TSK 1406 */ finishImageWriter(long imgHandle)1407 public static int finishImageWriter(long imgHandle) throws TskCoreException { 1408 getTSKReadLock(); 1409 try { 1410 if(! imgHandleIsValid(imgHandle)) { 1411 throw new TskCoreException("Image handle " + imgHandle + " is closed"); 1412 } 1413 return finishImageWriterNat(imgHandle); 1414 } finally { 1415 releaseTSKReadLock(); 1416 } 1417 } 1418 1419 /** 1420 * Get the current progress of the finish image process (0-100) 1421 * 1422 * @param imgHandle 1423 * 1424 * @return Percentage of blocks completed (0-100) 1425 */ getFinishImageProgress(long imgHandle)1426 public static int getFinishImageProgress(long imgHandle) { 1427 getTSKReadLock(); 1428 try { 1429 if (imgHandleIsValid(imgHandle)) { 1430 return getFinishImageProgressNat(imgHandle); 1431 } else { 1432 return 0; 1433 } 1434 } finally { 1435 releaseTSKReadLock(); 1436 } 1437 } 1438 1439 /** 1440 * Cancel the finish image process 1441 * 1442 * @param imgHandle 1443 */ cancelFinishImage(long imgHandle)1444 public static void cancelFinishImage(long imgHandle) { 1445 getTSKReadLock(); 1446 try { 1447 if (imgHandleIsValid(imgHandle)) { 1448 cancelFinishImageNat(imgHandle); 1449 } 1450 } finally { 1451 releaseTSKReadLock(); 1452 } 1453 } 1454 1455 /** 1456 * Get size of a device (physical, logical device, image) pointed to by 1457 * devPath 1458 * 1459 * @param devPath device path pointing to the device 1460 * 1461 * @return size of the device in bytes 1462 * 1463 * @throws TskCoreException exception thrown if the device size could not be 1464 * queried 1465 */ findDeviceSize(String devPath)1466 public static long findDeviceSize(String devPath) throws TskCoreException { 1467 return findDeviceSizeNat(devPath); 1468 } 1469 isImageSupported(String imagePath)1470 public static boolean isImageSupported(String imagePath) { 1471 return isImageSupportedNat(imagePath); 1472 } 1473 1474 /** 1475 * Get a read lock for the C++ layer. Do not get this lock after obtaining 1476 * HandleCache.cacheLock. 1477 */ getTSKReadLock()1478 private static void getTSKReadLock() { 1479 tskLock.readLock().lock(); 1480 } 1481 1482 /** 1483 * Release the read lock 1484 */ releaseTSKReadLock()1485 private static void releaseTSKReadLock() { 1486 tskLock.readLock().unlock(); 1487 } 1488 1489 //free pointers 1490 /** 1491 * frees the imgHandle pointer currently does not close the image - 1492 * imgHandle should only be freed as part of CaseDbHandle.free(). 1493 * 1494 * @param imgHandle to close the image 1495 */ 1496 @Deprecated closeImg(long imgHandle)1497 public static void closeImg(long imgHandle) { 1498 //closeImgNat(imgHandle); 1499 } 1500 1501 /** 1502 * frees the vsHandle pointer - currently does nothing 1503 * 1504 * @param vsHandle pointer to volume system structure in sleuthkit 1505 */ 1506 @Deprecated closeVs(long vsHandle)1507 public static void closeVs(long vsHandle) { 1508 // closeVsNat(vsHandle); TODO JIRA-3829 1509 } 1510 1511 /** 1512 * frees the fsHandle pointer Currently does not do anything - fsHandle 1513 * should only be freed as part of CaseDbHandle.free(). 1514 * 1515 * @param fsHandle pointer to file system structure in sleuthkit 1516 */ 1517 @Deprecated closeFs(long fsHandle)1518 public static void closeFs(long fsHandle) { 1519 //closeFsNat(fsHandle); 1520 } 1521 1522 /** 1523 * Open the image and return the image info pointer. 1524 * 1525 * @param imageFiles the paths to the images 1526 * 1527 * @return the image info pointer 1528 * 1529 * @throws TskCoreException exception thrown if critical error occurs within 1530 * TSK 1531 * @deprecated Use the version with the SleuthkitCase argument 1532 */ 1533 @Deprecated openImage(String[] imageFiles)1534 public static long openImage(String[] imageFiles) throws TskCoreException { 1535 1536 return openImage(imageFiles, 0, true, null); 1537 } 1538 1539 /** 1540 * Open the image with a specified sector size and return the image info 1541 * pointer. 1542 * 1543 * @param imageFiles the paths to the images 1544 * @param sSize the sector size (use '0' for autodetect) 1545 * 1546 * @return the image info pointer 1547 * 1548 * @throws TskCoreException exception thrown if critical error occurs within 1549 * TSK 1550 * @deprecated Use the version with the SleuthkitCase argument 1551 */ 1552 @Deprecated openImage(String[] imageFiles, int sSize)1553 public static long openImage(String[] imageFiles, int sSize) throws TskCoreException { 1554 return openImage(imageFiles, sSize, true, null); 1555 } 1556 1557 1558 /** 1559 * Get file system Handle Opened handle is cached (transparently) so it does 1560 * not need be reopened next time for the duration of the application 1561 * 1562 * @param imgHandle pointer to imgHandle in sleuthkit 1563 * @param fsOffset byte offset to the file system 1564 * 1565 * @return pointer to a fsHandle structure in the sleuthkit 1566 * 1567 * @throws TskCoreException exception thrown if critical error occurs within 1568 * TSK 1569 * @deprecated Use the version with the SleuthkitCase argument 1570 */ 1571 @Deprecated openFs(long imgHandle, long fsOffset)1572 public static long openFs(long imgHandle, long fsOffset) throws TskCoreException { 1573 return openFs(imgHandle, fsOffset, null); 1574 } 1575 1576 /** 1577 * Get file Handle 1578 * 1579 * @param fsHandle fsHandle pointer in the sleuthkit 1580 * @param fileId id of the file 1581 * @param attrType file attribute type to open 1582 * @param attrId file attribute id to open 1583 * 1584 * @return pointer to a file structure in the sleuthkit 1585 * 1586 * @throws TskCoreException exception thrown if critical error occurs within 1587 * TSK 1588 * @deprecated Use the version with the SleuthkitCase argument 1589 */ 1590 @Deprecated openFile(long fsHandle, long fileId, TSK_FS_ATTR_TYPE_ENUM attrType, int attrId)1591 public static long openFile(long fsHandle, long fileId, TSK_FS_ATTR_TYPE_ENUM attrType, int attrId) throws TskCoreException { 1592 return openFile(fsHandle, fileId, attrType, attrId, null); 1593 } 1594 1595 getVersionNat()1596 private static native String getVersionNat(); 1597 startVerboseLoggingNat(String logPath)1598 private static native void startVerboseLoggingNat(String logPath); 1599 newCaseDbNat(String dbPath)1600 private static native long newCaseDbNat(String dbPath) throws TskCoreException; 1601 newCaseDbMultiNat(String hostNameOrIP, String portNumber, String userName, String password, int dbTypeOrdinal, String databaseName)1602 private static native long newCaseDbMultiNat(String hostNameOrIP, String portNumber, String userName, String password, int dbTypeOrdinal, String databaseName); 1603 openCaseDbMultiNat(String hostNameOrIP, String portNumber, String userName, String password, int dbTypeOrdinal, String databaseName)1604 private static native long openCaseDbMultiNat(String hostNameOrIP, String portNumber, String userName, String password, int dbTypeOrdinal, String databaseName); 1605 openCaseDbNat(String path)1606 private static native long openCaseDbNat(String path) throws TskCoreException; 1607 closeCaseDbNat(long db)1608 private static native void closeCaseDbNat(long db) throws TskCoreException; 1609 hashDbOpenNat(String hashDbPath)1610 private static native int hashDbOpenNat(String hashDbPath) throws TskCoreException; 1611 hashDbNewNat(String hashDbPath)1612 private static native int hashDbNewNat(String hashDbPath) throws TskCoreException; 1613 hashDbBeginTransactionNat(int dbHandle)1614 private static native int hashDbBeginTransactionNat(int dbHandle) throws TskCoreException; 1615 hashDbCommitTransactionNat(int dbHandle)1616 private static native int hashDbCommitTransactionNat(int dbHandle) throws TskCoreException; 1617 hashDbRollbackTransactionNat(int dbHandle)1618 private static native int hashDbRollbackTransactionNat(int dbHandle) throws TskCoreException; 1619 hashDbAddEntryNat(String filename, String hashMd5, String hashSha1, String hashSha256, String comment, int dbHandle)1620 private static native int hashDbAddEntryNat(String filename, String hashMd5, String hashSha1, String hashSha256, String comment, int dbHandle) throws TskCoreException; 1621 hashDbIsUpdateableNat(int dbHandle)1622 private static native boolean hashDbIsUpdateableNat(int dbHandle); 1623 hashDbIsReindexableNat(int dbHandle)1624 private static native boolean hashDbIsReindexableNat(int dbHandle); 1625 hashDbPathNat(int dbHandle)1626 private static native String hashDbPathNat(int dbHandle); 1627 hashDbIndexPathNat(int dbHandle)1628 private static native String hashDbIndexPathNat(int dbHandle); 1629 hashDbGetDisplayName(int dbHandle)1630 private static native String hashDbGetDisplayName(int dbHandle) throws TskCoreException; 1631 hashDbCloseAll()1632 private static native void hashDbCloseAll() throws TskCoreException; 1633 hashDbClose(int dbHandle)1634 private static native void hashDbClose(int dbHandle) throws TskCoreException; 1635 hashDbCreateIndexNat(int dbHandle)1636 private static native void hashDbCreateIndexNat(int dbHandle) throws TskCoreException; 1637 hashDbIndexExistsNat(int dbHandle)1638 private static native boolean hashDbIndexExistsNat(int dbHandle) throws TskCoreException; 1639 hashDbIsIdxOnlyNat(int dbHandle)1640 private static native boolean hashDbIsIdxOnlyNat(int dbHandle) throws TskCoreException; 1641 hashDbLookup(String hash, int dbHandle)1642 private static native boolean hashDbLookup(String hash, int dbHandle) throws TskCoreException; 1643 hashDbLookupVerbose(String hash, int dbHandle)1644 private static native HashHitInfo hashDbLookupVerbose(String hash, int dbHandle) throws TskCoreException; 1645 initAddImgNat(long db, String timezone, boolean addUnallocSpace, boolean skipFatFsOrphans)1646 private static native long initAddImgNat(long db, String timezone, boolean addUnallocSpace, boolean skipFatFsOrphans) throws TskCoreException; 1647 initializeAddImgNat(long db, String timezone, boolean addFileSystems, boolean addUnallocSpace, boolean skipFatFsOrphans)1648 private static native long initializeAddImgNat(long db, String timezone, boolean addFileSystems, boolean addUnallocSpace, boolean skipFatFsOrphans) throws TskCoreException; 1649 runOpenAndAddImgNat(long process, String deviceId, String[] imgPath, int splits, String timezone)1650 private static native void runOpenAndAddImgNat(long process, String deviceId, String[] imgPath, int splits, String timezone) throws TskCoreException, TskDataException; 1651 runAddImgNat(long process, String deviceId, long a_img_info, String timeZone, String imageWriterPath)1652 private static native void runAddImgNat(long process, String deviceId, long a_img_info, String timeZone, String imageWriterPath) throws TskCoreException, TskDataException; 1653 stopAddImgNat(long process)1654 private static native void stopAddImgNat(long process) throws TskCoreException; 1655 revertAddImgNat(long process)1656 private static native void revertAddImgNat(long process) throws TskCoreException; 1657 commitAddImgNat(long process)1658 private static native long commitAddImgNat(long process) throws TskCoreException; 1659 openImgNat(String[] imgPath, int splits, int sSize)1660 private static native long openImgNat(String[] imgPath, int splits, int sSize) throws TskCoreException; 1661 openVsNat(long imgHandle, long vsOffset)1662 private static native long openVsNat(long imgHandle, long vsOffset) throws TskCoreException; 1663 openVolNat(long vsHandle, long volId)1664 private static native long openVolNat(long vsHandle, long volId) throws TskCoreException; 1665 openFsNat(long imgHandle, long fsId)1666 private static native long openFsNat(long imgHandle, long fsId) throws TskCoreException; 1667 openFileNat(long fsHandle, long fileId, int attrType, int attrId)1668 private static native long openFileNat(long fsHandle, long fileId, int attrType, int attrId) throws TskCoreException; 1669 readImgNat(long imgHandle, byte[] readBuffer, long offset, long len)1670 private static native int readImgNat(long imgHandle, byte[] readBuffer, long offset, long len) throws TskCoreException; 1671 readVsNat(long vsHandle, byte[] readBuffer, long offset, long len)1672 private static native int readVsNat(long vsHandle, byte[] readBuffer, long offset, long len) throws TskCoreException; 1673 readVolNat(long volHandle, byte[] readBuffer, long offset, long len)1674 private static native int readVolNat(long volHandle, byte[] readBuffer, long offset, long len) throws TskCoreException; 1675 readFsNat(long fsHandle, byte[] readBuffer, long offset, long len)1676 private static native int readFsNat(long fsHandle, byte[] readBuffer, long offset, long len) throws TskCoreException; 1677 readFileNat(long fileHandle, byte[] readBuffer, long offset, int offset_type, long len)1678 private static native int readFileNat(long fileHandle, byte[] readBuffer, long offset, int offset_type, long len) throws TskCoreException; 1679 saveFileMetaDataTextNat(long fileHandle, String fileName)1680 private static native int saveFileMetaDataTextNat(long fileHandle, String fileName) throws TskCoreException; 1681 closeImgNat(long imgHandle)1682 private static native void closeImgNat(long imgHandle); 1683 closeVsNat(long vsHandle)1684 private static native void closeVsNat(long vsHandle); 1685 closeFsNat(long fsHandle)1686 private static native void closeFsNat(long fsHandle); 1687 closeFileNat(long fileHandle)1688 private static native void closeFileNat(long fileHandle); 1689 findDeviceSizeNat(String devicePath)1690 private static native long findDeviceSizeNat(String devicePath) throws TskCoreException; 1691 getCurDirNat(long process)1692 private static native String getCurDirNat(long process); 1693 isImageSupportedNat(String imagePath)1694 private static native boolean isImageSupportedNat(String imagePath); 1695 finishImageWriterNat(long a_img_info)1696 private static native int finishImageWriterNat(long a_img_info); 1697 getFinishImageProgressNat(long a_img_info)1698 private static native int getFinishImageProgressNat(long a_img_info); 1699 cancelFinishImageNat(long a_img_info)1700 private static native void cancelFinishImageNat(long a_img_info); 1701 1702 } 1703