Skip to content
Snippets Groups Projects
Unverified Commit 8d88cfff authored by Richard Cordovano's avatar Richard Cordovano Committed by GitHub
Browse files

Merge pull request #2476 from APriestman/7676_deleteHosts

7676 Delete hosts/realms/os accounts on data source deletion
parents a98139b2 4e8801b8
No related branches found
No related tags found
No related merge requests found
...@@ -223,7 +223,7 @@ private void createFileTables(Statement stmt) throws SQLException { ...@@ -223,7 +223,7 @@ private void createFileTables(Statement stmt) throws SQLException {
+ "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " + "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(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_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id)) " ); + "FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE SET NULL) " );
stmt.execute("CREATE TABLE file_encoding_types (encoding_type INTEGER PRIMARY KEY, name TEXT NOT NULL)"); stmt.execute("CREATE TABLE file_encoding_types (encoding_type INTEGER PRIMARY KEY, name TEXT NOT NULL)");
...@@ -418,7 +418,7 @@ private void createHostTables(Statement stmt) throws SQLException { ...@@ -418,7 +418,7 @@ private void createHostTables(Statement stmt) throws SQLException {
+ "person_id INTEGER, " + "person_id INTEGER, "
+ "merged_into " + dbQueryHelper.getBigIntType() + ", " + "merged_into " + dbQueryHelper.getBigIntType() + ", "
+ "FOREIGN KEY(person_id) REFERENCES tsk_persons(id) ON DELETE SET NULL, " + "FOREIGN KEY(person_id) REFERENCES tsk_persons(id) ON DELETE SET NULL, "
+ "FOREIGN KEY(merged_into) REFERENCES tsk_hosts(id), " + "FOREIGN KEY(merged_into) REFERENCES tsk_hosts(id) ON DELETE CASCADE, "
+ "UNIQUE(name)) "); + "UNIQUE(name)) ");
stmt.execute("CREATE TABLE tsk_host_addresses (id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, " stmt.execute("CREATE TABLE tsk_host_addresses (id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, "
...@@ -491,8 +491,8 @@ private void createAccountTables(Statement stmt) throws SQLException { ...@@ -491,8 +491,8 @@ private void createAccountTables(Statement stmt) throws SQLException {
+ "db_status INTEGER DEFAULT 0, " // active/merged/deleted + "db_status INTEGER DEFAULT 0, " // active/merged/deleted
+ "merged_into " + dbQueryHelper.getBigIntType() + " DEFAULT NULL, " + "merged_into " + dbQueryHelper.getBigIntType() + " DEFAULT NULL, "
+ "UNIQUE(realm_signature), " + "UNIQUE(realm_signature), "
+ "FOREIGN KEY(scope_host_id) REFERENCES tsk_hosts(id)," + "FOREIGN KEY(scope_host_id) REFERENCES tsk_hosts(id) ON DELETE CASCADE,"
+ "FOREIGN KEY(merged_into) REFERENCES tsk_os_account_realms(id) )"); + "FOREIGN KEY(merged_into) REFERENCES tsk_os_account_realms(id) ON DELETE CASCADE )");
// References tsk_objects, tsk_os_account_realms, tsk_persons // References tsk_objects, tsk_os_account_realms, tsk_persons
stmt.execute("CREATE TABLE tsk_os_accounts (os_account_obj_id " + dbQueryHelper.getBigIntType() + " PRIMARY KEY, " stmt.execute("CREATE TABLE tsk_os_accounts (os_account_obj_id " + dbQueryHelper.getBigIntType() + " PRIMARY KEY, "
...@@ -508,8 +508,8 @@ private void createAccountTables(Statement stmt) throws SQLException { ...@@ -508,8 +508,8 @@ private void createAccountTables(Statement stmt) throws SQLException {
+ "merged_into " + dbQueryHelper.getBigIntType() + " DEFAULT NULL, " + "merged_into " + dbQueryHelper.getBigIntType() + " DEFAULT NULL, "
+ "UNIQUE(signature, realm_id), " + "UNIQUE(signature, realm_id), "
+ "FOREIGN KEY(os_account_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " + "FOREIGN KEY(os_account_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
+ "FOREIGN KEY(realm_id) REFERENCES tsk_os_account_realms(id)," + "FOREIGN KEY(realm_id) REFERENCES tsk_os_account_realms(id) ON DELETE CASCADE,"
+ "FOREIGN KEY(merged_into) REFERENCES tsk_os_accounts(os_account_obj_id) )"); + "FOREIGN KEY(merged_into) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE CASCADE )");
} }
// Must be called after createAccountTables() and blackboard_attribute_types, blackboard_artifacts creation. // Must be called after createAccountTables() and blackboard_attribute_types, blackboard_artifacts creation.
...@@ -526,8 +526,8 @@ private void createAccountInstancesAndArtifacts(Statement stmt) throws SQLExcept ...@@ -526,8 +526,8 @@ private void createAccountInstancesAndArtifacts(Statement stmt) throws SQLExcept
+ "value_text TEXT, " + "value_text TEXT, "
+ "value_int32 INTEGER, value_int64 " + dbQueryHelper.getBigIntType() + ", " + "value_int32 INTEGER, value_int64 " + dbQueryHelper.getBigIntType() + ", "
+ "value_double NUMERIC(20, 10), " + "value_double NUMERIC(20, 10), "
+ "FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id), " + "FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE CASCADE, "
+ "FOREIGN KEY(host_id) REFERENCES tsk_hosts(id), " + "FOREIGN KEY(host_id) REFERENCES tsk_hosts(id) ON DELETE CASCADE, "
+ "FOREIGN KEY(source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE SET NULL, " + "FOREIGN KEY(source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE SET NULL, "
+ "FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))"); + "FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))");
...@@ -537,7 +537,7 @@ private void createAccountInstancesAndArtifacts(Statement stmt) throws SQLExcept ...@@ -537,7 +537,7 @@ private void createAccountInstancesAndArtifacts(Statement stmt) throws SQLExcept
+ "data_source_obj_id " + dbQueryHelper.getBigIntType() + " NOT NULL, " + "data_source_obj_id " + dbQueryHelper.getBigIntType() + " NOT NULL, "
+ "instance_type INTEGER NOT NULL, " // PerformedActionOn/ReferencedOn + "instance_type INTEGER NOT NULL, " // PerformedActionOn/ReferencedOn
+ "UNIQUE(os_account_obj_id, data_source_obj_id), " + "UNIQUE(os_account_obj_id, data_source_obj_id), "
+ "FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id), " + "FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE CASCADE, "
+ "FOREIGN KEY(data_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 ) ");
// References blackboard_artifacts, tsk_os_accounts // References blackboard_artifacts, tsk_os_accounts
...@@ -545,7 +545,7 @@ private void createAccountInstancesAndArtifacts(Statement stmt) throws SQLExcept ...@@ -545,7 +545,7 @@ private void createAccountInstancesAndArtifacts(Statement stmt) throws SQLExcept
+ "artifact_obj_id " + dbQueryHelper.getBigIntType() + " PRIMARY KEY, " + "artifact_obj_id " + dbQueryHelper.getBigIntType() + " PRIMARY KEY, "
+ "os_account_obj_id " + dbQueryHelper.getBigIntType() + ", " + "os_account_obj_id " + dbQueryHelper.getBigIntType() + ", "
+ "FOREIGN KEY(artifact_obj_id) REFERENCES blackboard_artifacts(artifact_obj_id) ON DELETE CASCADE, " + "FOREIGN KEY(artifact_obj_id) REFERENCES blackboard_artifacts(artifact_obj_id) ON DELETE CASCADE, "
+ "FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id)) "); + "FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE SET NULL) ");
} }
private void createEventTables(Statement stmt) throws SQLException { private void createEventTables(Statement stmt) throws SQLException {
......
...@@ -435,11 +435,23 @@ public List<Host> getAllHosts() throws TskCoreException { ...@@ -435,11 +435,23 @@ public List<Host> getAllHosts() throws TskCoreException {
* @throws TskCoreException if no host is found or an error occurs. * @throws TskCoreException if no host is found or an error occurs.
*/ */
public Host getHostByDataSource(DataSource dataSource) throws TskCoreException { public Host getHostByDataSource(DataSource dataSource) throws TskCoreException {
return getHostByDataSource(dataSource.getId());
}
/**
* Get host for the given data source ID.
*
* @param dataSourceId The data source ID to look up the host for.
*
* @return The host for this data source (will not be null).
*
* @throws TskCoreException if no host is found or an error occurs.
*/
Host getHostByDataSource(long dataSourceId) throws TskCoreException {
String queryString = "SELECT tsk_hosts.id AS hostId, tsk_hosts.name AS name, tsk_hosts.db_status AS db_status FROM \n" String queryString = "SELECT tsk_hosts.id AS hostId, tsk_hosts.name AS name, tsk_hosts.db_status AS db_status FROM \n"
+ "tsk_hosts INNER JOIN data_source_info \n" + "tsk_hosts INNER JOIN data_source_info \n"
+ "ON tsk_hosts.id = data_source_info.host_id \n" + "ON tsk_hosts.id = data_source_info.host_id \n"
+ "WHERE data_source_info.obj_id = " + dataSource.getId(); + "WHERE data_source_info.obj_id = " + dataSourceId;
db.acquireSingleUserCaseReadLock(); db.acquireSingleUserCaseReadLock();
try (CaseDbConnection connection = this.db.getConnection(); try (CaseDbConnection connection = this.db.getConnection();
...@@ -447,12 +459,12 @@ public Host getHostByDataSource(DataSource dataSource) throws TskCoreException { ...@@ -447,12 +459,12 @@ public Host getHostByDataSource(DataSource dataSource) throws TskCoreException {
ResultSet rs = connection.executeQuery(s, queryString)) { ResultSet rs = connection.executeQuery(s, queryString)) {
if (!rs.next()) { if (!rs.next()) {
throw new TskCoreException(String.format("Host not found for data source with ID = %d", dataSource.getId())); throw new TskCoreException(String.format("Host not found for data source with ID = %d", dataSourceId));
} else { } else {
return new Host(rs.getLong("hostId"), rs.getString("name"), Host.HostDbStatus.fromID(rs.getInt("db_status"))); return new Host(rs.getLong("hostId"), rs.getString("name"), Host.HostDbStatus.fromID(rs.getInt("db_status")));
} }
} catch (SQLException ex) { } catch (SQLException ex) {
throw new TskCoreException(String.format("Error getting host for data source with ID = %d", dataSource.getId()), ex); throw new TskCoreException(String.format("Error getting host for data source with ID = %d", dataSourceId), ex);
} finally { } finally {
db.releaseSingleUserCaseReadLock(); db.releaseSingleUserCaseReadLock();
} }
......
...@@ -9782,6 +9782,22 @@ public void setImagePaths(long obj_id, List<String> paths) throws TskCoreExcepti ...@@ -9782,6 +9782,22 @@ public void setImagePaths(long obj_id, List<String> paths) throws TskCoreExcepti
* within tsk core and the update fails * within tsk core and the update fails
*/ */
void deleteDataSource(long dataSourceObjectId) throws TskCoreException { void deleteDataSource(long dataSourceObjectId) throws TskCoreException {
// Check if this data source is the only one associated with its host. If so,
// we will delete the host and other associated data.
// Note that the cascading deletes were only added in schema 9.1, so we
// would get an error trying to delete a host from older cases.
Host hostToDelete = null;
VersionNumber version = getDBSchemaCreationVersion();
int major = version.getMajor();
int minor = version.getMinor();
if(major > 9 || (major == 9 && minor >= 1)) {
hostToDelete = getHostManager().getHostByDataSource(dataSourceObjectId);
if (getHostManager().getDataSourcesForHost(hostToDelete).size() != 1) {
hostToDelete = null;
}
}
CaseDbConnection connection = null; CaseDbConnection connection = null;
Statement statement; Statement statement;
acquireSingleUserCaseWriteLock(); acquireSingleUserCaseWriteLock();
...@@ -9798,6 +9814,19 @@ void deleteDataSource(long dataSourceObjectId) throws TskCoreException { ...@@ -9798,6 +9814,19 @@ void deleteDataSource(long dataSourceObjectId) throws TskCoreException {
+ "WHERE account_id NOT IN (SELECT account1_id FROM account_relationships) " + "WHERE account_id NOT IN (SELECT account1_id FROM account_relationships) "
+ "AND account_id NOT IN (SELECT account2_id FROM account_relationships))"; + "AND account_id NOT IN (SELECT account2_id FROM account_relationships))";
statement.execute(accountSql); statement.execute(accountSql);
// Now delete any host that was only associated with this data source. This will cascade to delete
// realms, os accounts, and os account attributes that were associated with the host.
if (hostToDelete != null) {
statement.execute("DELETE FROM tsk_hosts WHERE id = " + hostToDelete.getHostId());
// Clean up any stray OS Account objects
String deleteOsAcctObjectsQuery = "DELETE FROM tsk_objects " +
"WHERE type=" + TskData.ObjectType.OS_ACCOUNT.getObjectType() + " " +
"AND obj_id NOT IN (SELECT os_account_obj_id FROM tsk_os_accounts WHERE os_account_obj_id IS NOT NULL)";
statement.execute(deleteOsAcctObjectsQuery);
}
connection.commitTransaction(); connection.commitTransaction();
} catch (SQLException ex) { } catch (SQLException ex) {
rollbackTransaction(connection); rollbackTransaction(connection);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment