Sleuth Kit Java Bindings (JNI)  4.11.1
Java bindings for using The Sleuth Kit
TskCaseDbBridge.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2020 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 com.google.common.base.Strings;
22 import java.sql.PreparedStatement;
23 import java.sql.SQLException;
24 import java.sql.Statement;
25 import org.apache.commons.lang3.StringUtils;
26 import java.util.List;
27 import java.util.Arrays;
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 import java.util.Iterator;
31 import java.util.LinkedList;
32 import java.util.Map;
33 import java.util.Objects;
34 import java.util.Optional;
35 import java.util.Queue;
36 import java.util.logging.Level;
37 import java.util.logging.Logger;
40 
50 class TskCaseDbBridge {
51 
52  private static final Logger logger = Logger.getLogger(TskCaseDbBridge.class.getName());
53 
54  private final SleuthkitCase caseDb;
55  private CaseDbTransaction trans = null;
56  private final AddDataSourceCallbacks addDataSourceCallbacks;
57  private final Host imageHost;
58 
59  private final Map<Long, Long> fsIdToRootDir = new HashMap<>();
60  private final Map<Long, TskData.TSK_FS_TYPE_ENUM> fsIdToFsType = new HashMap<>();
61  private final Map<ParentCacheKey, Long> parentDirCache = new HashMap<>();
62 
63  private final Map<String, OsAccount> ownerIdToAccountMap = new HashMap<>();
64 
65  private static final long BATCH_FILE_THRESHOLD = 500;
66  private final Queue<FileInfo> batchedFiles = new LinkedList<>();
67  private final Queue<LayoutRangeInfo> batchedLayoutRanges = new LinkedList<>();
68  private final List<Long> layoutFileIds = new ArrayList<>();
69  private final Map<Long, VirtualDirectory> unallocFileDirs = new HashMap<>();
70 
71  TskCaseDbBridge(SleuthkitCase caseDb, AddDataSourceCallbacks addDataSourceCallbacks, Host host) {
72  this.caseDb = caseDb;
73  this.addDataSourceCallbacks = addDataSourceCallbacks;
74  imageHost = host;
75  trans = null;
76  }
77 
83  private void beginTransaction() throws TskCoreException {
84  trans = caseDb.beginTransaction();
85  }
86 
92  private void commitTransaction() throws TskCoreException {
93  trans.commit();
94  trans = null;
95  }
96 
100  private void revertTransaction() {
101  try {
102  if (trans != null) {
103  trans.rollback();
104  trans = null;
105  }
106  } catch (TskCoreException ex) {
107  logger.log(Level.SEVERE, "Error rolling back transaction", ex);
108  }
109  }
110 
114  void finish() {
115  addBatchedFilesToDb();
116  addBatchedLayoutRangesToDb();
117  processLayoutFiles();
118  }
119 
139  long addImageInfo(int type, long ssize, String timezone,
140  long size, String md5, String sha1, String sha256, String deviceId,
141  String collectionDetails, String[] paths) {
142  try {
143  beginTransaction();
144  long objId = addImageToDb(TskData.TSK_IMG_TYPE_ENUM.valueOf(type), ssize, size,
145  timezone, md5, sha1, sha256, deviceId, collectionDetails, trans);
146  for (int i = 0;i < paths.length;i++) {
147  addImageNameToDb(objId, paths[i], i, trans);
148  }
149  commitTransaction();
150  return objId;
151  } catch (TskCoreException ex) {
152  logger.log(Level.SEVERE, "Error adding image to the database", ex);
153  revertTransaction();
154  return -1;
155  }
156  }
157 
164  void addAcquisitionDetails(long imgId, String details) {
165  try {
166  beginTransaction();
167  caseDb.setAcquisitionDetails(imgId, details, trans);
168  commitTransaction();
169  } catch (TskCoreException ex) {
170  logger.log(Level.SEVERE, "Error adding image details \"" + details + "\" to image with ID " + imgId, ex);
171  revertTransaction();
172  }
173  }
174 
186  long addVsInfo(long parentObjId, int vsType, long imgOffset, long blockSize) {
187  try {
188  beginTransaction();
189  VolumeSystem vs = caseDb.addVolumeSystem(parentObjId, TskData.TSK_VS_TYPE_ENUM.valueOf(vsType), imgOffset, blockSize, trans);
190  commitTransaction();
191  return vs.getId();
192  } catch (TskCoreException ex) {
193  logger.log(Level.SEVERE, "Error adding volume system to the database - parent obj ID: " + parentObjId
194  + ", image offset: " + imgOffset, ex);
195  revertTransaction();
196  return -1;
197  }
198  }
199 
213  long addVolume(long parentObjId, long addr, long start, long length, String desc,
214  long flags) {
215  try {
216  beginTransaction();
217  Volume vol = caseDb.addVolume(parentObjId, addr, start, length, desc, flags, trans);
218  commitTransaction();
219  return vol.getId();
220  } catch (TskCoreException ex) {
221  logger.log(Level.SEVERE, "Error adding volume to the database - parent object ID: " + parentObjId
222  + ", addr: " + addr, ex);
223  revertTransaction();
224  return -1;
225  }
226  }
227 
237  long addPool(long parentObjId, int poolType) {
238  try {
239  beginTransaction();
240  Pool pool = caseDb.addPool(parentObjId, TskData.TSK_POOL_TYPE_ENUM.valueOf(poolType), trans);
241  commitTransaction();
242  return pool.getId();
243  } catch (TskCoreException ex) {
244  logger.log(Level.SEVERE, "Error adding pool to the database - parent object ID: " + parentObjId, ex);
245  revertTransaction();
246  return -1;
247  }
248  }
249 
265  long addFileSystem(long parentObjId, long imgOffset, int fsType, long blockSize, long blockCount,
266  long rootInum, long firstInum, long lastInum) {
267  try {
268  beginTransaction();
269  FileSystem fs = caseDb.addFileSystem(parentObjId, imgOffset, TskData.TSK_FS_TYPE_ENUM.valueOf(fsType), blockSize, blockCount,
270  rootInum, firstInum, lastInum, null, trans);
271  commitTransaction();
272  fsIdToFsType.put(fs.getId(), TskData.TSK_FS_TYPE_ENUM.valueOf(fsType));
273  return fs.getId();
274  } catch (TskCoreException ex) {
275  logger.log(Level.SEVERE, "Error adding file system to the database - parent object ID: " + parentObjId
276  + ", offset: " + imgOffset, ex);
277  revertTransaction();
278  return -1;
279  }
280  }
281 
323  long addFile(long parentObjId,
324  long fsObjId, long dataSourceObjId,
325  int fsType,
326  int attrType, int attrId, String name,
327  long metaAddr, long metaSeq,
328  int dirType, int metaType, int dirFlags, int metaFlags,
329  long size,
330  long crtime, long ctime, long atime, long mtime,
331  int meta_mode, int gid, int uid,
332  String escaped_path, String extension,
333  long seq, long parMetaAddr, long parSeq, String ownerUid) {
334 
335  // Add the new file to the list
336  batchedFiles.add(new FileInfo(parentObjId,
337  fsObjId, dataSourceObjId,
338  fsType,
339  attrType, attrId, name,
340  metaAddr, metaSeq,
341  dirType, metaType, dirFlags, metaFlags,
342  size,
343  crtime, ctime, atime, mtime,
344  meta_mode, gid, uid,
345  escaped_path, extension,
346  seq, parMetaAddr, parSeq, ownerUid));
347 
348  // Add the current files to the database if we've exceeded the threshold or if we
349  // have the root folder.
350  if ((fsObjId == parentObjId)
351  || (batchedFiles.size() > BATCH_FILE_THRESHOLD)) {
352  return addBatchedFilesToDb();
353  }
354  return 0;
355  }
356 
362  private long addBatchedFilesToDb() {
363  List<Long> newObjIds = new ArrayList<>();
364  try {
365 
366  // loop through the batch, and make sure owner accounts exist for all the files in the batch.
367  // If not, create accounts.
368  Iterator<FileInfo> it = batchedFiles.iterator();
369 
370  while (it.hasNext()) {
371  FileInfo fileInfo = it.next();
372  String ownerUid = fileInfo.ownerUid;
373  if (Strings.isNullOrEmpty(fileInfo.ownerUid) == false) {
374  // first check the owner id is in the map, if found, then continue
375  if (this.ownerIdToAccountMap.containsKey(ownerUid)) {
376  continue;
377  }
378 
379  // query the DB to get the owner account
380  try {
381  Optional<OsAccount> ownerAccount = caseDb.getOsAccountManager().getWindowsOsAccount(ownerUid, null, null, imageHost);
382  if (ownerAccount.isPresent()) {
383  // found account - add to map
384  ownerIdToAccountMap.put(ownerUid, ownerAccount.get());
385  } else {
386  // account not found in the database, create the account and add to map
387  // Currently we expect only NTFS systems to provide a windows style SID as owner id.
388  OsAccountManager accountMgr = caseDb.getOsAccountManager();
389  OsAccount newAccount = accountMgr.newWindowsOsAccount(ownerUid, null, null, imageHost, OsAccountRealm.RealmScope.UNKNOWN);
390  Content ds = caseDb.getContentById(fileInfo.dataSourceObjId); // Data sources are cached so this will only access the database once
391  if (ds instanceof DataSource) {
392  accountMgr.newOsAccountInstance(newAccount, (DataSource)ds, OsAccountInstance.OsAccountInstanceType.ACCESSED);
393  }
394  ownerIdToAccountMap.put(ownerUid, newAccount);
395  }
396  } catch (NotUserSIDException ex) {
397  // if the owner SID is not a user SID, set the owner account to null
398  ownerIdToAccountMap.put(ownerUid, null);
399  }
400  }
401  }
402 
403 
404 
405  beginTransaction();
406  FileInfo fileInfo;
407  while ((fileInfo = batchedFiles.poll()) != null) {
408  long computedParentObjId = fileInfo.parentObjId;
409  try {
410  // If we weren't given the parent object ID, look it up
411  if (fileInfo.parentObjId == 0) {
412  computedParentObjId = getParentObjId(fileInfo);
413  }
414 
415  Long ownerAccountObjId = OsAccount.NO_ACCOUNT;
416  if (Strings.isNullOrEmpty(fileInfo.ownerUid) == false) {
417  if (ownerIdToAccountMap.containsKey(fileInfo.ownerUid)) {
418  // for any non user SIDs, the map will have a null for account
419  if (Objects.nonNull(ownerIdToAccountMap.get(fileInfo.ownerUid))) {
420  ownerAccountObjId = ownerIdToAccountMap.get(fileInfo.ownerUid).getId();
421  }
422  } else {
423  // Error - the map should have an account or a null at this point for the owner SID.
424  throw new TskCoreException(String.format("Failed to add file. Owner account not found for file with parent object ID: %d, name: %s, owner id: %s", fileInfo.parentObjId, fileInfo.name, fileInfo.ownerUid));
425  }
426  }
427 
428  // We've seen a case where the root folder comes in with an undefined meta type.
429  // We've also seen a case where it comes in as a regular file. The root folder should always be
430  // a directory so it will be cached properly and will not cause errors later for
431  // being an unexpected type.
432  if ((fileInfo.parentObjId == fileInfo.fsObjId)
433  && (fileInfo.metaType != TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue())) {
434  fileInfo.metaType = TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue();
435  }
436 
437  long objId = addFileToDb(computedParentObjId,
438  fileInfo.fsObjId, fileInfo.dataSourceObjId,
439  fileInfo.fsType,
440  fileInfo.attrType, fileInfo.attrId, fileInfo.name,
441  fileInfo.metaAddr, fileInfo.metaSeq,
442  fileInfo.dirType, fileInfo.metaType, fileInfo.dirFlags, fileInfo.metaFlags,
443  fileInfo.size,
444  fileInfo.crtime, fileInfo.ctime, fileInfo.atime, fileInfo.mtime,
445  fileInfo.meta_mode, fileInfo.gid, fileInfo.uid,
446  null, TskData.FileKnown.UNKNOWN,
447  fileInfo.escaped_path, fileInfo.extension, fileInfo.ownerUid, ownerAccountObjId,
448  false, trans);
449  if (fileInfo.fsObjId != fileInfo.parentObjId) {
450  // Add new file ID to the list to send to ingest unless it is the root folder
451  newObjIds.add(objId);
452  }
453 
454  // If we're adding the root directory for the file system, cache it
455  if (fileInfo.parentObjId == fileInfo.fsObjId) {
456  fsIdToRootDir.put(fileInfo.fsObjId, objId);
457  }
458 
459  // If the file is a directory, cache the object ID.
460  if ((fileInfo.metaType == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()
461  || (fileInfo.metaType == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR.getValue()))
462  && (fileInfo.name != null)
463  && ! fileInfo.name.equals(".")
464  && ! fileInfo.name.equals("..")) {
465  String dirName = fileInfo.escaped_path + fileInfo.name;
466  ParentCacheKey key = new ParentCacheKey(fileInfo.fsObjId, fileInfo.metaAddr, fileInfo.seq, dirName);
467  parentDirCache.put(key, objId);
468  }
469  } catch (TskCoreException ex) {
470  if (computedParentObjId > 0) {
471  // Most likely a database error occurred
472  logger.log(Level.SEVERE, "Error adding file to the database - parent object ID: " + computedParentObjId
473  + ", file system object ID: " + fileInfo.fsObjId + ", name: " + fileInfo.name, ex);
474  } else {
475  // The parent lookup failed
476  logger.log(Level.SEVERE, "Error adding file to the database", ex);
477  }
478  }
479  }
480  commitTransaction();
481  try {
482  addDataSourceCallbacks.onFilesAdded(newObjIds);
483  } catch (Exception ex) {
484  // Exception firewall to prevent unexpected return to the native code
485  logger.log(Level.SEVERE, "Unexpected error from files added callback", ex);
486  }
487  } catch (TskCoreException ex) {
488  logger.log(Level.SEVERE, "Error adding batched files to database", ex);
489  revertTransaction();
490  return -1;
491  }
492  return 0;
493  }
494 
504  private long getParentObjId(FileInfo fileInfo) throws TskCoreException {
505  // Remove the final slash from the path unless we're in the root folder
506  String parentPath = fileInfo.escaped_path;
507  if(parentPath.endsWith("/") && ! parentPath.equals("/")) {
508  parentPath = parentPath.substring(0, parentPath.lastIndexOf('/'));
509  }
510 
511  // Look up the parent
512  ParentCacheKey key = new ParentCacheKey(fileInfo.fsObjId, fileInfo.parMetaAddr, fileInfo.parSeq, parentPath);
513  if (parentDirCache.containsKey(key)) {
514  return parentDirCache.get(key);
515  } else {
516  // There's no reason to do a database query since every folder added is being
517  // stored in the cache.
518  throw new TskCoreException("Could not find parent (fsObjId: " +fileInfo.fsObjId + ", parMetaAddr: " + fileInfo.parMetaAddr
519  + ", parSeq: " + fileInfo.parSeq + ", parentPath: " + parentPath + ")");
520  }
521  }
522 
536  long addLayoutFile(long parentObjId,
537  long fsObjId, long dataSourceObjId,
538  int fileType,
539  String name, long size) {
540  try {
541 
542  // The file system may be null for layout files
543  Long fsObjIdForDb = fsObjId;
544  if (fsObjId == 0) {
545  fsObjIdForDb = null;
546  }
547 
548  // If the layout file is in an $Unalloc folder, add the name. Otherwise use "/".
549  String parentPath = "/";
550  if (unallocFileDirs.containsKey(parentObjId)) {
551  parentPath = "/" + unallocFileDirs.get(parentObjId).getName() + "/";
552  }
553 
554  beginTransaction();
555  long objId = addFileToDb(parentObjId,
556  fsObjIdForDb, dataSourceObjId,
557  fileType,
558  null, null, name,
559  null, null,
560  TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue(),
561  TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue(),
562  TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue(),
563  TskData.TSK_FS_META_FLAG_ENUM.UNALLOC.getValue(),
564  size,
565  null, null, null, null,
566  null, null, null,
567  null, TskData.FileKnown.UNKNOWN,
568  parentPath, null, null, OsAccount.NO_ACCOUNT,
569  true, trans);
570  commitTransaction();
571 
572  // Store the layout file ID for later processing
573  layoutFileIds.add(objId);
574 
575  return objId;
576  } catch (TskCoreException ex) {
577  logger.log(Level.SEVERE, "Error adding layout file to the database - parent object ID: " + parentObjId
578  + ", file system object ID: " + fsObjId + ", name: " + name, ex);
579  revertTransaction();
580  return -1;
581  }
582  }
583 
595  long addLayoutFileRange(long objId, long byteStart, long byteLen, long seq) {
596  batchedLayoutRanges.add(new LayoutRangeInfo(objId, byteStart, byteLen, seq));
597 
598  if (batchedLayoutRanges.size() > BATCH_FILE_THRESHOLD) {
599  return addBatchedLayoutRangesToDb();
600  }
601  return 0;
602  }
603 
609  private long addBatchedLayoutRangesToDb() {
610  try {
611  beginTransaction();
612  LayoutRangeInfo range;
613  while ((range = batchedLayoutRanges.poll()) != null) {
614  try {
615  addLayoutFileRangeToDb(range.objId, range.byteStart, range.byteLen, range.seq, trans);
616  } catch (TskCoreException ex) {
617  logger.log(Level.SEVERE, "Error adding layout file range to the database - layout file ID: " + range.objId
618  + ", byte start: " + range.byteStart + ", length: " + range.byteLen + ", seq: " + range.seq, ex);
619  }
620  }
621  commitTransaction();
622  return 0;
623  } catch (TskCoreException ex) {
624  logger.log(Level.SEVERE, "Error adding batched files to database", ex);
625  revertTransaction();
626  return -1;
627  }
628  }
629 
635  void processLayoutFiles() {
636  addDataSourceCallbacks.onFilesAdded(layoutFileIds);
637  layoutFileIds.clear();
638  }
639 
649  long addUnallocFsBlockFilesParent(long fsObjId, String name) {
650  try {
651  if (! fsIdToRootDir.containsKey(fsObjId)) {
652  logger.log(Level.SEVERE, "Error - root directory for file system ID {0} not found", fsObjId);
653  return -1;
654  }
655  beginTransaction();
656  VirtualDirectory dir = caseDb.addVirtualDirectory(fsIdToRootDir.get(fsObjId), name, trans);
657  commitTransaction();
658  unallocFileDirs.put(dir.getId(), dir);
659  addDataSourceCallbacks.onFilesAdded(Arrays.asList(dir.getId()));
660  return dir.getId();
661  } catch (TskCoreException ex) {
662  logger.log(Level.SEVERE, "Error creating virtual directory " + name + " under file system ID " + fsObjId, ex);
663  revertTransaction();
664  return -1;
665  }
666  }
667 
671  private class ParentCacheKey {
672  long fsObjId;
673  long metaAddr;
674  long seqNum;
675  String path;
676 
686  ParentCacheKey(long fsObjId, long metaAddr, long seqNum, String path) {
687  this.fsObjId = fsObjId;
688  this.metaAddr = metaAddr;
689  if (ownerIdToAccountMap.containsKey(fsObjId)
690  && (ownerIdToAccountMap.get(fsObjId).equals(TskData.TSK_FS_TYPE_ENUM.TSK_FS_TYPE_NTFS)
691  || ownerIdToAccountMap.get(fsObjId).equals(TskData.TSK_FS_TYPE_ENUM.TSK_FS_TYPE_NTFS_DETECT))) {
692  this.seqNum = seqNum;
693  } else {
694  this.seqNum = 0;
695  }
696  this.path = path;
697  }
698 
699  @Override
700  public boolean equals(Object obj) {
701  if (! (obj instanceof ParentCacheKey)) {
702  return false;
703  }
704 
705  ParentCacheKey otherKey = (ParentCacheKey) obj;
706  if (this.fsObjId != otherKey.fsObjId
707  || this.metaAddr != otherKey.metaAddr
708  || this.seqNum != otherKey.seqNum) {
709  return false;
710  }
711 
712  return StringUtils.equals(this.path, otherKey.path);
713  }
714 
715  @Override
716  public int hashCode() {
717  int hash = 3;
718  hash = 31 * hash + (int) (this.fsObjId ^ (this.fsObjId >>> 32));
719  hash = 31 * hash + (int) (this.metaAddr ^ (this.metaAddr >>> 32));
720  hash = 31 * hash + (int) (this.seqNum ^ (this.seqNum >>> 32));
721  hash = 31 * hash + Objects.hashCode(this.path);
722  return hash;
723  }
724  }
725 
730  private class LayoutRangeInfo {
731  long objId;
732  long byteStart;
733  long byteLen;
734  long seq;
735 
736  LayoutRangeInfo(long objId, long byteStart, long byteLen, long seq) {
737  this.objId = objId;
738  this.byteStart = byteStart;
739  this.byteLen = byteLen;
740  this.seq = seq;
741  }
742  }
743 
748  private class FileInfo {
749  long parentObjId;
750  long fsObjId;
751  long dataSourceObjId;
752  int fsType;
753  int attrType;
754  int attrId;
755  String name;
756  long metaAddr;
757  long metaSeq;
758  int dirType;
759  int metaType;
760  int dirFlags;
761  int metaFlags;
762  long size;
763  long crtime;
764  long ctime;
765  long atime;
766  long mtime;
767  int meta_mode;
768  int gid;
769  int uid;
770  String escaped_path;
771  String extension;
772  long seq;
773  long parMetaAddr;
774  long parSeq;
775  String ownerUid;
776 
777  FileInfo(long parentObjId,
778  long fsObjId, long dataSourceObjId,
779  int fsType,
780  int attrType, int attrId, String name,
781  long metaAddr, long metaSeq,
782  int dirType, int metaType, int dirFlags, int metaFlags,
783  long size,
784  long crtime, long ctime, long atime, long mtime,
785  int meta_mode, int gid, int uid,
786  String escaped_path, String extension,
787  long seq, long parMetaAddr, long parSeq, String ownerUid) {
788 
789  this.parentObjId = parentObjId;
790  this.fsObjId = fsObjId;
791  this.dataSourceObjId = dataSourceObjId;
792  this.fsType = fsType;
793  this.attrType = attrType;
794  this.attrId = attrId;
795  this.name = name;
796  this.metaAddr = metaAddr;
797  this.metaSeq = metaSeq;
798  this.dirType = dirType;
799  this.metaType = metaType;
800  this.dirFlags = dirFlags;
801  this.metaFlags = metaFlags;
802  this.size = size;
803  this.crtime = crtime;
804  this.ctime = ctime;
805  this.atime = atime;
806  this.mtime = mtime;
807  this.meta_mode = meta_mode;
808  this.gid = gid;
809  this.uid = uid;
810  this.escaped_path = escaped_path;
811  this.extension = extension;
812  this.seq = seq;
813  this.parMetaAddr = parMetaAddr;
814  this.parSeq = parSeq;
815  this.ownerUid = ownerUid;
816  }
817  }
818 
862  private long addFileToDb(long parentObjId,
863  Long fsObjId, long dataSourceObjId,
864  int fsType,
865  Integer attrType, Integer attrId, String name,
866  Long metaAddr, Long metaSeq,
867  int dirType, int metaType, int dirFlags, int metaFlags,
868  long size,
869  Long crtime, Long ctime, Long atime, Long mtime,
870  Integer meta_mode, Integer gid, Integer uid,
871  String md5, TskData.FileKnown known,
872  String escaped_path, String extension, String ownerUid, Long ownerAcctObjId,
873  boolean hasLayout, CaseDbTransaction transaction) throws TskCoreException {
874 
875  try {
876  SleuthkitCase.CaseDbConnection connection = transaction.getConnection();
877 
878  // Insert a row for the local/logical file into the tsk_objects table.
879  // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
880  long objectId = caseDb.addObject(parentObjId, TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
881 
882  String fileInsert = "INSERT INTO tsk_files (fs_obj_id, obj_id, data_source_obj_id, type, attr_type, attr_id, name, meta_addr, meta_seq, dir_type, meta_type, dir_flags, meta_flags, size, crtime, ctime, atime, mtime, mode, gid, uid, md5, known, parent_path, extension, has_layout, owner_uid, os_account_obj_id)"
883  + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; // NON-NLS
884  PreparedStatement preparedStatement = connection.getPreparedStatement(fileInsert, Statement.NO_GENERATED_KEYS);
885  preparedStatement.clearParameters();
886 
887  if (fsObjId != null) {
888  preparedStatement.setLong(1, fsObjId); // fs_obj_id
889  } else {
890  preparedStatement.setNull(1, java.sql.Types.BIGINT);
891  }
892  preparedStatement.setLong(2, objectId); // obj_id
893  preparedStatement.setLong(3, dataSourceObjId); // data_source_obj_id
894  preparedStatement.setShort(4, (short) fsType); // type
895  if (attrType != null) {
896  preparedStatement.setShort(5, attrType.shortValue()); // attr_type
897  } else {
898  preparedStatement.setNull(5, java.sql.Types.SMALLINT);
899  }
900  if (attrId != null) {
901  preparedStatement.setInt(6, attrId); // attr_id
902  } else {
903  preparedStatement.setNull(6, java.sql.Types.INTEGER);
904  }
905  preparedStatement.setString(7, name); // name
906  if (metaAddr != null) {
907  preparedStatement.setLong(8, metaAddr); // meta_addr
908  } else {
909  preparedStatement.setNull(8, java.sql.Types.BIGINT);
910  }
911  if (metaSeq != null) {
912  preparedStatement.setInt(9, metaSeq.intValue()); // meta_seq
913  } else {
914  preparedStatement.setNull(9, java.sql.Types.INTEGER);
915  }
916  preparedStatement.setShort(10, (short) dirType); // dir_type
917  preparedStatement.setShort(11, (short) metaType); // meta_type
918  preparedStatement.setShort(12, (short) dirFlags); // dir_flags
919  preparedStatement.setShort(13, (short) metaFlags); // meta_flags
920  preparedStatement.setLong(14, size < 0 ? 0 : size); // size
921  if (crtime != null) {
922  preparedStatement.setLong(15, crtime); // crtime
923  } else {
924  preparedStatement.setNull(15, java.sql.Types.BIGINT);
925  }
926  if (ctime != null) {
927  preparedStatement.setLong(16, ctime); // ctime
928  } else {
929  preparedStatement.setNull(16, java.sql.Types.BIGINT);
930  }
931  if (atime != null) {
932  preparedStatement.setLong(17, atime); // atime
933  } else {
934  preparedStatement.setNull(17, java.sql.Types.BIGINT);
935  }
936  if (mtime != null) {
937  preparedStatement.setLong(18, mtime); // mtime
938  } else {
939  preparedStatement.setNull(18, java.sql.Types.BIGINT);
940  }
941  if (meta_mode != null) {
942  preparedStatement.setLong(19, meta_mode); // mode
943  } else {
944  preparedStatement.setNull(19, java.sql.Types.BIGINT);
945  }
946  if (gid != null) {
947  preparedStatement.setLong(20, gid); // gid
948  } else {
949  preparedStatement.setNull(20, java.sql.Types.BIGINT);
950  }
951  if (uid != null) {
952  preparedStatement.setLong(21, uid); // uid
953  } else {
954  preparedStatement.setNull(21, java.sql.Types.BIGINT);
955  }
956  preparedStatement.setString(22, md5); // md5
957  preparedStatement.setInt(23, known.getFileKnownValue());// known
958  preparedStatement.setString(24, escaped_path); // parent_path
959  preparedStatement.setString(25, extension); // extension
960  if (hasLayout) {
961  preparedStatement.setInt(26, 1); // has_layout
962  } else {
963  preparedStatement.setNull(26, java.sql.Types.INTEGER);
964  }
965 
966  preparedStatement.setString(27, ownerUid); // ownerUid
967 
968  if (ownerAcctObjId != OsAccount.NO_ACCOUNT) {
969  preparedStatement.setLong(28, ownerAcctObjId); //
970  } else {
971  preparedStatement.setNull(28, java.sql.Types.BIGINT);
972  }
973 
974  connection.executeUpdate(preparedStatement);
975 
976  // If this is not a slack file create the timeline events
977  if (!hasLayout
978  && TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType() != fsType
979  && (!name.equals(".")) && (!name.equals(".."))) {
980  TimelineManager timelineManager = caseDb.getTimelineManager();
981  DerivedFile derivedFile = new DerivedFile(caseDb, objectId, dataSourceObjId, fsObjId, name,
982  TskData.TSK_FS_NAME_TYPE_ENUM.valueOf((short) dirType),
983  TskData.TSK_FS_META_TYPE_ENUM.valueOf((short) metaType),
984  TskData.TSK_FS_NAME_FLAG_ENUM.valueOf(dirFlags),
985  (short) metaFlags,
986  size, ctime, crtime, atime, mtime, null, null, null, null, escaped_path, null, parentObjId, null, null, extension, ownerUid, ownerAcctObjId);
987 
988  timelineManager.addEventsForNewFileQuiet(derivedFile, connection);
989  }
990 
991  return objectId;
992  } catch (SQLException ex) {
993  throw new TskCoreException("Failed to add file system file", ex);
994  }
995  }
996 
1016  private long addImageToDb(TskData.TSK_IMG_TYPE_ENUM type, long sectorSize, long size,
1017  String timezone, String md5, String sha1, String sha256,
1018  String deviceId, String collectionDetails,
1019  CaseDbTransaction transaction) throws TskCoreException {
1020  try {
1021  // Insert a row for the Image into the tsk_objects table.
1022  SleuthkitCase.CaseDbConnection connection = transaction.getConnection();
1023  long newObjId = caseDb.addObject(0, TskData.ObjectType.IMG.getObjectType(), connection);
1024 
1025  // Add a row to tsk_image_info
1026  // INSERT INTO tsk_image_info (obj_id, type, ssize, tzone, size, md5, sha1, sha256, display_name)
1027  String imageInfoSql = "INSERT INTO tsk_image_info (obj_id, type, ssize, tzone, size, md5, sha1, sha256, display_name)"
1028  + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; // NON-NLS
1029  PreparedStatement preparedStatement = connection.getPreparedStatement(imageInfoSql, Statement.NO_GENERATED_KEYS);
1030  preparedStatement.clearParameters();
1031  preparedStatement.setLong(1, newObjId);
1032  preparedStatement.setShort(2, (short) type.getValue());
1033  preparedStatement.setLong(3, sectorSize);
1034  preparedStatement.setString(4, timezone);
1035  //prevent negative size
1036  long savedSize = size < 0 ? 0 : size;
1037  preparedStatement.setLong(5, savedSize);
1038  preparedStatement.setString(6, md5);
1039  preparedStatement.setString(7, sha1);
1040  preparedStatement.setString(8, sha256);
1041  preparedStatement.setString(9, null);
1042  connection.executeUpdate(preparedStatement);
1043 
1044  // Add a row to data_source_info
1045  String dataSourceInfoSql = "INSERT INTO data_source_info (obj_id, device_id, time_zone, acquisition_details, host_id) VALUES (?, ?, ?, ?, ?)"; // NON-NLS
1046  preparedStatement = connection.getPreparedStatement(dataSourceInfoSql, Statement.NO_GENERATED_KEYS);
1047  preparedStatement.clearParameters();
1048  preparedStatement.setLong(1, newObjId);
1049  preparedStatement.setString(2, deviceId);
1050  preparedStatement.setString(3, timezone);
1051  preparedStatement.setString(4, collectionDetails);
1052  preparedStatement.setLong(5, imageHost.getHostId());
1053  connection.executeUpdate(preparedStatement);
1054 
1055  return newObjId;
1056  } catch (SQLException ex) {
1057  throw new TskCoreException(String.format("Error adding image to database"), ex);
1058  }
1059  }
1060 
1071  private void addImageNameToDb(long objId, String name, long sequence,
1072  CaseDbTransaction transaction) throws TskCoreException {
1073  try {
1074  SleuthkitCase.CaseDbConnection connection = transaction.getConnection();
1075 
1076  String imageNameSql = "INSERT INTO tsk_image_names (obj_id, name, sequence) VALUES (?, ?, ?)"; // NON-NLS
1077  PreparedStatement preparedStatement = connection.getPreparedStatement(imageNameSql, Statement.NO_GENERATED_KEYS);
1078  preparedStatement.clearParameters();
1079  preparedStatement.setLong(1, objId);
1080  preparedStatement.setString(2, name);
1081  preparedStatement.setLong(3, sequence);
1082  connection.executeUpdate(preparedStatement);
1083  } catch (SQLException ex) {
1084  throw new TskCoreException(String.format("Error adding image name %s to image with object ID %d", name, objId), ex);
1085  }
1086  }
1087 
1099  void addLayoutFileRangeToDb(long objId, long byteStart, long byteLen,
1100  long seq, CaseDbTransaction transaction) throws TskCoreException {
1101  try {
1102  SleuthkitCase.CaseDbConnection connection = transaction.getConnection();
1103 
1104  String insertRangeSql = "INSERT INTO tsk_file_layout (obj_id, byte_start, byte_len, sequence) " //NON-NLS
1105  + "VALUES (?, ?, ?, ?)";
1106  PreparedStatement preparedStatement = connection.getPreparedStatement(insertRangeSql, Statement.NO_GENERATED_KEYS);
1107  preparedStatement.clearParameters();
1108  preparedStatement.setLong(1, objId);
1109  preparedStatement.setLong(2, byteStart);
1110  preparedStatement.setLong(3, byteLen);
1111  preparedStatement.setLong(4, seq);
1112  connection.executeUpdate(preparedStatement);
1113  } catch (SQLException ex) {
1114  throw new TskCoreException("Error adding layout range to file with obj ID " + objId, ex);
1115  }
1116  }
1117 }

Copyright © 2011-2021 Brian Carrier. (carrier -at- sleuthkit -dot- org)
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.