From fefc40fb937e35be49fa9e67df7d8ce16d62162f Mon Sep 17 00:00:00 2001
From: Richard Cordovano <rcordovano@basistech.com>
Date: Thu, 13 Oct 2016 13:47:20 -0400
Subject: [PATCH] Implement addFileSystems flag for adding images to case
 database

---
 bindings/java/jni/dataModel_SleuthkitJNI.cpp  | 63 ++++++++++-----
 bindings/java/jni/dataModel_SleuthkitJNI.h    |  8 ++
 .../org/sleuthkit/datamodel/SleuthkitJNI.java | 80 ++++++++++++++-----
 tsk/auto/auto_db.cpp                          | 18 ++++-
 tsk/auto/tsk_case_db.h                        |  7 ++
 5 files changed, 136 insertions(+), 40 deletions(-)

diff --git a/bindings/java/jni/dataModel_SleuthkitJNI.cpp b/bindings/java/jni/dataModel_SleuthkitJNI.cpp
index e9c8e16af..cea4f13ec 100644
--- a/bindings/java/jni/dataModel_SleuthkitJNI.cpp
+++ b/bindings/java/jni/dataModel_SleuthkitJNI.cpp
@@ -919,17 +919,39 @@ JNIEXPORT jobject JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbLookup
 }
 
 /*
- * Create an add-image process that can later be run with specific inputs
- * @return the pointer to the process or NULL on error
- * @param env pointer to java environment this was called from
- * @partam caseHandle pointer to case to add image to
- * @param timezone timezone for the image
- * @param addUnallocSpace whether to create virtual files for the unallocated space in the disk image
- * @param noFatFsOrphans whether to skip processing orphans on FAT filesystems
+ * Initialize a process for adding an image to a case database.
+ *
+ * @param env Pointer to java environment.
+ * @param obj Pointer the Java class object.
+ * @partam caseHandle Pointer to a TskCaseDb object.
+ * @param timeZone The time zone for the image.
+ * @param addUnallocSpace Pass true to create virtual files for unallocated space. Ignored if addFileSystems is false.
+ * @param skipFatFsOrphans Pass true to skip processing of orphan files for FAT file systems. Ignored if addFileSystems is false.
+ *
+ * @return A pointer to the process (TskAutoDb object) or NULL on error.
  */
 JNIEXPORT jlong JNICALL
     Java_org_sleuthkit_datamodel_SleuthkitJNI_initAddImgNat(JNIEnv * env,
-    jclass obj, jlong caseHandle, jstring timezone, jboolean addUnallocSpace, jboolean noFatFsOrphans) {
+    jclass obj, jlong caseHandle, jstring timeZone, jboolean addUnallocSpace, jboolean skipFatFsOrphans) {
+    return Java_org_sleuthkit_datamodel_SleuthkitJNI_initializeAddImgNat(env, obj, caseHandle, timeZone, true, addUnallocSpace, skipFatFsOrphans);
+}
+
+/*
+ * Initialize a process for adding an image to a case database.
+ *
+ * @param env Pointer to java environment.
+ * @param obj Pointer the Java class object.
+ * @partam caseHandle Pointer to a TskCaseDb object.
+ * @param timeZone The time zone for the image.
+ * @param addFileSystems Pass true to attempt to add file systems within the image to the case database.
+ * @param addUnallocSpace Pass true to create virtual files for unallocated space. Ignored if addFileSystems is false.
+ * @param skipFatFsOrphans Pass true to skip processing of orphan files for FAT file systems. Ignored if addFileSystems is false.
+ *
+ * @return A pointer to the process (TskAutoDb object) or NULL on error.
+ */
+JNIEXPORT jlong JNICALL
+    Java_org_sleuthkit_datamodel_SleuthkitJNI_initializeAddImgNat(JNIEnv * env, jclass obj, 
+    jlong caseHandle, jstring timeZone, jboolean addFileSystems, jboolean addUnallocSpace, jboolean skipFatFsOrphans) {
     jboolean isCopy;
 
     TskCaseDb *tskCase = castCaseDb(env, caseHandle);
@@ -938,11 +960,11 @@ JNIEXPORT jlong JNICALL
         return 0;
     }
 
-    if (env->GetStringUTFLength(timezone) > 0) {
-        const char *tzstr = env->GetStringUTFChars(timezone, &isCopy);
+    if (env->GetStringUTFLength(timeZone) > 0) {
+        const char *tzstr = env->GetStringUTFChars(timeZone, &isCopy);
 
         if (strlen(tzstr) > 64) {
-            env->ReleaseStringUTFChars(timezone, tzstr);
+            env->ReleaseStringUTFChars(timeZone, tzstr);
             stringstream ss;
             ss << "Timezone is too long";
             setThrowTskCoreError(env, ss.str().c_str());
@@ -951,7 +973,7 @@ JNIEXPORT jlong JNICALL
 
         char envstr[70];
         snprintf(envstr, 70, "TZ=%s", tzstr);
-        env->ReleaseStringUTFChars(timezone, tzstr);
+        env->ReleaseStringUTFChars(timeZone, tzstr);
 
         if (0 != putenv(envstr)) {
             stringstream ss;
@@ -972,13 +994,19 @@ JNIEXPORT jlong JNICALL
     }
 
     // set the options flags
-    if (addUnallocSpace) {
-        tskAuto->setAddUnallocSpace(true, 500*1024*1024);
-    }
-    else {
+    tskAuto->setAddFileSystems(addFileSystems?true:false);
+    if (addFileSystems) {
+        if (addUnallocSpace) {
+            tskAuto->setAddUnallocSpace(true, 500*1024*1024);
+        }
+        else {
+            tskAuto->setAddUnallocSpace(false);
+        }
+        tskAuto->setNoFatFsOrphans(skipFatFsOrphans?true:false);
+    } else {
         tskAuto->setAddUnallocSpace(false);
+        tskAuto->setNoFatFsOrphans(true);
     }
-    tskAuto->setNoFatFsOrphans(noFatFsOrphans?true:false);
 
     // we don't use the block map and it slows it down
     tskAuto->createBlockMap(false);
@@ -989,7 +1017,6 @@ JNIEXPORT jlong JNICALL
     return (jlong) tskAuto;
 }
 
-
 /*
  * Add an image to a database using a pre-created process, which can be cancelled.
  * MUST call commitAddImg or revertAddImg afterwards once runAddImg returns.  If there is an 
diff --git a/bindings/java/jni/dataModel_SleuthkitJNI.h b/bindings/java/jni/dataModel_SleuthkitJNI.h
index 07b59c69f..97e77e530 100644
--- a/bindings/java/jni/dataModel_SleuthkitJNI.h
+++ b/bindings/java/jni/dataModel_SleuthkitJNI.h
@@ -215,6 +215,14 @@ JNIEXPORT jobject JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbLookup
 JNIEXPORT jlong JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_initAddImgNat
   (JNIEnv *, jclass, jlong, jstring, jboolean, jboolean);
 
+/*
+ * Class:     org_sleuthkit_datamodel_SleuthkitJNI
+ * Method:    initializeAddImgNat
+ * Signature: (JLjava/lang/String;ZZZ)J
+ */
+JNIEXPORT jlong JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_initializeAddImgNat
+  (JNIEnv *, jclass, jlong, jstring, jboolean, jboolean, jboolean);
+
 /*
  * Class:     org_sleuthkit_datamodel_SleuthkitJNI
  * Method:    runAddImgNat
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java
index 188422940..156951a19 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java
@@ -21,6 +21,7 @@
 import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.IOException;
+import java.nio.file.Path;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -29,6 +30,9 @@
 import java.util.List;
 import java.util.Map;
 import java.util.TimeZone;
+import java.util.UUID;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 import org.sleuthkit.datamodel.TskData.TSK_FS_ATTR_TYPE_ENUM;
 
 /**
@@ -63,7 +67,7 @@ private SleuthkitJNI() {
 
 	/**
 	 * Encapsulates a handle to a SleuthKit case database with support for
-	 * adding images to the database. Adding an image
+	 * adding images to the database.
 	 */
 	public static class CaseDbHandle {
 
@@ -125,21 +129,54 @@ void free() throws TskCoreException {
 			SleuthkitJNI.closeCaseDbNat(caseDbPointer);
 		}
 
+		/**
+		 * Adds an image to the case database. For finer-grained control of the
+		 * process of adding the image, call CaseDbHandle.initAddImageProcess
+		 * instead.
+		 *
+		 * @param deviceObjId      The object id of the device associated with
+		 *                         the image.
+		 * @param imageFilePaths   The image file paths.
+		 * @param timeZone         The time zone for the image.
+		 * @param addFileSystems   Pass true to attempt to add file systems
+		 *                         within the image to the case database.
+		 * @param addUnallocSpace  Pass true to create virtual files for
+		 *                         unallocated space. Ignored if addFileSystems
+		 *                         is false.
+		 * @param skipFatFsOrphans Pass true to skip processing of orphan files
+		 *                         for FAT file systems. Ignored if
+		 *                         addFileSystems is false.
+		 *
+		 * @return The object id of the image.
+		 *
+		 * @throws TskCoreException if there is an error adding the image to
+		 *                          case database.
+		 */
+		long addImage(long deviceObjId, List<String> imageFilePaths, String timeZone, boolean addFileSystems, boolean addUnallocSpace, boolean skipFatFsOrphans) throws TskCoreException {
+			try {
+				long tskAutoDbPointer = initializeAddImgNat(caseDbPointer, timezoneLongToShort(timeZone), addFileSystems, addUnallocSpace, skipFatFsOrphans);
+				runAddImgNat(tskAutoDbPointer, UUID.randomUUID().toString(), imageFilePaths.toArray(new String[0]), imageFilePaths.size(), timeZone);
+				return commitAddImgNat(tskAutoDbPointer);
+			} catch (TskDataException ex) {
+				throw new TskCoreException("Error adding image to case database", ex);
+			}
+		}
+
 		/**
 		 * Initializes a multi-step process for adding an image to the case
 		 * database.
 		 *
-		 * @param timeZone        The time zone of the image.
-		 * @param addUnallocSpace Pass true to create virtual files for
-		 *                        unallocated space.
-		 * @param noFatFsOrphans  Pass true to skip processing of orphan files
-		 *                        for FAT file systems.
+		 * @param timeZone         The time zone of the image.
+		 * @param addUnallocSpace  Pass true to create virtual files for
+		 *                         unallocated space.
+		 * @param skipFatFsOrphans Pass true to skip processing of orphan files
+		 *                         for FAT file systems.
 		 *
 		 * @return An object that can be used to exercise fine-grained control
 		 *         of the process of adding the image to the case database.
 		 */
-		AddImageProcess initAddImageProcess(String timeZone, boolean addUnallocSpace, boolean noFatFsOrphans) {
-			return new AddImageProcess(timeZone, addUnallocSpace, noFatFsOrphans);
+		AddImageProcess initAddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFatFsOrphans) {
+			return new AddImageProcess(timeZone, addUnallocSpace, skipFatFsOrphans);
 		}
 
 		/**
@@ -150,23 +187,23 @@ public class AddImageProcess {
 
 			private final String timeZone;
 			private final boolean addUnallocSpace;
-			private final boolean noFatFsOrphans;
+			private final boolean skipFatFsOrphans;
 			private volatile long tskAutoDbPointer;
 
 			/**
 			 * Consdtructs an object that encapsulates a multi-step process to
 			 * add an image to the case database.
 			 *
-			 * @param timeZone        The time zone of the image.
-			 * @param addUnallocSpace Pass true to create virtual files for
-			 *                        unallocated space.
-			 * @param noFatFsOrphans  Pass true to skip processing of orphan
-			 *                        files for FAT file systems.
+			 * @param timeZone         The time zone of the image.
+			 * @param addUnallocSpace  Pass true to create virtual files for
+			 *                         unallocated space.
+			 * @param skipFatFsOrphans Pass true to skip processing of orphan
+			 *                         files for FAT file systems.
 			 */
-			private AddImageProcess(String timeZone, boolean addUnallocSpace, boolean noFatFsOrphans) {
+			private AddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFatFsOrphans) {
 				this.timeZone = timeZone;
 				this.addUnallocSpace = addUnallocSpace;
-				this.noFatFsOrphans = noFatFsOrphans;
+				this.skipFatFsOrphans = skipFatFsOrphans;
 				tskAutoDbPointer = 0;
 			}
 
@@ -193,7 +230,7 @@ public void run(String deviceId, String[] imageFilePaths) throws TskCoreExceptio
 				}
 
 				synchronized (this) {
-					tskAutoDbPointer = initAddImgNat(caseDbPointer, timezoneLongToShort(timeZone), addUnallocSpace, noFatFsOrphans);
+					tskAutoDbPointer = initAddImgNat(caseDbPointer, timezoneLongToShort(timeZone), addUnallocSpace, skipFatFsOrphans);
 				}
 				if (0 == tskAutoDbPointer) {
 					throw new TskCoreException("initAddImgNat returned a NULL TskAutoDb pointer");
@@ -239,7 +276,7 @@ public synchronized void revert() throws TskCoreException {
 			 * Completes the process of adding an image to the case database
 			 * that was started by calling AddImageProcess.run.
 			 *
-			 * @return The object id of the image that was added. 
+			 * @return The object id of the image that was added.
 			 *
 			 * @throws TskCoreException if a critical error occurs within the
 			 *                          SleuthKit.
@@ -256,7 +293,8 @@ public synchronized long commit() throws TskCoreException {
 			}
 
 			/**
-			 * Gets the file system directory currently being processed by the SleuthKit.
+			 * Gets the file system directory currently being processed by the
+			 * SleuthKit.
 			 *
 			 * @return The directory
 			 */
@@ -959,7 +997,9 @@ public static long findDeviceSize(String devPath) throws TskCoreException {
 
 	private static native HashHitInfo hashDbLookupVerbose(String hash, int dbHandle) throws TskCoreException;
 
-	private static native long initAddImgNat(long db, String timezone, boolean addUnallocSpace, boolean noFatFsOrphans) throws TskCoreException;
+	private static native long initAddImgNat(long db, String timezone, boolean addUnallocSpace, boolean skipFatFsOrphans) throws TskCoreException;
+
+	private static native long initializeAddImgNat(long db, String timezone, boolean addFileSystems, boolean addUnallocSpace, boolean skipFatFsOrphans) throws TskCoreException;
 
 	private static native void runAddImgNat(long process, String deviceId, String[] imgPath, int splits, String timezone) throws TskCoreException, TskDataException;
 
diff --git a/tsk/auto/auto_db.cpp b/tsk/auto/auto_db.cpp
index 23ee066db..949be1345 100644
--- a/tsk/auto/auto_db.cpp
+++ b/tsk/auto/auto_db.cpp
@@ -53,6 +53,7 @@ TskAutoDb::TskAutoDb(TskDb * a_db, TSK_HDB_INFO * a_NSRLDb, TSK_HDB_INFO * a_kno
         m_fileHashFlag = true;
     else
         m_fileHashFlag = false;
+    m_addFileSystems = true;
     m_noFatFsOrphans = false;
     m_addUnallocSpace = false;
     m_chunkSize = -1;
@@ -90,6 +91,11 @@ void
     m_fileHashFlag = flag;
 }
 
+void TskAutoDb::setAddFileSystems(bool addFileSystems)
+{
+    m_addFileSystems = addFileSystems;
+}
+
 void TskAutoDb::setNoFatFsOrphans(bool noFatFsOrphans)
 {
     m_noFatFsOrphans = noFatFsOrphans;
@@ -447,7 +453,11 @@ uint8_t
         return 1;
     }
     
-    return addFilesInImgToDb();
+    if (m_addFileSystems) {
+        return addFilesInImgToDb();
+    } else {
+        return 0;
+    }
 }
 
 
@@ -506,7 +516,11 @@ uint8_t
         return 1;
     }
 
-    return addFilesInImgToDb();
+    if (m_addFileSystems) {
+        return addFilesInImgToDb();
+    } else {
+        return 0;
+    }
 }
 #endif
 
diff --git a/tsk/auto/tsk_case_db.h b/tsk/auto/tsk_case_db.h
index 302213302..5dcd5e39f 100644
--- a/tsk/auto/tsk_case_db.h
+++ b/tsk/auto/tsk_case_db.h
@@ -64,6 +64,12 @@ class TskAutoDb:public TskAuto {
      */
     virtual void hashFiles(bool flag);
 
+    /**
+     * Sets whether or not the file systems for an image should be added when 
+     * the image is added to the case database. The default value is true. 
+     */
+    void TskAutoDb::setAddFileSystems(bool addFileSytems);
+
     /**
      * Skip processing of orphans on FAT filesystems.  
      * This will make the loading of the database much faster
@@ -122,6 +128,7 @@ class TskAutoDb:public TskAuto {
     bool m_imgTransactionOpen;
     TSK_HDB_INFO * m_NSRLDb;
     TSK_HDB_INFO * m_knownBadDb;
+    bool m_addFileSystems;
     bool m_noFatFsOrphans;
     bool m_addUnallocSpace;
     int64_t m_chunkSize;
-- 
GitLab