diff --git a/bindings/java/jni/auto_db_java.cpp b/bindings/java/jni/auto_db_java.cpp index 7cc3888cf390a52966d1f52d3cfa0e432844ae71..20e915d81c21412a12f83536ad618421b4cfcc1a 100644 --- a/bindings/java/jni/auto_db_java.cpp +++ b/bindings/java/jni/auto_db_java.cpp @@ -110,7 +110,7 @@ TskAutoDbJava::initializeJni(JNIEnv * jniEnv, jobject jobj) { return TSK_ERR; } - m_addFileMethodID = m_jniEnv->GetMethodID(m_callbackClass, "addFile", "(JJJIIILjava/lang/String;JJIIIIJJJJJIIILjava/lang/String;Ljava/lang/String;JJJ)J"); + m_addFileMethodID = m_jniEnv->GetMethodID(m_callbackClass, "addFile", "(JJJIIILjava/lang/String;JJIIIIJJJJJIIILjava/lang/String;Ljava/lang/String;JJJLjava/lang/String;)J"); if (m_addFileMethodID == NULL) { return TSK_ERR; } @@ -631,6 +631,17 @@ TskAutoDbJava::addFile(TSK_FS_FILE* fs_file, } TSK_INUM_T par_meta_addr = fs_file->name->par_addr; + char *sid_str = NULL; + jstring sidj = NULL; // return null across JNI if sid is not available + + if (tsk_fs_file_get_owner_sid(fs_file, &sid_str) == 0) { + if (createJString(sid_str, sidj) != TSK_OK) { + free(sid_str); + return TSK_ERR; + } + free(sid_str); + } + // Add the file to the database jlong ret_val = m_jniEnv->CallLongMethod(m_javaDbObj, m_addFileMethodID, parObjId, fsObjId, @@ -643,7 +654,7 @@ TskAutoDbJava::addFile(TSK_FS_FILE* fs_file, (unsigned long long)crtime, (unsigned long long)ctime, (unsigned long long) atime, (unsigned long long) mtime, meta_mode, gid, uid, pathj, extj, - (uint64_t)meta_seq, par_meta_addr, par_seqj); + (uint64_t)meta_seq, par_meta_addr, par_seqj, sidj); if (ret_val < 0) { free(name); @@ -690,7 +701,7 @@ TskAutoDbJava::addFile(TSK_FS_FILE* fs_file, (unsigned long long)crtime, (unsigned long long)ctime, (unsigned long long) atime, (unsigned long long) mtime, meta_mode, gid, uid, // md5TextPtr, known, pathj, slackExtj, - (uint64_t)meta_seq, par_meta_addr, par_seqj); + (uint64_t)meta_seq, par_meta_addr, par_seqj, sidj); if (ret_val < 0) { free(name); diff --git a/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java b/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java index 512ebef21e67fb94ca685b34c2ba57912a60a3cd..a0bbe2c3763a1717871637de8cd58b18fb5697c3 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java +++ b/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java @@ -21,11 +21,13 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.ResourceBundle; import java.util.Set; import java.util.SortedSet; @@ -91,6 +93,8 @@ public abstract class AbstractFile extends AbstractContent { private long dataSourceObjectId; private final String extension; + private final String uidStr; // SID/uid + private final long userRowId; /** * Initializes common fields used by AbstactFile implementations (objects in * tsk_files table) @@ -125,8 +129,11 @@ public abstract class AbstractFile extends AbstractContent { * unknown (default) * @param parentPath * @param mimeType The MIME type of the file, can be null. - * @param extension The extension part of the file name (not + * @param extension The extension part of the file name (not * including the '.'), can be null. + * @param uidStr String uid/SID, can be null if not available. + * @param userRowId The row id of user in tsk_os_accounts. + * */ AbstractFile(SleuthkitCase db, long objId, @@ -144,7 +151,9 @@ public abstract class AbstractFile extends AbstractContent { String md5Hash, String sha256Hash, FileKnown knownState, String parentPath, String mimeType, - String extension) { + String extension, + String uidStr, + long userRowId) { super(db, objId, name); this.dataSourceObjectId = dataSourceObjectId; this.attrType = attrType; @@ -176,6 +185,8 @@ public abstract class AbstractFile extends AbstractContent { this.mimeType = mimeType; this.extension = extension == null ? "" : extension; this.encodingType = TskData.EncodingType.NONE; + this.uidStr = uidStr; + this.userRowId = userRowId; } /** @@ -1174,6 +1185,52 @@ public void save() throws TskCoreException { } } + /** + * Get the uidStr. + * + * @return String uid. Returns an empty string if no uid is recorded. + */ + public String getUidStr() { + return Objects.nonNull(uidStr) ? uidStr + : ""; + } + + /** + * Get the row id of the owing user. + * + * @return rowId, or OsAccount.NO_USER + */ + public long getUserRowId() { + return userRowId; + } + + /** + * Gets the user for the file. + * + * @return OsAccount + * + * @throws TskCoreException If there is an error getting the user + */ + public OsAccount getUser() throws TskCoreException { + + // run a query to get the user row id from the tsk_files + String queryStr = "SELECT os_account_row_id FROM tsk_files WHERE obj_id = " + this.getId(); + try (SleuthkitCase.CaseDbConnection connection = getSleuthkitCase().getConnection(); + Statement statement = connection.createStatement(); + ResultSet resultSet = connection.executeQuery(statement, queryStr);) { + + if (resultSet.next()) { + long userRowId = resultSet.getLong("os_account_row_id"); + return getSleuthkitCase().getOsAccountManager().getOsAccount(userRowId); + } else { + throw new TskCoreException(String.format("Error getting user account id for file (obj_id = %d)", this.getId())); + } + + } catch (SQLException ex) { + throw new TskCoreException(String.format("Error getting user account id for file (obj_id = %d)", this.getId()), ex); + } + } + @Override public BlackboardArtifact newArtifact(int artifactTypeID) throws TskCoreException { // don't let them make more than 1 GEN_INFO @@ -1221,7 +1278,7 @@ protected AbstractFile(SleuthkitCase db, long objId, TskData.TSK_FS_ATTR_TYPE_EN TSK_FS_NAME_TYPE_ENUM dirType, TSK_FS_META_TYPE_ENUM metaType, TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size, long ctime, long crtime, long atime, long mtime, short modes, int uid, int gid, String md5Hash, FileKnown knownState, String parentPath) { - this(db, objId, db.getDataSourceObjectId(objId), attrType, (int) attrId, name, fileType, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, null, knownState, parentPath, null, null); + this(db, objId, db.getDataSourceObjectId(objId), attrType, (int) attrId, name, fileType, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, null, knownState, parentPath, null, null, OsAccount.NULL_UID_STR, OsAccount.NO_USER); } /** @@ -1266,7 +1323,7 @@ protected AbstractFile(SleuthkitCase db, long objId, TskData.TSK_FS_ATTR_TYPE_EN String name, TskData.TSK_DB_FILES_TYPE_ENUM fileType, long metaAddr, int metaSeq, TSK_FS_NAME_TYPE_ENUM dirType, TSK_FS_META_TYPE_ENUM metaType, TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size, long ctime, long crtime, long atime, long mtime, short modes, int uid, int gid, String md5Hash, FileKnown knownState, String parentPath, String mimeType) { - this(db, objId, dataSourceObjectId, attrType, (int) attrId, name, fileType, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, null, knownState, parentPath, null, null); + this(db, objId, dataSourceObjectId, attrType, (int) attrId, name, fileType, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, null, knownState, parentPath, null, null, OsAccount.NULL_UID_STR, OsAccount.NO_USER); } /** diff --git a/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java b/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java index b6c262f9d57b0b1d532201108e8ef08dd20a109b..34bf523ad858a212e3f2e41bfb9ba1bfdfcb8407 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java +++ b/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java @@ -208,9 +208,12 @@ private void createFileTables(Statement stmt) throws SQLException { + "mtime " + dbQueryHelper.getBigIntType() + ", mode INTEGER, uid INTEGER, gid INTEGER, md5 TEXT, sha256 TEXT, " + "known INTEGER, " + "parent_path TEXT, mime_type TEXT, extension TEXT, " + + "uid_str TEXT, " + + "os_account_row_id " + dbQueryHelper.getBigIntType() + ", " + "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " + "FOREIGN KEY(fs_obj_id) REFERENCES tsk_fs_info(obj_id) ON DELETE CASCADE, " - + "FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id) ON DELETE CASCADE)"); + + "FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id) ON DELETE CASCADE, " + + "FOREIGN KEY(os_account_row_id) REFERENCES tsk_os_accounts(id)) " ); stmt.execute("CREATE TABLE file_encoding_types (encoding_type INTEGER PRIMARY KEY, name TEXT NOT NULL)"); @@ -270,7 +273,7 @@ private void createArtifactTables(Statement stmt) throws SQLException { + "value_text TEXT, value_int32 INTEGER, value_int64 " + dbQueryHelper.getBigIntType() + ", value_double NUMERIC(20, 10), " + "FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id) ON DELETE CASCADE, " + "FOREIGN KEY(artifact_type_id) REFERENCES blackboard_artifact_types(artifact_type_id), " - + "FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))"); + + "FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))"); } private void createAnalysisResultsTables(Statement stmt) throws SQLException { @@ -408,6 +411,23 @@ private void createAccountTables(Statement stmt) throws SQLException { + "FOREIGN KEY(account2_id) REFERENCES accounts(account_id), " + "FOREIGN KEY(relationship_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " + "FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)"); + + stmt.execute("CREATE TABLE tsk_os_accounts (id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, " + + "data_source_obj_id " + dbQueryHelper.getBigIntType() + " NOT NULL, " + + "user_name TEXT, " // username if available + + "realm TEXT, " // domain or host + + "unique_id TEXT, " // SID/UID, if available + + "signature TEXT NOT NULL, " // realm/username or sid + + "artifact_obj_id " + dbQueryHelper.getBigIntType() + "," + + "UNIQUE(data_source_obj_id, signature), " + + "FOREIGN KEY(artifact_obj_id) REFERENCES blackboard_artifacts(artifact_obj_id) ON DELETE CASCADE, " + + "FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id))"); + + stmt.execute("CREATE TABLE tsk_data_artifact_data (id " + dbQueryHelper.getBigIntType() + " NOT NULL, " + + "artifact_obj_id " + dbQueryHelper.getBigIntType() + " NOT NULL, " + + "os_account_row_id " + dbQueryHelper.getBigIntType() + " NOT NULL, " + + "FOREIGN KEY(artifact_obj_id) REFERENCES blackboard_artifacts(artifact_obj_id) ON DELETE CASCADE, " + + "FOREIGN KEY(os_account_row_id) REFERENCES tsk_os_accounts(id)) "); } private void createEventTables(Statement stmt) throws SQLException { diff --git a/bindings/java/src/org/sleuthkit/datamodel/DataArtifact.java b/bindings/java/src/org/sleuthkit/datamodel/DataArtifact.java new file mode 100644 index 0000000000000000000000000000000000000000..996535bb1c714e13cdd4d90fee8e1c802789a0f3 --- /dev/null +++ b/bindings/java/src/org/sleuthkit/datamodel/DataArtifact.java @@ -0,0 +1,50 @@ +/* + * Sleuth Kit Data Model + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier <at> sleuthkit <dot> org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.datamodel; + + +/** + * DataArtifact is a category of artifact types that are simply data directly + * extracted from a data source. + * + */ +public class DataArtifact extends BlackboardArtifact { + + private final OsAccount osAccount; + + + DataArtifact(SleuthkitCase sleuthkitCase, long artifactID, long sourceObjId, long artifactObjId, long dataSourceObjId, int artifactTypeID, String artifactTypeName, String displayName, ReviewStatus reviewStatus, OsAccount osAccount) { + super(sleuthkitCase, artifactID, sourceObjId, artifactObjId, dataSourceObjId, artifactTypeID, artifactTypeName, displayName, reviewStatus); + this.osAccount = osAccount; + } + + + /** + * Gets the user for this artifact. + * + * @return OsAccount + * + * @throws TskCoreException If there is an error getting the user + */ + public OsAccount getOsAccount() throws TskCoreException { + return osAccount; + } + + +} diff --git a/bindings/java/src/org/sleuthkit/datamodel/DerivedFile.java b/bindings/java/src/org/sleuthkit/datamodel/DerivedFile.java index ef147fb10c980eb874594e42931342e0ba336dd2..0e07226d7499b3d37c2b15af3701e94d030c7bd0 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/DerivedFile.java +++ b/bindings/java/src/org/sleuthkit/datamodel/DerivedFile.java @@ -82,6 +82,10 @@ public class DerivedFile extends AbstractFile { * @param encodingType The encoding type of the file. * @param extension The extension part of the file name (not * including the '.'), can be null. + * @param uidStr String UID of the user as found in in the file + * system, can be null. + * @param osAccountRowId Row id of the user in the tsk_os_accounts + * table. */ DerivedFile(SleuthkitCase db, long objId, @@ -97,12 +101,14 @@ public class DerivedFile extends AbstractFile { long parentId, String mimeType, TskData.EncodingType encodingType, - String extension) { + String extension, + String uidStr, + long osAccountRowId) { // TODO (AUT-1904): The parent id should be passed to AbstractContent // through the class hierarchy contructors. super(db, objId, dataSourceObjectId, TskData.TSK_FS_ATTR_TYPE_ENUM.TSK_FS_ATTR_TYPE_DEFAULT, 0, name, TSK_DB_FILES_TYPE_ENUM.LOCAL, 0L, 0, dirType, metaType, dirFlag, - metaFlags, size, ctime, crtime, atime, mtime, (short) 0, 0, 0, md5Hash, sha256Hash, knownState, parentPath, mimeType, extension); + metaFlags, size, ctime, crtime, atime, mtime, (short) 0, 0, 0, md5Hash, sha256Hash, knownState, parentPath, mimeType, extension, uidStr, osAccountRowId); setLocalFilePath(localPath); setEncodingType(encodingType); } @@ -306,7 +312,7 @@ protected DerivedFile(SleuthkitCase db, this(db, objId, db.getDataSourceObjectId(objId), name, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, md5Hash, null, knownState, - parentPath, localPath, parentId, null, TskData.EncodingType.NONE, null); + parentPath, localPath, parentId, null, TskData.EncodingType.NONE, null, OsAccount.NULL_UID_STR, OsAccount.NO_USER); } } diff --git a/bindings/java/src/org/sleuthkit/datamodel/Directory.java b/bindings/java/src/org/sleuthkit/datamodel/Directory.java index 39b0c62188ef261354eedeb1596ba6f6f2fd0e6f..3aec920c6226d804024f8c2b497912831a51208a 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/Directory.java +++ b/bindings/java/src/org/sleuthkit/datamodel/Directory.java @@ -72,6 +72,10 @@ public class Directory extends FsContent { * @param knownState The known state of the file from a hash * database lookup, null if not yet looked up. * @param parentPath The path of the parent of the file. + * @param uidStr String UID of the user as found in in the file + * system, can be null. + * @param osAccountRowId Row id of the user in the tsk_os_accounts + * table. */ Directory(SleuthkitCase db, long objId, @@ -85,8 +89,9 @@ public class Directory extends FsContent { long size, long ctime, long crtime, long atime, long mtime, short modes, int uid, int gid, - String md5Hash, String sha256Hash, FileKnown knownState, String parentPath) { - super(db, objId, dataSourceObjectId, fsObjId, attrType, attrId, name, TskData.TSK_DB_FILES_TYPE_ENUM.FS, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, sha256Hash, knownState, parentPath, null, null); + String md5Hash, String sha256Hash, FileKnown knownState, String parentPath, + String uidStr, long osAccountRowId ) { + super(db, objId, dataSourceObjectId, fsObjId, attrType, attrId, name, TskData.TSK_DB_FILES_TYPE_ENUM.FS, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, sha256Hash, knownState, parentPath, null, null, uidStr, osAccountRowId); } /** @@ -247,6 +252,6 @@ protected Directory(SleuthkitCase db, long ctime, long crtime, long atime, long mtime, short modes, int uid, int gid, String md5Hash, FileKnown knownState, String parentPath) { - this(db, objId, dataSourceObjectId, fsObjId, attrType, (int) attrId, name, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, null, knownState, parentPath); + this(db, objId, dataSourceObjectId, fsObjId, attrType, (int) attrId, name, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, null, knownState, parentPath, OsAccount.NULL_UID_STR, OsAccount.NO_USER); } } diff --git a/bindings/java/src/org/sleuthkit/datamodel/File.java b/bindings/java/src/org/sleuthkit/datamodel/File.java index c6758c0ff88657acb513b55810acbc445b518df3..26315e1d07465f50f3e208393d58a49055c7cccc 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/File.java +++ b/bindings/java/src/org/sleuthkit/datamodel/File.java @@ -76,6 +76,10 @@ public class File extends FsContent { * yet been determined. * @param extension The extension part of the file name (not * including the '.'), can be null. + * @param uidStr String UID of the user as found in in the file + * system, can be null. + * @param osAccountRowId Row id of the user in the tsk_os_accounts + * table. */ File(SleuthkitCase db, long objId, @@ -90,8 +94,10 @@ public class File extends FsContent { long ctime, long crtime, long atime, long mtime, short modes, int uid, int gid, String md5Hash, String sha256Hash, FileKnown knownState, String parentPath, String mimeType, - String extension) { - super(db, objId, dataSourceObjectId, fsObjId, attrType, attrId, name, TskData.TSK_DB_FILES_TYPE_ENUM.FS, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, sha256Hash, knownState, parentPath, mimeType, extension); + String extension, + String uidStr, + long osAccountRowId) { + super(db, objId, dataSourceObjectId, fsObjId, attrType, attrId, name, TskData.TSK_DB_FILES_TYPE_ENUM.FS, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, sha256Hash, knownState, parentPath, mimeType, extension, uidStr, osAccountRowId); } /** @@ -245,6 +251,6 @@ protected File(SleuthkitCase db, String name, long metaAddr, int metaSeq, TSK_FS_NAME_TYPE_ENUM dirType, TSK_FS_META_TYPE_ENUM metaType, TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size, long ctime, long crtime, long atime, long mtime, short modes, int uid, int gid, String md5Hash, FileKnown knownState, String parentPath, String mimeType) { - this(db, objId, dataSourceObjectId, fsObjId, attrType, (int) attrId, name, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, null, knownState, parentPath, mimeType, null); + this(db, objId, dataSourceObjectId, fsObjId, attrType, (int) attrId, name, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, null, knownState, parentPath, mimeType, null, OsAccount.NULL_UID_STR, OsAccount.NO_USER); } } diff --git a/bindings/java/src/org/sleuthkit/datamodel/FsContent.java b/bindings/java/src/org/sleuthkit/datamodel/FsContent.java index aa4bb739d06a0bad71b343ab9766c75f5f38511a..2f4afaefcc874af9d1118c65150e22379304ae5e 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/FsContent.java +++ b/bindings/java/src/org/sleuthkit/datamodel/FsContent.java @@ -105,6 +105,10 @@ public abstract class FsContent extends AbstractFile { * yet been determined. * @param extension The extension part of the file name (not * including the '.'), can be null. + * @param uidStr String UID of the user as found in in the file + * system, can be null. + * @param osAccountRowId Row id of the user in the tsk_os_accounts + * table. */ @SuppressWarnings("deprecation") FsContent(SleuthkitCase db, @@ -123,8 +127,10 @@ public abstract class FsContent extends AbstractFile { String md5Hash, String sha256Hash, FileKnown knownState, String parentPath, String mimeType, - String extension) { - super(db, objId, dataSourceObjectId, attrType, attrId, name, fileType, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, sha256Hash, knownState, parentPath, mimeType, extension); + String extension, + String uidStr, + long osAccountRowId) { + super(db, objId, dataSourceObjectId, attrType, attrId, name, fileType, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, sha256Hash, knownState, parentPath, mimeType, extension, uidStr, osAccountRowId); this.fsObjId = fsObjId; } @@ -383,7 +389,7 @@ public String toString(boolean preserveState) { String name, long metaAddr, int metaSeq, TSK_FS_NAME_TYPE_ENUM dirType, TSK_FS_META_TYPE_ENUM metaType, TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size, long ctime, long crtime, long atime, long mtime, short modes, int uid, int gid, String md5Hash, FileKnown knownState, String parentPath) { - this(db, objId, db.getDataSourceObjectId(objId), fsObjId, attrType, (int) attrId, name, TSK_DB_FILES_TYPE_ENUM.FS, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, null, knownState, parentPath, null, null); + this(db, objId, db.getDataSourceObjectId(objId), fsObjId, attrType, (int) attrId, name, TSK_DB_FILES_TYPE_ENUM.FS, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, null, knownState, parentPath, null, null, OsAccount.NULL_UID_STR, OsAccount.NO_USER); } /** @@ -442,6 +448,6 @@ public String toString(boolean preserveState) { String name, long metaAddr, int metaSeq, TSK_FS_NAME_TYPE_ENUM dirType, TSK_FS_META_TYPE_ENUM metaType, TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size, long ctime, long crtime, long atime, long mtime, short modes, int uid, int gid, String md5Hash, FileKnown knownState, String parentPath, String mimeType) { - this(db, objId, dataSourceObjectId, fsObjId, attrType, (int) attrId, name, TSK_DB_FILES_TYPE_ENUM.FS, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, null, knownState, parentPath, mimeType, null); + this(db, objId, dataSourceObjectId, fsObjId, attrType, (int) attrId, name, TSK_DB_FILES_TYPE_ENUM.FS, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, null, knownState, parentPath, mimeType, null, OsAccount.NULL_UID_STR, OsAccount.NO_USER); } } diff --git a/bindings/java/src/org/sleuthkit/datamodel/LayoutFile.java b/bindings/java/src/org/sleuthkit/datamodel/LayoutFile.java index ab98c64e75a8ffc50219df350fbe2c63b2a539f6..9a44ed4d0b2a73e2d83fcc828c100a137f491125 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/LayoutFile.java +++ b/bindings/java/src/org/sleuthkit/datamodel/LayoutFile.java @@ -81,6 +81,10 @@ public class LayoutFile extends AbstractFile { * @param parentPath The path of the parent of the file. * @param mimeType The MIME type of the file, null if it has not * yet been determined. + * @param uidStr String UID of the user as found in in the file + * system, can be null. + * @param osAccountRowId Row id of the user in the tsk_os_accounts + * table. */ LayoutFile(SleuthkitCase db, long objId, @@ -92,8 +96,11 @@ public class LayoutFile extends AbstractFile { long size, long ctime, long crtime, long atime, long mtime, String md5Hash, String sha256Hash, FileKnown knownState, - String parentPath, String mimeType) { - super(db, objId, dataSourceObjectId, TSK_FS_ATTR_TYPE_ENUM.TSK_FS_ATTR_TYPE_DEFAULT, 0, name, fileType, 0L, 0, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, (short) 0, 0, 0, md5Hash, sha256Hash, knownState, parentPath, mimeType, SleuthkitCase.extractExtension(name)); + String parentPath, String mimeType, + String uidStr, + long osAccountRowId) { + + super(db, objId, dataSourceObjectId, TSK_FS_ATTR_TYPE_ENUM.TSK_FS_ATTR_TYPE_DEFAULT, 0, name, fileType, 0L, 0, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, (short) 0, 0, 0, md5Hash, sha256Hash, knownState, parentPath, mimeType, SleuthkitCase.extractExtension(name), uidStr, osAccountRowId); } /** @@ -280,6 +287,6 @@ protected LayoutFile(SleuthkitCase db, long objId, String name, TSK_FS_NAME_TYPE_ENUM dirType, TSK_FS_META_TYPE_ENUM metaType, TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size, String md5Hash, FileKnown knownState, String parentPath) { - this(db, objId, db.getDataSourceObjectId(objId), name, fileType, dirType, metaType, dirFlag, metaFlags, size, 0L, 0L, 0L, 0L, md5Hash, null, knownState, parentPath, null); + this(db, objId, db.getDataSourceObjectId(objId), name, fileType, dirType, metaType, dirFlag, metaFlags, size, 0L, 0L, 0L, 0L, md5Hash, null, knownState, parentPath, null, OsAccount.NULL_UID_STR, OsAccount.NO_USER); } } diff --git a/bindings/java/src/org/sleuthkit/datamodel/LocalFile.java b/bindings/java/src/org/sleuthkit/datamodel/LocalFile.java index 99abf74e70cd7f77cbaa062e0fa1316072064611..bf5edbd804d22f08b605856e57722a2b86eab861 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/LocalFile.java +++ b/bindings/java/src/org/sleuthkit/datamodel/LocalFile.java @@ -74,6 +74,10 @@ public class LocalFile extends AbstractFile { * @param encodingType The encoding type of the file. * @param extension The extension part of the file name (not * including the '.'), can be null. + * @param uidStr String UID of the user as found in in the file + * system, can be null. + * @param osAccountRowId Row id of the user in the tsk_os_accounts + * table. */ LocalFile(SleuthkitCase db, long objId, @@ -88,10 +92,12 @@ public class LocalFile extends AbstractFile { long dataSourceObjectId, String localPath, TskData.EncodingType encodingType, - String extension) { + String extension, + String uidStr, + long osAccountRowId) { super(db, objId, dataSourceObjectId, TSK_FS_ATTR_TYPE_ENUM.TSK_FS_ATTR_TYPE_DEFAULT, 0, name, fileType, 0L, 0, dirType, metaType, dirFlag, - metaFlags, size, ctime, crtime, atime, mtime, (short) 0, 0, 0, md5Hash, sha256Hash, knownState, parentPath, mimeType, extension); + metaFlags, size, ctime, crtime, atime, mtime, (short) 0, 0, 0, md5Hash, sha256Hash, knownState, parentPath, mimeType, extension, uidStr, osAccountRowId); // TODO (AUT-1904): The parent id should be passed to AbstractContent // through the class hierarchy contructors, using // AbstractContent.UNKNOWN_ID as needed. @@ -222,7 +228,7 @@ protected LocalFile(SleuthkitCase db, AbstractContent.UNKNOWN_ID, parentPath, db.getDataSourceObjectId(objId), localPath, - TskData.EncodingType.NONE, null); + TskData.EncodingType.NONE, null, OsAccount.NULL_UID_STR, OsAccount.NO_USER); } /** diff --git a/bindings/java/src/org/sleuthkit/datamodel/OsAccount.java b/bindings/java/src/org/sleuthkit/datamodel/OsAccount.java new file mode 100644 index 0000000000000000000000000000000000000000..829614322da8ef40a0a214af409a138f6796ba52 --- /dev/null +++ b/bindings/java/src/org/sleuthkit/datamodel/OsAccount.java @@ -0,0 +1,85 @@ +/* + * Sleuth Kit Data Model + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier <at> sleuthkit <dot> org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.sleuthkit.datamodel; + +import java.util.Optional; + +/** + * Abstracts an OS User account. + * + * A user may own files and (some) artifacts. + * + */ +public class OsAccount { + + final static long NO_USER = -1; + final static String NULL_UID_STR = null; + + private final long rowId; // row id in the tsk_os_accounts table + private final long dataSourceObjId; + private final String userName; // user login name - may be null + private final String realm; // realm where the username is unique - a domain or a host name, may be null + private final String uniqueId; // a unique sid/uid, may be null + private final String signature; // some to uniquely identify this user - either the uid or the realm/userName. + private final Long artifactObjId; // object id of the backing artifact, may be null if one hasnt been created yet. + + + /** + * Creates an OsAccount with a realm/username and unique id, and signature + */ + OsAccount(long rowId, long dataSourceObjId, String userName, String realm, String uniqueId, String signature, long artifactObjId ) { + + this.rowId = rowId; + this.dataSourceObjId = dataSourceObjId; + this.uniqueId = uniqueId; + this.userName = userName; + this.realm = realm; + this.signature = signature; + this.artifactObjId = artifactObjId; + } + + public long getRowId() { + return rowId; + } + + public long getDataSourceObjId() { + return dataSourceObjId; + } + + public Optional<String> getUniqueId() { + return Optional.ofNullable(uniqueId); + } + + public String getSignature() { + return signature; + } + + public Optional<String> getRealm() { + return Optional.ofNullable(realm); + } + + public Optional<String> getUserName() { + return Optional.ofNullable(userName); + } + + public Optional<Long> getArtifactObjId() { + return Optional.ofNullable(artifactObjId); + } +} \ No newline at end of file diff --git a/bindings/java/src/org/sleuthkit/datamodel/OsAccountManager.java b/bindings/java/src/org/sleuthkit/datamodel/OsAccountManager.java new file mode 100644 index 0000000000000000000000000000000000000000..6dfe206e25b78ac7d021c28771e7ec08412c8be8 --- /dev/null +++ b/bindings/java/src/org/sleuthkit/datamodel/OsAccountManager.java @@ -0,0 +1,299 @@ +/* + * Sleuth Kit Data Model + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier <at> sleuthkit <dot> org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.datamodel; + +import com.google.common.base.Strings; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.sleuthkit.datamodel.SleuthkitCase.CaseDbConnection; +import org.sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction; + +/** + * Responsible for creating/updating/retrieving the OS user accounts for files + * and artifacts. + * + */ +public class OsAccountManager { + + private static final Logger LOGGER = Logger.getLogger(OsAccountManager.class.getName()); + + private final SleuthkitCase db; + + /** + * Construct a OsUserManager for the given SleuthkitCase. + * + * @param skCase The SleuthkitCase + * + */ + OsAccountManager(SleuthkitCase skCase) { + this.db = skCase; + } + + /** + * Gets or creates a OS user account with given unique id or given user name + * for the given data source. + * + * @param dataSourceId Data source object id. + * @param uniqueAccountId User sid/uid. + * @param userName User name. + * @param realm Realm within which the accountId/userName is + * unique. + * @param transaction Transaction to use for database operation. + * + * @return Row id of the row matching the given user id and data source. + */ + long createOrGetOsAccount(long dataSourceId, String uniqueAccountId, String userName, String realm, CaseDbTransaction transaction) throws TskCoreException { + + // ensure at least one of the two is supplied - unique id or user name + if (Strings.isNullOrEmpty(uniqueAccountId) && Strings.isNullOrEmpty(userName)) { + throw new IllegalArgumentException("Cannot create OS User with both uniqueId and userName as null."); + } + + CaseDbConnection connection = transaction.getConnection(); + + // First search for user by uniqueId + OsAccount osAccount = getOsAccountByUniqueId(dataSourceId, uniqueAccountId, connection); + if (osAccount != null) { + return osAccount.getRowId(); + } + + // search by user name + osAccount = getOsAccountByName(dataSourceId, userName, realm, connection); + if (osAccount != null) { + return osAccount.getRowId(); + } + + // could'nt find it, create a new account + return createOsAccount(dataSourceId, uniqueAccountId, userName, realm, connection); + + } + + /** + * Creates a user with the given uid, name, and realm. + * + * @param dataSourceId Data source object id. + * @param uniqueId User sid/uid. May be null/empty. + * @param userName User name. may be null or empty. + * @param realm Realm - domain or host name. + * @param connection Database connection to use. + * + * @return + * + * @throws TskCoreException + */ + private long createOsAccount(long dataSourceId, String uniqueId, String userName, String realm, CaseDbConnection connection) throws TskCoreException { + + String signature; + if (Strings.isNullOrEmpty(uniqueId) == false) { + signature = uniqueId; + } else { + if (Strings.isNullOrEmpty(realm)) { + signature = userName; + } else { + signature = String.format("%s/%s", realm, userName); + } + } + + db.acquireSingleUserCaseWriteLock(); + try { + String userInsertSQL = "INSERT INTO tsk_os_accounts(data_source_obj_id, user_name, realm, unique_id, signature, artifact_obj_id)" + + " VALUES (?, ?, ?, ?, ?, ?)"; // NON-NLS + + PreparedStatement preparedStatement = connection.getPreparedStatement(userInsertSQL, Statement.RETURN_GENERATED_KEYS); + preparedStatement.clearParameters(); + + preparedStatement.setLong(1, dataSourceId); + preparedStatement.setString(2, userName); + preparedStatement.setString(3, realm); + preparedStatement.setString(4, uniqueId); + preparedStatement.setString(5, signature); + preparedStatement.setNull(6, java.sql.Types.BIGINT); + + + connection.executeUpdate(preparedStatement); + + // Read back the row id + try (ResultSet resultSet = preparedStatement.getGeneratedKeys();) { + if (resultSet.next()) { + return resultSet.getLong(1); //last_insert_rowid() + } else { + throw new SQLException("Error executing " + userInsertSQL); + } + } + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, null, ex); + throw new TskCoreException(String.format("Error adding user with uniqueId = %s, userName = %s for data source object id %d", uniqueId, userName, dataSourceId), ex); + } finally { + db.releaseSingleUserCaseWriteLock(); + } + } + + /** + * Get the OsUser with the given unique user id and the specified data + * source. This should be called only if its certain that this user with + * uniqueId exists in the database. + * + * @param dataSourceId Data source object id. + * @param uniqueId User sid/uid. + * + * @return OsUser. + * + * @throws TskCoreException If there is an error getting the user. + * @throws IllegalArgumentException If no matching user is found. + */ + public OsAccount getOsAccount(long dataSourceId, String uniqueId) throws TskCoreException { + + try (CaseDbConnection connection = this.db.getConnection()) { + + OsAccount osAccount = getOsAccountByUniqueId(dataSourceId, uniqueId, connection); + if (osAccount == null) { + throw new IllegalArgumentException(String.format("No user found with id %s and data source object id = %d ", uniqueId, dataSourceId)); + } + + return osAccount; + } + } + + /** + * Gets a user by the uniqueId. Returns null if no matching user is found. + * + * @param dataSourceId + * @param uniqueId + * @param connection + * + * @return OsUser, null if no user with matching uniqueId is found. + * + * @throws TskCoreException + */ + private OsAccount getOsAccountByUniqueId(long dataSourceId, String uniqueId, CaseDbConnection connection) throws TskCoreException { + + String queryString = "SELECT * FROM tsk_os_accounts" + + " WHERE data_source_obj_id = " + dataSourceId + + " AND LOWER(unique_id) = LOWER('" + uniqueId + "')"; + + try (Statement s = connection.createStatement(); + ResultSet rs = connection.executeQuery(s, queryString)) { + + if (!rs.next()) { + return null; // no match found + } else { + return new OsAccount(rs.getLong("id"), rs.getLong("data_source_obj_id"), rs.getString("user_name"), rs.getString("realm"), rs.getString("unique_id"), rs.getString("signature"), rs.getLong("artifact_obj_id")); + } + } catch (SQLException ex) { + throw new TskCoreException(String.format("Error getting OS user account for unique id = %s, data source objId = %d ", uniqueId, dataSourceId), ex); + } + } + + /** + * Gets a user by the realm/userName. Returns null if no matching user is + * found. + * + * @param dataSourceId Data source object id. + * @param userName User name. + * @param realm Realm - domain or host name. + * @param connection Database connection to use. + * + * @return OsUser, null if no user with matching uniqueId is found. + * + * @throws TskCoreException + */ + private OsAccount getOsAccountByName(long dataSourceId, String userName, String realm, CaseDbConnection connection) throws TskCoreException { + + String queryString = "SELECT * FROM tsk_os_accounts" + + " WHERE data_source_obj_id = " + dataSourceId + + " AND LOWER(user_name) = LOWER('" + userName + "')" + + " AND LOWER(realm) = LOWER('" + realm + "')"; + + try (Statement s = connection.createStatement(); + ResultSet rs = connection.executeQuery(s, queryString)) { + + if (!rs.next()) { + return null; // no match found + } else { + return new OsAccount(rs.getLong("id"), rs.getLong("data_source_obj_id"), rs.getString("user_name"), rs.getString("realm"), rs.getString("unique_id"), rs.getString("signature"), rs.getLong("artifact_obj_id")); + } + } catch (SQLException ex) { + throw new TskCoreException(String.format("Error getting OS user account for realm = %s and userName = %s, data source objId = %d ", realm, userName, dataSourceId), ex); + } + } + + /** + * Get the OsUser with the given row id. + * + * @param userRowId Row id for the user account. + * + * @return OsUser. + * + * @throws TskCoreException If there is an error getting the user. + * @throws IllegalArgumentException If no matching user is found. + */ + public OsAccount getOsAccount(long userRowId) throws TskCoreException { + + String queryString = "SELECT * FROM tsk_os_accounts" + + " WHERE id = " + userRowId; + + try (CaseDbConnection connection = this.db.getConnection(); + Statement s = connection.createStatement(); + ResultSet rs = connection.executeQuery(s, queryString)) { + + if (!rs.next()) { + throw new IllegalArgumentException(String.format("No user found with row id = %d ", userRowId)); + } else { + Long artifactObjId = rs.getLong("artifact_obj_id"); + if (rs.wasNull()) { + throw new TskCoreException(String.format("No artifact created yet for user, row id = %d ", userRowId)); + } + + // BlackboardArtifact accountArtifact = db.getArtifactById(artifactObjId); + return new OsAccount(rs.getLong("id"), rs.getLong("data_source_obj_id"), rs.getString("user_name"), + rs.getString("realm"), rs.getString("unique_id"), rs.getString("signature"), artifactObjId); + } + } catch (SQLException ex) { + throw new TskCoreException("Error getting OS user account ", ex); + } + } + + /** + * Updates the artifact object id for the user with specified row id. + * + * @param userRowId Row id of the row to be updated + * @param artifactObjId Artifact object id to be updated with. + * @param transaction Transaction to use for database operation. + * + * @throws TskCoreException + */ + public void updateOsAccount(long userRowId, long artifactObjId, CaseDbTransaction transaction) throws TskCoreException { + + CaseDbConnection connection = transaction.getConnection(); + + db.acquireSingleUserCaseWriteLock(); + try (Statement updateStatement = connection.createStatement()) { + connection.executeUpdate(updateStatement, "UPDATE tsk_os_accounts SET artifact_obj_id = " + artifactObjId + " WHERE id = " + userRowId); + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, null, ex); + throw new TskCoreException(String.format("Error updating user row id %s", userRowId), ex); + } finally { + db.releaseSingleUserCaseWriteLock(); + } + } +} diff --git a/bindings/java/src/org/sleuthkit/datamodel/SlackFile.java b/bindings/java/src/org/sleuthkit/datamodel/SlackFile.java index df038e6021013a8f0a5b706e27721a721b2856d5..bebc1037d1aec437dcdc8038ca92fd02d64a67aa 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SlackFile.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SlackFile.java @@ -76,6 +76,11 @@ public class SlackFile extends FsContent { * yet been determined. * @param extension The extension part of the file name (not * including the '.'), can be null. + * @param uidStr String UID of the user as found in in the file + * system, can be null. + * @param osAccountRowId Row id of the user in the tsk_os_accounts + * table. + * */ SlackFile(SleuthkitCase db, long objId, @@ -90,8 +95,10 @@ public class SlackFile extends FsContent { long ctime, long crtime, long atime, long mtime, short modes, int uid, int gid, String md5Hash, String sha256Hash, FileKnown knownState, String parentPath, String mimeType, - String extension) { - super(db, objId, dataSourceObjectId, fsObjId, attrType, attrId, name, TskData.TSK_DB_FILES_TYPE_ENUM.SLACK, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, sha256Hash, knownState, parentPath, mimeType, extension); + String extension, + String uidStr, + long osAccountRowId) { + super(db, objId, dataSourceObjectId, fsObjId, attrType, attrId, name, TskData.TSK_DB_FILES_TYPE_ENUM.SLACK, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, sha256Hash, knownState, parentPath, mimeType, extension, uidStr, osAccountRowId); } /** diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java index 753a130bc961d67f5052dd937deeac496e74f47f..8458ab49727ca9aa21620a8ef86850318b6a84d3 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java @@ -212,6 +212,7 @@ public class SleuthkitCase { private CaseDbAccessManager dbAccessManager; private TaggingManager taggingMgr; private ScoringManager scoringManager; + private OsAccountManager osAccountManager; private final Map<String, Set<Long>> deviceIdToDatasourceObjIdMap = new HashMap<>(); @@ -391,6 +392,7 @@ private void init() throws Exception { dbAccessManager = new CaseDbAccessManager(this); taggingMgr = new TaggingManager(this); scoringManager = new ScoringManager(this); + osAccountManager = new OsAccountManager(this); } /** @@ -514,6 +516,17 @@ public ScoringManager getScoringManager() throws TskCoreException { return scoringManager; } + /** + * Gets the OS account manager for this case. + * + * @return The per case OsAccountManager object. + * + * @throws TskCoreException + */ + public OsAccountManager getOsAccountManager() throws TskCoreException { + return osAccountManager; + } + /** * Make sure the predefined artifact types are in the artifact types table. * @@ -5765,8 +5778,8 @@ public VirtualDirectory addVirtualDirectory(long parentId, String directoryName, // Insert a row for the virtual directory into the tsk_files table. // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type, - // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, known, mime_type, parent_path, data_source_obj_id,extension) - // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?) + // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, known, mime_type, parent_path, data_source_obj_id,extension,uid_str, os_account_row_id) + // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?,?) PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE); statement.clearParameters(); statement.setLong(1, newObjId); @@ -5831,8 +5844,13 @@ public VirtualDirectory addVirtualDirectory(long parentId, String directoryName, //extension, since this is not really file we just set it to null statement.setString(21, null); + + statement.setString(22, OsAccount.NULL_UID_STR); // uidStr + statement.setNull(23, java.sql.Types.BIGINT); // osAccountRowId + connection.executeUpdate(statement); + return new VirtualDirectory(this, newObjId, dataSourceObjectId, directoryName, dirType, metaType, dirFlag, metaFlags, null, null, FileKnown.UNKNOWN, parentPath); @@ -5910,8 +5928,8 @@ public LocalDirectory addLocalDirectory(long parentId, String directoryName, Cas // Insert a row for the local directory into the tsk_files table. // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type, - // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, sha256, known, mime_type, parent_path, data_source_obj_id) - // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, sha256, known, mime_type, parent_path, data_source_obj_id, extension, uid_str, os_account_row_id) + // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE); statement.clearParameters(); statement.setLong(1, newObjId); @@ -5963,6 +5981,9 @@ public LocalDirectory addLocalDirectory(long parentId, String directoryName, Cas //extension, since this is a directory we just set it to null statement.setString(21, null); + statement.setString(22, OsAccount.NULL_UID_STR); // uidStr + statement.setNull(23, java.sql.Types.BIGINT); // osAccountRowId + connection.executeUpdate(statement); return new LocalDirectory(this, newObjId, dataSourceObjectId, directoryName, dirType, @@ -6014,8 +6035,8 @@ public LocalFilesDataSource addLocalFilesDataSource(String deviceId, String root // its own object id. // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, // dir_type, meta_type, dir_flags, meta_flags, size, ctime, crtime, - // atime, mtime, md5, known, mime_type, parent_path, data_source_obj_id, extension) - // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?) + // atime, mtime, md5, known, mime_type, parent_path, data_source_obj_id, extension, uid_str, os_account_row_id) + // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?) PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE); preparedStatement.clearParameters(); preparedStatement.setLong(1, newObjId); @@ -6045,6 +6066,8 @@ public LocalFilesDataSource addLocalFilesDataSource(String deviceId, String root preparedStatement.setString(19, parentPath); preparedStatement.setLong(20, newObjId); preparedStatement.setString(21, null); //extension, just set it to null + preparedStatement.setString(22, OsAccount.NULL_UID_STR); // uidStr + preparedStatement.setNull(23, java.sql.Types.BIGINT); // osAccountRowId connection.executeUpdate(preparedStatement); return new LocalFilesDataSource(this, newObjId, newObjId, deviceId, rootDirectoryName, dirType, metaType, dirFlag, metaFlags, timeZone, null, null, FileKnown.UNKNOWN, parentPath); @@ -6391,7 +6414,7 @@ public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId, } else { parentPath = "/"; } - + PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE_SYSTEM_FILE); statement.clearParameters(); statement.setLong(1, objectId); // obj_is @@ -6422,7 +6445,7 @@ public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId, connection.executeUpdate(statement); DerivedFile derivedFile = new DerivedFile(this, objectId, dataSourceObjId, fileName, dirType, metaType, dirFlag, metaFlags, - size, ctime, crtime, atime, mtime, null, null, null, parentPath, null, parent.getId(), null, null, extension); + size, ctime, crtime, atime, mtime, null, null, null, parentPath, null, parent.getId(), null, null, extension, OsAccount.NULL_UID_STR, OsAccount.NO_USER); timelineManager.addEventsForNewFile(derivedFile, connection); @@ -6434,7 +6457,7 @@ public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, (short) 0, 0, 0, null, null, null, parentPath, null, - extension); + extension, OsAccount.NULL_UID_STR, OsAccount.NO_USER); } catch (SQLException ex) { logger.log(Level.WARNING, "Failed to add file system file", ex); @@ -6530,8 +6553,8 @@ public final List<LayoutFile> addLayoutFiles(Content parent, List<TskFileRange> * INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, * has_path, dir_type, meta_type, dir_flags, meta_flags, size, * ctime, crtime, atime, mtime, md5, known, mime_type, - * parent_path, data_source_obj_id,extension) VALUES (?, ?, ?, - * ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?) + * parent_path, data_source_obj_id,extension, uid_str, os_account_row_id) VALUES (?, ?, ?, + * ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?) */ PreparedStatement prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE); prepStmt.clearParameters(); @@ -6558,6 +6581,10 @@ public final List<LayoutFile> addLayoutFiles(Content parent, List<TskFileRange> //extension, since this is not a FS file we just set it to null prepStmt.setString(21, null); + + prepStmt.setString(22, OsAccount.NULL_UID_STR); // uidStr + prepStmt.setNull(23, java.sql.Types.BIGINT); // osAccountRowId + connection.executeUpdate(prepStmt); /* @@ -6590,7 +6617,9 @@ public final List<LayoutFile> addLayoutFiles(Content parent, List<TskFileRange> null, null, FileKnown.UNKNOWN, parent.getUniquePath(), - null)); + null, + OsAccount.NULL_UID_STR, + OsAccount.NO_USER)); } transaction.commit(); @@ -6711,8 +6740,8 @@ public final List<LayoutFile> addCarvedFiles(CarvingResult carvingResult) throws * INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, * has_path, dir_type, meta_type, dir_flags, meta_flags, size, * ctime, crtime, atime, mtime, md5, known, mime_type, - * parent_path, data_source_obj_id,extenion) VALUES (?, ?, ?, ?, - * ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?) + * parent_path, data_source_obj_id,extenion, uid_str, os_account_row_id) + * VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) */ PreparedStatement prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE); prepStmt.clearParameters(); @@ -6741,6 +6770,10 @@ public final List<LayoutFile> addCarvedFiles(CarvingResult carvingResult) throws prepStmt.setString(19, parentPath); // parent path prepStmt.setLong(20, carvedFilesDir.getDataSourceObjectId()); // data_source_obj_id prepStmt.setString(21, extractExtension(carvedFile.getName())); //extension + + prepStmt.setString(22, OsAccount.NULL_UID_STR); // uidStr + prepStmt.setNull(23, java.sql.Types.BIGINT); // osAccountRowId + connection.executeUpdate(prepStmt); /* @@ -6775,7 +6808,9 @@ public final List<LayoutFile> addCarvedFiles(CarvingResult carvingResult) throws null, null, FileKnown.UNKNOWN, parentPath, - null)); + null, + OsAccount.NULL_UID_STR, + OsAccount.NO_USER)); } transaction.commit(); @@ -6917,6 +6952,9 @@ public DerivedFile addDerivedFile(String fileName, String localPath, final String extension = extractExtension(fileName); //extension statement.setString(21, extension); + + statement.setString(22, OsAccount.NULL_UID_STR); // uidStr + statement.setNull(23, java.sql.Types.BIGINT); // osAccountRowId connection.executeUpdate(statement); @@ -6924,7 +6962,7 @@ public DerivedFile addDerivedFile(String fileName, String localPath, addFilePath(connection, newObjId, localPath, encodingType); DerivedFile derivedFile = new DerivedFile(this, newObjId, dataSourceObjId, fileName, dirType, metaType, dirFlag, metaFlags, - savedSize, ctime, crtime, atime, mtime, null, null, null, parentPath, localPath, parentId, null, encodingType, extension); + savedSize, ctime, crtime, atime, mtime, null, null, null, parentPath, localPath, parentId, null, encodingType, extension, OsAccount.NULL_UID_STR, OsAccount.NO_USER); timelineManager.addEventsForNewFile(derivedFile, connection); transaction.commit(); @@ -7034,7 +7072,7 @@ public DerivedFile updateDerivedFile(DerivedFile derivedFile, String localPath, long dataSourceObjId = getDataSourceObjectId(connection, parentId); final String extension = extractExtension(derivedFile.getName()); return new DerivedFile(this, derivedFile.getId(), dataSourceObjId, derivedFile.getName(), dirType, metaType, dirFlag, metaFlags, - savedSize, ctime, crtime, atime, mtime, null, null, null, parentPath, localPath, parentId, null, encodingType, extension); + savedSize, ctime, crtime, atime, mtime, null, null, null, parentPath, localPath, parentId, null, encodingType, extension, derivedFile.getUidStr(), derivedFile.getUserRowId()); } catch (SQLException ex) { connection.rollbackTransaction(); throw new TskCoreException("Failed to add derived file to case database", ex); @@ -7165,8 +7203,8 @@ public LocalFile addLocalFile(String fileName, String localPath, // Insert a row for the local/logical file into the tsk_files table. // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type, // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, known, mime_type, - // parent_path, data_source_obj_id,extension) - // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?) + // parent_path, data_source_obj_id,extension, uid_str, os_account_row_id) + // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?) PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE); statement.clearParameters(); statement.setLong(1, objectId); @@ -7217,6 +7255,9 @@ public LocalFile addLocalFile(String fileName, String localPath, final String extension = extractExtension(fileName); statement.setString(21, extension); + statement.setString(22, OsAccount.NULL_UID_STR); // uidStr + statement.setNull(23, java.sql.Types.BIGINT); // osAccountRowId + connection.executeUpdate(statement); addFilePath(connection, objectId, localPath, encodingType); LocalFile localFile = new LocalFile(this, @@ -7233,7 +7274,8 @@ public LocalFile addLocalFile(String fileName, String localPath, parent.getId(), parentPath, dataSourceObjId, localPath, - encodingType, extension); + encodingType, extension, + OsAccount.NULL_UID_STR, OsAccount.NO_USER); getTimelineManager().addEventsForNewFile(localFile, connection); return localFile; @@ -7345,8 +7387,8 @@ public LayoutFile addLayoutFile(String fileName, * tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, * meta_type, dir_flags, meta_flags, size, ctime, crtime, atime, * mtime, md5, known, mime_type, parent_path, - * data_source_obj_id,extenion) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, - * ?, ?, ?, ?, ?, ?, ?,?) + * data_source_obj_id,extenion, uid_str, os_account_row_id) + * VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) */ PreparedStatement prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE); prepStmt.clearParameters(); @@ -7385,6 +7427,10 @@ public LayoutFile addLayoutFile(String fileName, prepStmt.setLong(20, parent.getDataSource().getId()); // data_source_obj_id prepStmt.setString(21, extractExtension(fileName)); //extension + + prepStmt.setString(22, OsAccount.NULL_UID_STR); // uidStr + prepStmt.setNull(23, java.sql.Types.BIGINT); // osAccountRowId + connection.executeUpdate(prepStmt); /* @@ -7419,7 +7465,9 @@ public LayoutFile addLayoutFile(String fileName, null, null, FileKnown.UNKNOWN, parentPath, - null); + null, + OsAccount.NULL_UID_STR, + OsAccount.NO_USER); transaction.commit(); transaction = null; @@ -8709,6 +8757,12 @@ private List<AbstractFile> resultSetToAbstractFiles(ResultSet rs, CaseDbConnecti if (parentPath == null) { parentPath = "/"; //NON-NLS } + + long osAccountRowId = rs.getInt("os_account_row_id"); + if (rs.wasNull()) { + osAccountRowId = OsAccount.NO_USER; + } + LayoutFile lf = new LayoutFile(this, rs.getLong("obj_id"), //NON-NLS rs.getLong("data_source_obj_id"), @@ -8718,7 +8772,9 @@ private List<AbstractFile> resultSetToAbstractFiles(ResultSet rs, CaseDbConnecti TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), rs.getShort("meta_flags"), //NON-NLS rs.getLong("size"), //NON-NLS rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS - rs.getString("md5"), rs.getString("sha256"), FileKnown.valueOf(rs.getByte("known")), parentPath, rs.getString("mime_type")); //NON-NLS + rs.getString("md5"), rs.getString("sha256"), FileKnown.valueOf(rs.getByte("known")), parentPath, + rs.getString("mime_type"), + rs.getString("uid_str"), osAccountRowId ); //NON-NLS results.add(lf); } else if (type == TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType()) { final DerivedFile df; @@ -8753,6 +8809,11 @@ private List<AbstractFile> resultSetToAbstractFiles(ResultSet rs, CaseDbConnecti * @throws SQLException */ org.sleuthkit.datamodel.File file(ResultSet rs, FileSystem fs) throws SQLException { + long osAccountRowId = rs.getInt("os_account_row_id"); + if (rs.wasNull()) { + osAccountRowId = OsAccount.NO_USER; + } + org.sleuthkit.datamodel.File f = new org.sleuthkit.datamodel.File(this, rs.getLong("obj_id"), //NON-NLS rs.getLong("data_source_obj_id"), rs.getLong("fs_obj_id"), //NON-NLS TskData.TSK_FS_ATTR_TYPE_ENUM.valueOf(rs.getShort("attr_type")), //NON-NLS @@ -8764,7 +8825,7 @@ org.sleuthkit.datamodel.File file(ResultSet rs, FileSystem fs) throws SQLExcepti rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS (short) rs.getInt("mode"), rs.getInt("uid"), rs.getInt("gid"), //NON-NLS rs.getString("md5"), rs.getString("sha256"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS - rs.getString("parent_path"), rs.getString("mime_type"), rs.getString("extension")); //NON-NLS + rs.getString("parent_path"), rs.getString("mime_type"), rs.getString("extension"), rs.getString("uid_str"), osAccountRowId); //NON-NLS f.setFileSystem(fs); return f; } @@ -8781,6 +8842,11 @@ org.sleuthkit.datamodel.File file(ResultSet rs, FileSystem fs) throws SQLExcepti * @throws SQLException thrown if SQL error occurred */ Directory directory(ResultSet rs, FileSystem fs) throws SQLException { + long osAccountRowId = rs.getInt("os_account_row_id"); + if (rs.wasNull()) { + osAccountRowId = OsAccount.NO_USER; + } + Directory dir = new Directory(this, rs.getLong("obj_id"), rs.getLong("data_source_obj_id"), rs.getLong("fs_obj_id"), //NON-NLS TskData.TSK_FS_ATTR_TYPE_ENUM.valueOf(rs.getShort("attr_type")), //NON-NLS rs.getInt("attr_id"), rs.getString("name"), rs.getLong("meta_addr"), rs.getInt("meta_seq"), //NON-NLS @@ -8791,7 +8857,7 @@ Directory directory(ResultSet rs, FileSystem fs) throws SQLException { rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS rs.getShort("mode"), rs.getInt("uid"), rs.getInt("gid"), //NON-NLS rs.getString("md5"), rs.getString("sha256"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS - rs.getString("parent_path")); //NON-NLS + rs.getString("parent_path"), rs.getString("uid_str"), osAccountRowId); //NON-NLS dir.setFileSystem(fs); return dir; } @@ -8928,6 +8994,12 @@ private DerivedFile derivedFile(ResultSet rs, CaseDbConnection connection, long if (parentPath == null) { parentPath = ""; } + + long osAccountRowId = rs.getInt("os_account_row_id"); + if (rs.wasNull()) { + osAccountRowId = OsAccount.NO_USER; + } + final DerivedFile df = new DerivedFile(this, objId, rs.getLong("data_source_obj_id"), rs.getString("name"), //NON-NLS TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS @@ -8937,7 +9009,8 @@ private DerivedFile derivedFile(ResultSet rs, CaseDbConnection connection, long rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS rs.getString("md5"), rs.getString("sha256"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS parentPath, localPath, parentId, rs.getString("mime_type"), - encodingType, rs.getString("extension")); + encodingType, rs.getString("extension"), + rs.getString("uid_str"), osAccountRowId); return df; } @@ -8981,6 +9054,11 @@ private LocalFile localFile(ResultSet rs, CaseDbConnection connection, long pare if (null == parentPath) { parentPath = ""; } + long osAccountRowId = rs.getInt("os_account_row_id"); + if (rs.wasNull()) { + osAccountRowId = OsAccount.NO_USER; + } + LocalFile file = new LocalFile(this, objId, rs.getString("name"), //NON-NLS TSK_DB_FILES_TYPE_ENUM.valueOf(rs.getShort("type")), //NON-NLS TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS @@ -8990,7 +9068,8 @@ private LocalFile localFile(ResultSet rs, CaseDbConnection connection, long pare rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS rs.getString("mime_type"), rs.getString("md5"), rs.getString("sha256"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS parentId, parentPath, rs.getLong("data_source_obj_id"), - localPath, encodingType, rs.getString("extension")); + localPath, encodingType, rs.getString("extension"), + rs.getString("uid_str"), osAccountRowId); return file; } @@ -9006,6 +9085,10 @@ private LocalFile localFile(ResultSet rs, CaseDbConnection connection, long pare * @throws SQLException */ org.sleuthkit.datamodel.SlackFile slackFile(ResultSet rs, FileSystem fs) throws SQLException { + long osAccountRowId = rs.getInt("os_account_row_id"); + if (rs.wasNull()) { + osAccountRowId = OsAccount.NO_USER; + } org.sleuthkit.datamodel.SlackFile f = new org.sleuthkit.datamodel.SlackFile(this, rs.getLong("obj_id"), //NON-NLS rs.getLong("data_source_obj_id"), rs.getLong("fs_obj_id"), //NON-NLS TskData.TSK_FS_ATTR_TYPE_ENUM.valueOf(rs.getShort("attr_type")), //NON-NLS @@ -9017,7 +9100,8 @@ org.sleuthkit.datamodel.SlackFile slackFile(ResultSet rs, FileSystem fs) throws rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS (short) rs.getInt("mode"), rs.getInt("uid"), rs.getInt("gid"), //NON-NLS rs.getString("md5"), rs.getString("sha256"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS - rs.getString("parent_path"), rs.getString("mime_type"), rs.getString("extension")); //NON-NLS + rs.getString("parent_path"), rs.getString("mime_type"), rs.getString("extension"), + rs.getString("uid_str"), osAccountRowId); //NON-NLS f.setFileSystem(fs); return f; } @@ -9071,6 +9155,10 @@ List<Content> fileChildren(ResultSet rs, CaseDbConnection connection, long paren if (parentPath == null) { parentPath = ""; } + long osAccountRowId = rs.getInt("os_account_row_id"); + if (rs.wasNull()) { + osAccountRowId = OsAccount.NO_USER; + } final LayoutFile lf = new LayoutFile(this, rs.getLong("obj_id"), rs.getLong("data_source_obj_id"), rs.getString("name"), type, TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), @@ -9079,7 +9167,8 @@ List<Content> fileChildren(ResultSet rs, CaseDbConnection connection, long paren rs.getLong("size"), rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), rs.getString("md5"), rs.getString("sha256"), - FileKnown.valueOf(rs.getByte("known")), parentPath, rs.getString("mime_type")); + FileKnown.valueOf(rs.getByte("known")), parentPath, rs.getString("mime_type"), + rs.getString("uid_str"), osAccountRowId); children.add(lf); break; } @@ -11486,8 +11575,8 @@ private enum PREPARED_STATEMENT { SELECT_FILE_DERIVATION_METHOD("SELECT tool_name, tool_version, other FROM tsk_files_derived_method WHERE derived_id = ?"), //NON-NLS SELECT_MAX_OBJECT_ID("SELECT MAX(obj_id) AS max_obj_id FROM tsk_objects"), //NON-NLS INSERT_OBJECT("INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)"), //NON-NLS - INSERT_FILE("INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type, dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, sha256, known, mime_type, parent_path, data_source_obj_id,extension) " //NON-NLS - + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"), //NON-NLS + INSERT_FILE("INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type, dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, sha256, known, mime_type, parent_path, data_source_obj_id, extension, uid_str, os_account_row_id ) " //NON-NLS + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"), //NON-NLS INSERT_FILE_SYSTEM_FILE("INSERT INTO tsk_files(obj_id, fs_obj_id, data_source_obj_id, attr_type, attr_id, name, meta_addr, meta_seq, type, has_path, dir_type, meta_type, dir_flags, meta_flags, size, ctime, crtime, atime, mtime, parent_path, extension)" + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"), // NON-NLS UPDATE_DERIVED_FILE("UPDATE tsk_files SET type = ?, dir_type = ?, meta_type = ?, dir_flags = ?, meta_flags = ?, size= ?, ctime= ?, crtime= ?, atime= ?, mtime= ?, mime_type = ? " diff --git a/bindings/java/src/org/sleuthkit/datamodel/SpecialDirectory.java b/bindings/java/src/org/sleuthkit/datamodel/SpecialDirectory.java index 5db5888d5b34d8a0ebbd926d18b1fa52559c2512..fe00c3e42edcf38984ee1f46d722136ed8efc70a 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SpecialDirectory.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SpecialDirectory.java @@ -48,7 +48,7 @@ public abstract class SpecialDirectory extends AbstractFile { String mimeType) { super(db, objId, dataSourceObjectId, attrType, attrId, name, fileType, metaAddr, metaSeq, dirType, metaType, dirFlag, - metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, sha256Hash, knownState, parentPath, mimeType, null); + metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, sha256Hash, knownState, parentPath, mimeType, null, OsAccount.NULL_UID_STR, OsAccount.NO_USER); } /** diff --git a/bindings/java/src/org/sleuthkit/datamodel/TskCaseDbBridge.java b/bindings/java/src/org/sleuthkit/datamodel/TskCaseDbBridge.java index cee51945acc4b4f0b86cc06ab7dcab0e29548c2d..97fef20429d464f8d0d3cb48ffbc52b461d8f163 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/TskCaseDbBridge.java +++ b/bindings/java/src/org/sleuthkit/datamodel/TskCaseDbBridge.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.datamodel; +import com.google.common.base.Strings; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; @@ -306,6 +307,7 @@ long addFileSystem(long parentObjId, long imgOffset, int fsType, long blockSize, * @param seq The sequence number from fs_file->meta->seq. * @param parMetaAddr The metadata address of the parent * @param parSeq The parent sequence number if NTFS, -1 otherwise. + * @param ownerUid String uid of the file owner. May be an empty string. * * @return 0 if successful, -1 if not */ @@ -319,7 +321,7 @@ long addFile(long parentObjId, long crtime, long ctime, long atime, long mtime, int meta_mode, int gid, int uid, String escaped_path, String extension, - long seq, long parMetaAddr, long parSeq) { + long seq, long parMetaAddr, long parSeq, String ownerUid) { // Add the new file to the list batchedFiles.add(new FileInfo(parentObjId, @@ -332,7 +334,7 @@ long addFile(long parentObjId, crtime, ctime, atime, mtime, meta_mode, gid, uid, escaped_path, extension, - seq, parMetaAddr, parSeq)); + seq, parMetaAddr, parSeq, ownerUid)); // Add the current files to the database if we've exceeded the threshold or if we // have the root folder. @@ -371,7 +373,7 @@ private long addBatchedFilesToDb() { fileInfo.crtime, fileInfo.ctime, fileInfo.atime, fileInfo.mtime, fileInfo.meta_mode, fileInfo.gid, fileInfo.uid, null, TskData.FileKnown.UNKNOWN, - fileInfo.escaped_path, fileInfo.extension, + fileInfo.escaped_path, fileInfo.extension, fileInfo.ownerUid, false, trans); if (fileInfo.fsObjId != fileInfo.parentObjId) { // Add new file ID to the list to send to ingest unless it is the root folder @@ -486,7 +488,7 @@ long addLayoutFile(long parentObjId, null, null, null, null, null, null, null, null, TskData.FileKnown.UNKNOWN, - null, null, + null, null, null, true, trans); commitTransaction(); @@ -692,6 +694,7 @@ private class FileInfo { long seq; long parMetaAddr; long parSeq; + String ownerUid; FileInfo(long parentObjId, long fsObjId, long dataSourceObjId, @@ -703,7 +706,7 @@ private class FileInfo { long crtime, long ctime, long atime, long mtime, int meta_mode, int gid, int uid, String escaped_path, String extension, - long seq, long parMetaAddr, long parSeq) { + long seq, long parMetaAddr, long parSeq, String ownerUid) { this.parentObjId = parentObjId; this.fsObjId = fsObjId; @@ -731,6 +734,7 @@ private class FileInfo { this.seq = seq; this.parMetaAddr = parMetaAddr; this.parSeq = parSeq; + this.ownerUid = ownerUid; } } @@ -768,6 +772,7 @@ private class FileInfo { * @param known The file known status. * @param escaped_path The escaped path to the file. * @param extension The file extension. + * @param ownerUid The string user id of the file owner. * @param hasLayout True if this is a layout file, false otherwise. * @param transaction The open transaction. * @@ -785,8 +790,8 @@ private long addFileToDb(long parentObjId, Long crtime, Long ctime, Long atime, Long mtime, Integer meta_mode, Integer gid, Integer uid, String md5, TskData.FileKnown known, - String escaped_path, String extension, - boolean hasLayout, CaseDbTransaction transaction) throws TskCoreException { + String escaped_path, String extension, String ownerUid, + boolean hasLayout, CaseDbTransaction transaction) throws TskCoreException { try { SleuthkitCase.CaseDbConnection connection = transaction.getConnection(); @@ -795,8 +800,13 @@ private long addFileToDb(long parentObjId, // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?) long objectId = caseDb.addObject(parentObjId, TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection); - 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)" - + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; // NON-NLS + // add the ownerUid to the database. Use that rowId + long osAccountRowId = Strings.isNullOrEmpty(ownerUid) + ? OsAccount.NO_USER + : caseDb.getOsAccountManager().createOrGetOsAccount(dataSourceObjId, ownerUid, null, null, transaction); + + 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, uid_str, os_account_row_id)" + + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; // NON-NLS PreparedStatement preparedStatement = connection.getPreparedStatement(fileInsert, Statement.NO_GENERATED_KEYS); preparedStatement.clearParameters(); @@ -878,6 +888,14 @@ private long addFileToDb(long parentObjId, } else { preparedStatement.setNull(26, java.sql.Types.INTEGER); } + + preparedStatement.setString(27, ownerUid); // uidStr + + if (osAccountRowId != OsAccount.NO_USER) { + preparedStatement.setLong(28, osAccountRowId); + } else { + preparedStatement.setNull(28, java.sql.Types.BIGINT); + } connection.executeUpdate(preparedStatement); // If this is not a slack file create the timeline events @@ -890,7 +908,7 @@ private long addFileToDb(long parentObjId, TskData.TSK_FS_META_TYPE_ENUM.valueOf((short) metaType), TskData.TSK_FS_NAME_FLAG_ENUM.valueOf(dirFlags), (short) metaFlags, - size, ctime, crtime, atime, mtime, null, null, null, escaped_path, null, parentObjId, null, null, extension); + size, ctime, crtime, atime, mtime, null, null, null, escaped_path, null, parentObjId, null, null, extension, ownerUid, osAccountRowId); timelineManager.addEventsForNewFileQuiet(derivedFile, connection); }