19 package org.sleuthkit.datamodel;
21 import com.google.common.base.Strings;
22 import org.apache.commons.lang3.StringUtils;
23 import java.sql.PreparedStatement;
24 import java.sql.ResultSet;
25 import java.sql.SQLException;
26 import java.sql.Statement;
27 import java.sql.Types;
28 import java.util.Collections;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.NavigableSet;
32 import java.util.Objects;
33 import java.util.Optional;
34 import java.util.UUID;
35 import java.util.concurrent.ConcurrentSkipListSet;
36 import java.util.stream.Collectors;
52 private final Object osAcctInstancesCacheLock;
53 private final NavigableSet<OsAccountInstance> osAccountInstanceCache;
63 osAcctInstancesCacheLock =
new Object();
64 osAccountInstanceCache =
new ConcurrentSkipListSet<>();
83 if (Strings.isNullOrEmpty(uniqueAccountId)) {
100 }
catch (SQLException ex) {
106 Optional<OsAccount> osAccount = this.getOsAccountByAddr(uniqueAccountId, realm);
107 if (osAccount.isPresent()) {
108 return osAccount.get();
112 throw new TskCoreException(String.format(
"Error creating OsAccount with uniqueAccountId = %s in realm id = %d", uniqueAccountId, realm.getRealmId()), ex);
147 if (realmScope == null) {
148 throw new TskCoreException(
"RealmScope cannot be null. Use UNKNOWN if scope is not known.");
150 if (referringHost == null) {
151 throw new TskCoreException(
"A referring host is required to create an account.");
155 if (StringUtils.isBlank(sid) && StringUtils.isBlank(loginName)) {
156 throw new TskCoreException(
"Cannot create OS account with both uniqueId and loginName as null.");
159 if (StringUtils.isBlank(sid) && StringUtils.isBlank(realmName)) {
160 throw new TskCoreException(
"Realm name or SID is required to create a Windows account.");
163 if (!StringUtils.isBlank(sid) && !WindowsAccountUtils.isWindowsUserSid(sid)) {
168 Optional<OsAccountRealm> realmOptional;
169 try (CaseDbConnection connection = db.getConnection()) {
173 if (realmOptional.isPresent()) {
174 realm = realmOptional.get();
203 if (StringUtils.isBlank(sid) && StringUtils.isBlank(loginName)) {
204 throw new TskCoreException(
"Cannot create OS account with both uniqueId and loginName as null.");
207 if (!StringUtils.isBlank(sid) && !WindowsAccountUtils.isWindowsUserSid(sid)) {
219 }
catch (SQLException ex) {
225 Optional<OsAccount> osAccount;
228 if (!Strings.isNullOrEmpty(sid)) {
229 osAccount = getOsAccountByAddr(sid, realm);
230 if (osAccount.isPresent()) {
231 return osAccount.get();
236 if (!Strings.isNullOrEmpty(loginName)) {
237 osAccount = getOsAccountByLoginName(loginName, realm);
238 if (osAccount.isPresent()) {
239 return osAccount.get();
244 throw new TskCoreException(String.format(
"Error creating OsAccount with sid = %s, loginName = %s, realm = %s, referring host = %s",
245 (sid != null) ? sid :
"Null",
246 (loginName != null) ? loginName :
"Null",
273 if (Objects.isNull(realm)) {
274 throw new TskCoreException(
"Cannot create an OS Account, realm is NULL.");
277 String signature = getOsAccountSignature(uniqueId, loginName);
280 CaseDbConnection connection = trans.getConnection();
285 long parentObjId = 0;
287 int objTypeId = TskData.ObjectType.OS_ACCOUNT.getObjectType();
288 long osAccountObjId = db.addObject(parentObjId, objTypeId, connection);
290 String accountInsertSQL =
"INSERT INTO tsk_os_accounts(os_account_obj_id, login_name, realm_id, addr, signature, status)"
291 +
" VALUES (?, ?, ?, ?, ?, ?)";
293 PreparedStatement preparedStatement = connection.getPreparedStatement(accountInsertSQL, Statement.NO_GENERATED_KEYS);
294 preparedStatement.clearParameters();
296 preparedStatement.setLong(1, osAccountObjId);
298 preparedStatement.setString(2, loginName);
299 preparedStatement.setLong(3, realm.getRealmId());
301 preparedStatement.setString(4, uniqueId);
302 preparedStatement.setString(5, signature);
303 preparedStatement.setInt(6, accountStatus.getId());
305 connection.executeUpdate(preparedStatement);
307 account =
new OsAccount(db, osAccountObjId, realm.getRealmId(), loginName, uniqueId, signature,
308 null, null, null, accountStatus, OsAccount.OsAccountDbStatus.ACTIVE);
310 trans.registerAddedOsAccount(account);
325 private Optional<OsAccount> getOsAccountByAddr(String addr, Host host)
throws TskCoreException {
327 try (CaseDbConnection connection = db.getConnection()) {
328 return getOsAccountByAddr(addr, host, connection);
344 private Optional<OsAccount> getOsAccountByAddr(String uniqueId, Host host, CaseDbConnection connection)
throws TskCoreException {
346 String whereHostClause = (host == null)
348 :
" ( realms.scope_host_id = " + host.getHostId() +
" OR realms.scope_host_id IS NULL) ";
350 String queryString =
"SELECT accounts.os_account_obj_id as os_account_obj_id, accounts.login_name, accounts.full_name, "
351 +
" accounts.realm_id, accounts.addr, accounts.signature, "
352 +
" accounts.type, accounts.status, accounts.admin, accounts.created_date, accounts.db_status, "
353 +
" realms.realm_name as realm_name, realms.realm_addr as realm_addr, realms.realm_signature, realms.scope_host_id, realms.scope_confidence, realms.db_status as realm_db_status "
354 +
" FROM tsk_os_accounts as accounts"
355 +
" LEFT JOIN tsk_os_account_realms as realms"
356 +
" ON accounts.realm_id = realms.id"
357 +
" WHERE " + whereHostClause
359 +
" AND LOWER(accounts.addr) = LOWER('" + uniqueId +
"')";
362 try (Statement s = connection.createStatement();
363 ResultSet rs = connection.executeQuery(s, queryString)) {
366 return Optional.empty();
368 return Optional.of(osAccountFromResultSet(rs));
370 }
catch (SQLException ex) {
371 throw new TskCoreException(String.format(
"Error getting OS account for unique id = %s and host = %s", uniqueId, (host != null ? host.getName() :
"null")), ex);
388 Optional<OsAccount> getOsAccountByAddr(String uniqueId, OsAccountRealm realm)
throws TskCoreException {
390 String queryString =
"SELECT * FROM tsk_os_accounts"
391 +
" WHERE LOWER(addr) = LOWER('" + uniqueId +
"')"
393 +
" AND realm_id = " + realm.getRealmId();
396 try (CaseDbConnection connection = this.db.getConnection();
397 Statement s = connection.createStatement();
398 ResultSet rs = connection.executeQuery(s, queryString)) {
401 return Optional.empty();
403 return Optional.of(osAccountFromResultSet(rs));
405 }
catch (SQLException ex) {
406 throw new TskCoreException(String.format(
"Error getting OS account for realm = %s and uniqueId = %s.", (realm != null) ? realm.getSignature() :
"NULL", uniqueId), ex);
423 Optional<OsAccount> getOsAccountByLoginName(String loginName, OsAccountRealm realm)
throws TskCoreException {
425 String queryString =
"SELECT * FROM tsk_os_accounts"
426 +
" WHERE LOWER(login_name) = LOWER('" + loginName +
"')"
428 +
" AND realm_id = " + realm.getRealmId();
431 try (CaseDbConnection connection = this.db.getConnection();
432 Statement s = connection.createStatement();
433 ResultSet rs = connection.executeQuery(s, queryString)) {
436 return Optional.empty();
438 return Optional.of(osAccountFromResultSet(rs));
440 }
catch (SQLException ex) {
441 throw new TskCoreException(String.format(
"Error getting OS account for realm = %s and loginName = %s.", (realm != null) ? realm.getSignature() :
"NULL", loginName), ex);
458 try (CaseDbConnection connection = this.db.getConnection()) {
475 String queryString =
"SELECT * FROM tsk_os_accounts"
476 +
" WHERE os_account_obj_id = " + osAccountObjId;
479 try (Statement s = connection.createStatement();
480 ResultSet rs = connection.executeQuery(s, queryString)) {
483 throw new TskCoreException(String.format(
"No account found with obj id = %d ", osAccountObjId));
485 return osAccountFromResultSet(rs);
487 }
catch (SQLException ex) {
488 throw new TskCoreException(String.format(
"Error getting account with obj id = %d ", osAccountObjId), ex);
517 if (osAccount == null) {
518 throw new TskCoreException(
"Cannot create account instance with null account.");
520 if (dataSource == null) {
521 throw new TskCoreException(
"Cannot create account instance with null data source.");
531 synchronized (osAcctInstancesCacheLock) {
537 try (CaseDbConnection connection = this.db.getConnection()) {
563 synchronized (osAcctInstancesCacheLock) {
564 if (osAccountInstanceCache.contains(
new OsAccountInstance(db, 0, osAccountId, dataSourceObjId, instanceType))) {
574 String accountInsertSQL = db.getInsertOrIgnoreSQL(
"INTO tsk_os_account_instances(os_account_obj_id, data_source_obj_id, instance_type)"
575 +
" VALUES (?, ?, ?)");
576 PreparedStatement preparedStatement = connection.getPreparedStatement(accountInsertSQL, Statement.RETURN_GENERATED_KEYS);
577 preparedStatement.clearParameters();
578 preparedStatement.setLong(1, osAccountId);
579 preparedStatement.setLong(2, dataSourceObjId);
580 preparedStatement.setInt(3, instanceType.getId());
581 connection.executeUpdate(preparedStatement);
582 try (ResultSet resultSet = preparedStatement.getGeneratedKeys();) {
583 if (resultSet.next()) {
584 OsAccountInstance accountInstance =
new OsAccountInstance(db, resultSet.getLong(1), osAccountId, dataSourceObjId, instanceType);
585 synchronized (osAcctInstancesCacheLock) {
586 osAccountInstanceCache.add(accountInstance);
603 db.fireTSKEvent(
new TskEvent.OsAcctInstancesAddedTskEvent(Collections.singletonList(accountInstance)));
606 }
catch (SQLException ex) {
607 throw new TskCoreException(String.format(
"Error adding OS account instance for OS account object id = %d, data source object id = %d", osAccountId, dataSourceObjId), ex);
624 String queryString =
"SELECT * FROM tsk_os_accounts as accounts "
625 +
" JOIN tsk_os_account_instances as instances "
626 +
" ON instances.os_account_obj_id = accounts.os_account_obj_id "
627 +
" JOIN data_source_info as datasources "
628 +
" ON datasources.obj_id = instances.data_source_obj_id "
629 +
" WHERE datasources.host_id = " + host.getHostId()
633 try (CaseDbConnection connection = this.db.getConnection();
634 Statement s = connection.createStatement();
635 ResultSet rs = connection.executeQuery(s, queryString)) {
637 List<OsAccount> accounts =
new ArrayList<>();
639 accounts.add(osAccountFromResultSet(rs));
642 }
catch (SQLException ex) {
643 throw new TskCoreException(String.format(
"Error getting OS accounts for host id = %d", host.getHostId()), ex);
662 List<OsAccount> destinationAccounts =
getOsAccounts(destRealm, trans.getConnection());
663 List<OsAccount> sourceAccounts =
getOsAccounts(sourceRealm, trans.getConnection());
665 for (
OsAccount sourceAccount : sourceAccounts) {
672 if (sourceAccount.getAddr().isPresent() && sourceAccount.getLoginName().isPresent()) {
673 List<OsAccount> duplicateDestAccounts = destinationAccounts.stream()
674 .filter(p -> p.getAddr().equals(sourceAccount.getAddr())
675 || (p.getLoginName().equals(sourceAccount.getLoginName()) && (!p.getAddr().isPresent())))
676 .collect(Collectors.toList());
677 if (duplicateDestAccounts.size() > 1) {
678 OsAccount combinedDestAccount = duplicateDestAccounts.get(0);
679 duplicateDestAccounts.remove(combinedDestAccount);
680 for (
OsAccount dupeDestAccount : duplicateDestAccounts) {
681 mergeOsAccounts(dupeDestAccount, combinedDestAccount, trans);
687 OsAccount matchingDestAccount = null;
690 if (sourceAccount.getAddr().isPresent()) {
691 List<OsAccount> matchingDestAccounts = destinationAccounts.stream()
692 .filter(p -> p.getAddr().equals(sourceAccount.getAddr()))
693 .collect(Collectors.toList());
694 if (!matchingDestAccounts.isEmpty()) {
695 matchingDestAccount = matchingDestAccounts.get(0);
703 if (matchingDestAccount == null && sourceAccount.getLoginName().isPresent()) {
704 List<OsAccount> matchingDestAccounts = destinationAccounts.stream()
705 .filter(p -> (p.getLoginName().equals(sourceAccount.getLoginName())
706 && ((!sourceAccount.getAddr().isPresent()) || (!p.getAddr().isPresent()))))
707 .collect(Collectors.toList());
708 if (!matchingDestAccounts.isEmpty()) {
709 matchingDestAccount = matchingDestAccounts.get(0);
714 if (matchingDestAccount != null) {
715 mergeOsAccounts(sourceAccount, matchingDestAccount, trans);
717 String query =
"UPDATE tsk_os_accounts SET realm_id = " + destRealm.getRealmId() +
" WHERE os_account_obj_id = " + sourceAccount.getId();
718 try (Statement s = trans.getConnection().createStatement()) {
719 s.executeUpdate(query);
720 }
catch (SQLException ex) {
721 throw new TskCoreException(
"Error executing SQL update: " + query, ex);
723 trans.registerChangedOsAccount(sourceAccount);
742 private void mergeOsAccounts(OsAccount sourceAccount, OsAccount destAccount, CaseDbTransaction trans)
throws TskCoreException {
745 try (Statement s = trans.getConnection().createStatement()) {
748 query = makeOsAccountUpdateQuery(
"tsk_os_account_attributes", sourceAccount, destAccount);
749 s.executeUpdate(query);
753 query =
"DELETE FROM tsk_os_account_instances "
756 +
" sourceAccountInstance.id "
758 +
" tsk_os_account_instances destAccountInstance "
759 +
"INNER JOIN tsk_os_account_instances sourceAccountInstance ON destAccountInstance.data_source_obj_id = sourceAccountInstance.data_source_obj_id "
760 +
"WHERE destAccountInstance.os_account_obj_id = " + destAccount.getId()
761 +
" AND sourceAccountInstance.os_account_obj_id = " + sourceAccount.getId() +
" )";
762 s.executeUpdate(query);
764 query = makeOsAccountUpdateQuery(
"tsk_os_account_instances", sourceAccount, destAccount);
765 s.executeUpdate(query);
766 synchronized (osAcctInstancesCacheLock) {
767 osAccountInstanceCache.clear();
770 query = makeOsAccountUpdateQuery(
"tsk_files", sourceAccount, destAccount);
771 s.executeUpdate(query);
773 query = makeOsAccountUpdateQuery(
"tsk_data_artifacts", sourceAccount, destAccount);
774 s.executeUpdate(query);
777 String mergedSignature = makeMergedOsAccountSignature();
778 query =
"UPDATE tsk_os_accounts SET merged_into = " + destAccount.getId()
779 +
", db_status = " + OsAccount.OsAccountDbStatus.MERGED.getId()
780 +
", signature = '" + mergedSignature +
"' "
781 +
" WHERE os_account_obj_id = " + sourceAccount.getId();
783 s.executeUpdate(query);
784 trans.registerDeletedOsAccount(sourceAccount.getId());
789 mergeOsAccountObjectsAndUpdateDestAccount(sourceAccount, destAccount, trans);
790 }
catch (SQLException ex) {
791 throw new TskCoreException(
"Error executing SQL update: " + query, ex);
800 private String makeMergedOsAccountSignature() {
801 return "MERGED " + UUID.randomUUID().toString();
813 private String makeOsAccountUpdateQuery(String tableName, OsAccount sourceAccount, OsAccount destAccount) {
814 return "UPDATE " + tableName +
" SET os_account_obj_id = " + destAccount.getId() +
" WHERE os_account_obj_id = " + sourceAccount.getId();
828 private OsAccount mergeOsAccountObjectsAndUpdateDestAccount(OsAccount sourceAccount, OsAccount destAccount, CaseDbTransaction trans)
throws TskCoreException {
830 OsAccount mergedDestAccount = destAccount;
832 String destLoginName = null;
833 String destAddr = null;
836 if (!destAccount.getLoginName().isPresent() && sourceAccount.getLoginName().isPresent()) {
840 if (!destAccount.getAddr().isPresent() && sourceAccount.getAddr().isPresent()) {
841 destAddr = sourceAccount.getAddr().get();
845 OsAccountUpdateResult updateStatus = this.updateOsAccountCore(destAccount, destAddr, destLoginName, trans);
847 if (updateStatus.getUpdateStatusCode() == OsAccountUpdateStatus.UPDATED && updateStatus.getUpdatedAccount().isPresent()) {
848 mergedDestAccount = updateStatus.getUpdatedAccount().get();
851 String destFullName = null;
852 Long destCreationTime = null;
853 if (!destAccount.getFullName().isPresent() && sourceAccount.getFullName().isPresent()) {
854 destFullName = sourceAccount.getFullName().get();
857 if (!destAccount.getCreationTime().isPresent() && sourceAccount.getCreationTime().isPresent()) {
858 destCreationTime = sourceAccount.getCreationTime().get();
864 if (updateStatus.getUpdateStatusCode() == OsAccountUpdateStatus.UPDATED && updateStatus.getUpdatedAccount().isPresent()) {
865 mergedDestAccount = updateStatus.getUpdatedAccount().get();
868 return mergedDestAccount;
881 private List<OsAccount>
getOsAccounts(OsAccountRealm realm, CaseDbConnection connection)
throws TskCoreException {
882 String queryString =
"SELECT * FROM tsk_os_accounts"
883 +
" WHERE realm_id = " + realm.getRealmId()
884 +
" AND db_status = " + OsAccount.OsAccountDbStatus.ACTIVE.getId()
885 +
" ORDER BY os_account_obj_id";
887 try (Statement s = connection.createStatement();
888 ResultSet rs = connection.executeQuery(s, queryString)) {
890 List<OsAccount> accounts =
new ArrayList<>();
892 accounts.add(osAccountFromResultSet(rs));
895 }
catch (SQLException ex) {
896 throw new TskCoreException(String.format(
"Error getting OS accounts for realm id = %d", realm.getRealmId()), ex);
908 String queryString =
"SELECT * FROM tsk_os_accounts"
912 try (CaseDbConnection connection = this.db.getConnection();
913 Statement s = connection.createStatement();
914 ResultSet rs = connection.executeQuery(s, queryString)) {
916 List<OsAccount> accounts =
new ArrayList<>();
918 accounts.add(osAccountFromResultSet(rs));
921 }
catch (SQLException ex) {
922 throw new TskCoreException(String.format(
"Error getting OS accounts"), ex);
945 if (referringHost == null) {
946 throw new TskCoreException(
"A referring host is required to get an account.");
950 if (StringUtils.isBlank(sid) && StringUtils.isBlank(loginName)) {
951 throw new TskCoreException(
"Cannot get an OS account with both SID and loginName as null.");
956 if (!realm.isPresent()) {
957 return Optional.empty();
961 if (!Strings.isNullOrEmpty(sid)) {
962 if (!WindowsAccountUtils.isWindowsUserSid(sid)) {
966 return this.getOsAccountByAddr(sid, realm.get());
970 return this.getOsAccountByLoginName(loginName, realm.get());
984 synchronized (account) {
987 try (CaseDbConnection connection = db.getConnection()) {
990 String attributeInsertSQL =
"INSERT INTO tsk_os_account_attributes(os_account_obj_id, host_id, source_obj_id, attribute_type_id, value_type, value_byte, value_text, value_int32, value_int64, value_double)"
991 +
" VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
993 PreparedStatement preparedStatement = connection.getPreparedStatement(attributeInsertSQL, Statement.RETURN_GENERATED_KEYS);
994 preparedStatement.clearParameters();
996 preparedStatement.setLong(1, account.getId());
997 if (accountAttribute.getHostId().isPresent()) {
998 preparedStatement.setLong(2, accountAttribute.getHostId().get());
1000 preparedStatement.setNull(2, java.sql.Types.NULL);
1002 if (accountAttribute.getSourceObjectId().isPresent()) {
1003 preparedStatement.setLong(3, accountAttribute.getSourceObjectId().get());
1005 preparedStatement.setNull(3, java.sql.Types.NULL);
1008 preparedStatement.setLong(4, accountAttribute.getAttributeType().getTypeID());
1009 preparedStatement.setLong(5, accountAttribute.getAttributeType().getValueType().getType());
1012 preparedStatement.setBytes(6, accountAttribute.getValueBytes());
1014 preparedStatement.setBytes(6, null);
1019 preparedStatement.setString(7, accountAttribute.getValueString());
1021 preparedStatement.setString(7, null);
1024 preparedStatement.setInt(8, accountAttribute.getValueInt());
1026 preparedStatement.setNull(8, java.sql.Types.NULL);
1031 preparedStatement.setLong(9, accountAttribute.getValueLong());
1033 preparedStatement.setNull(9, java.sql.Types.NULL);
1037 preparedStatement.setDouble(10, accountAttribute.getValueDouble());
1039 preparedStatement.setNull(10, java.sql.Types.NULL);
1042 connection.executeUpdate(preparedStatement);
1044 }
catch (SQLException ex) {
1045 throw new TskCoreException(String.format(
"Error adding OS Account attribute for account id = %d", account.getId()), ex);
1050 List<OsAccountAttribute> currentAttribsList = getOsAccountAttributes(account);
1051 account.setAttributesInternal(currentAttribsList);
1053 fireChangeEvent(account);
1065 List<OsAccountAttribute> getOsAccountAttributes(
OsAccount account)
throws TskCoreException {
1067 String queryString =
"SELECT attributes.os_account_obj_id as os_account_obj_id, attributes.host_id as host_id, attributes.source_obj_id as source_obj_id, "
1068 +
" attributes.attribute_type_id as attribute_type_id, attributes.value_type as value_type, attributes.value_byte as value_byte, "
1069 +
" attributes.value_text as value_text, attributes.value_int32 as value_int32, attributes.value_int64 as value_int64, attributes.value_double as value_double, "
1070 +
" hosts.id, hosts.name as host_name, hosts.db_status as host_status "
1071 +
" FROM tsk_os_account_attributes as attributes"
1072 +
" LEFT JOIN tsk_hosts as hosts "
1073 +
" ON attributes.host_id = hosts.id "
1074 +
" WHERE os_account_obj_id = " + account.getId();
1077 try (CaseDbConnection connection = this.db.getConnection();
1078 Statement s = connection.createStatement();
1079 ResultSet rs = connection.executeQuery(s, queryString)) {
1081 List<OsAccountAttribute> attributes =
new ArrayList<>();
1085 long hostId = rs.getLong(
"host_id");
1086 if (!rs.wasNull()) {
1087 host =
new Host(hostId, rs.getString(
"host_name"),
Host.
HostDbStatus.fromID(rs.getInt(
"host_status")));
1090 Content sourceContent = null;
1091 long sourceObjId = rs.getLong(
"source_obj_id");
1092 if (!rs.wasNull()) {
1095 BlackboardAttribute.Type attributeType = db.
getAttributeType(rs.getInt(
"attribute_type_id"));
1096 OsAccountAttribute attribute = account.new OsAccountAttribute(attributeType, rs.getInt(
"value_int32"), rs.getLong(
"value_int64"),
1097 rs.getDouble(
"value_double"), rs.getString(
"value_text"), rs.getBytes(
"value_byte"),
1098 db, account, host, sourceContent);
1100 attributes.add(attribute);
1103 }
catch (SQLException ex) {
1104 throw new TskCoreException(String.format(
"Error getting OS account attributes for account obj id = %d", account.getId()), ex);
1119 List<OsAccountInstance> getOsAccountInstances(OsAccount account)
throws TskCoreException {
1120 String whereClause =
"tsk_os_account_instances.os_account_obj_id = " + account.getId();
1121 return getOsAccountInstances(whereClause);
1135 String instanceIds = instanceIDs.stream().map(
id ->
id.toString()).collect(Collectors.joining(
","));
1136 String whereClause =
"tsk_os_account_instances.id IN (" + instanceIds +
")";
1137 return getOsAccountInstances(whereClause);
1150 private List<OsAccountInstance> getOsAccountInstances(String whereClause)
throws TskCoreException {
1151 List<OsAccountInstance> osAcctInstances =
new ArrayList<>();
1152 String querySQL =
"SELECT * FROM tsk_os_account_instances WHERE " + whereClause;
1154 try (CaseDbConnection connection = db.getConnection();
1155 PreparedStatement preparedStatement = connection.getPreparedStatement(querySQL, Statement.NO_GENERATED_KEYS);
1156 ResultSet results = connection.executeQuery(preparedStatement)) {
1157 while (results.next()) {
1158 long instanceId = results.getLong(
"id");
1159 long osAccountObjID = results.getLong(
"os_account_obj_id");
1160 long dataSourceObjId = results.getLong(
"data_source_obj_id");
1161 int instanceType = results.getInt(
"instance_type");
1164 }
catch (SQLException ex) {
1165 throw new TskCoreException(
"Failed to get OsAccountInstances (SQL = " + querySQL +
")", ex);
1169 return osAcctInstances;
1197 return updateStatus;
1199 if (trans != null) {
1224 OsAccountUpdateStatus updateStatusCode = OsAccountUpdateStatus.NO_CHANGE;
1227 CaseDbConnection connection = trans.getConnection();
1229 if (!StringUtils.isBlank(fullName)) {
1230 updateAccountColumn(osAccount.getId(),
"full_name", fullName, connection);
1231 updateStatusCode = OsAccountUpdateStatus.UPDATED;
1234 if (Objects.nonNull(accountType)) {
1235 updateAccountColumn(osAccount.getId(),
"type", accountType, connection);
1236 updateStatusCode = OsAccountUpdateStatus.UPDATED;
1239 if (Objects.nonNull(accountStatus)) {
1240 updateAccountColumn(osAccount.getId(),
"status", accountStatus, connection);
1241 updateStatusCode = OsAccountUpdateStatus.UPDATED;
1244 if (Objects.nonNull(creationTime)) {
1245 updateAccountColumn(osAccount.getId(),
"created_date", creationTime, connection);
1246 updateStatusCode = OsAccountUpdateStatus.UPDATED;
1250 if (updateStatusCode == OsAccountUpdateStatus.NO_CHANGE) {
1251 return new OsAccountUpdateResult(updateStatusCode, null);
1258 trans.registerChangedOsAccount(updatedAccount);
1260 return new OsAccountUpdateResult(updateStatusCode, updatedAccount);
1262 }
catch (SQLException ex) {
1263 throw new TskCoreException(String.format(
"Error updating account with addr = %s, account id = %d", osAccount.getAddr().orElse(
"Unknown"), osAccount.getId()), ex);
1280 private <T>
void updateAccountColumn(
long accountObjId, String colName, T colValue, CaseDbConnection connection)
throws SQLException, TskCoreException {
1282 String updateSQL =
"UPDATE tsk_os_accounts "
1283 +
" SET " + colName +
" = ? "
1284 +
" WHERE os_account_obj_id = ?";
1288 PreparedStatement preparedStatement = connection.getPreparedStatement(updateSQL, Statement.NO_GENERATED_KEYS);
1289 preparedStatement.clearParameters();
1291 if (Objects.isNull(colValue)) {
1292 preparedStatement.setNull(1, Types.NULL);
1294 if (colValue instanceof String) {
1295 preparedStatement.setString(1, (String) colValue);
1296 }
else if (colValue instanceof Long) {
1297 preparedStatement.setLong(1, (Long) colValue);
1298 }
else if (colValue instanceof Integer) {
1299 preparedStatement.setInt(1, (Integer) colValue);
1301 throw new TskCoreException(String.format(
"Unhandled column data type received while updating the account (%d) ", accountObjId));
1305 preparedStatement.setLong(2, accountObjId);
1307 connection.executeUpdate(preparedStatement);
1323 private void updateAccountSignature(
long accountObjId, String signature, CaseDbConnection connection)
throws SQLException {
1325 String updateSQL =
"UPDATE tsk_os_accounts SET "
1327 +
" CASE WHEN db_status = " + OsAccount.OsAccountDbStatus.ACTIVE.getId() +
" THEN ? ELSE signature END "
1328 +
" WHERE os_account_obj_id = ?";
1330 PreparedStatement preparedStatement = connection.getPreparedStatement(updateSQL, Statement.NO_GENERATED_KEYS);
1331 preparedStatement.clearParameters();
1333 preparedStatement.setString(1, signature);
1334 preparedStatement.setLong(2, accountObjId);
1336 connection.executeUpdate(preparedStatement);
1366 return updateStatus;
1368 if (trans != null) {
1396 if (!StringUtils.isBlank(accountSid) || !StringUtils.isBlank(realmName)) {
1397 db.
getOsAccountRealmManager().getAndUpdateWindowsRealm(accountSid, realmName, referringHost, trans.getConnection());
1401 OsAccountUpdateResult updateStatus = this.updateOsAccountCore(osAccount, accountSid, loginName, trans);
1403 return updateStatus;
1428 private OsAccountUpdateResult updateOsAccountCore(OsAccount osAccount, String address, String loginName, CaseDbTransaction trans)
throws TskCoreException {
1430 OsAccountUpdateStatus updateStatusCode = OsAccountUpdateStatus.NO_CHANGE;
1431 OsAccount updatedAccount;
1434 CaseDbConnection connection = trans.getConnection();
1437 if (!StringUtils.isBlank(address) && !StringUtils.isBlank(osAccount.getAddr().orElse(null)) && !address.equalsIgnoreCase(osAccount.getAddr().orElse(
""))) {
1438 throw new TskCoreException(String.format(
"Account (%d) already has an address (%s), address cannot be updated.", osAccount.getId(), osAccount.getAddr().orElse(
"NULL")));
1442 if (!StringUtils.isBlank(loginName) && !StringUtils.isBlank(osAccount.getLoginName().orElse(null)) && !loginName.equalsIgnoreCase(osAccount.getLoginName().orElse(
""))) {
1443 throw new TskCoreException(String.format(
"Account (%d) already has a login name (%s), login name cannot be updated.", osAccount.getId(), osAccount.getLoginName().orElse(
"NULL")));
1446 if (StringUtils.isBlank(osAccount.getAddr().orElse(null)) && !StringUtils.isBlank(address)) {
1447 updateAccountColumn(osAccount.getId(),
"addr", address, connection);
1448 updateStatusCode = OsAccountUpdateStatus.UPDATED;
1451 if (StringUtils.isBlank(osAccount.getLoginName().orElse(null)) && !StringUtils.isBlank(loginName)) {
1452 updateAccountColumn(osAccount.getId(),
"login_name", loginName, connection);
1453 updateStatusCode = OsAccountUpdateStatus.UPDATED;
1457 if (updateStatusCode == OsAccountUpdateStatus.NO_CHANGE) {
1458 return new OsAccountUpdateResult(updateStatusCode, osAccount);
1463 String newAddress = currAccount.
getAddr().orElse(null);
1464 String newLoginName = currAccount.getLoginName().orElse(null);
1466 String newSignature = getOsAccountSignature(newAddress, newLoginName);
1467 updateAccountSignature(osAccount.getId(), newSignature, connection);
1473 trans.registerChangedOsAccount(updatedAccount);
1475 return new OsAccountUpdateResult(updateStatusCode, updatedAccount);
1477 }
catch (SQLException ex) {
1478 throw new TskCoreException(String.format(
"Error updating account with unique id = %s, account id = %d", osAccount.getAddr().orElse(
"Unknown"), osAccount.getId()), ex);
1492 List<Host> hostList =
new ArrayList<>();
1494 String query =
"SELECT tsk_hosts.id AS hostId, name, db_status FROM tsk_hosts "
1495 +
" JOIN data_source_info ON tsk_hosts.id = data_source_info.host_id"
1496 +
" JOIN tsk_os_account_instances ON data_source_info.obj_id = tsk_os_account_instances.data_source_obj_id"
1497 +
" WHERE os_account_obj_id = " + account.getId();
1500 try (CaseDbConnection connection = db.getConnection();
1501 Statement s = connection.createStatement();
1502 ResultSet rs = connection.executeQuery(s, query)) {
1505 hostList.add(
new Host(rs.getLong(
"hostId"), rs.getString(
"name"),
Host.
HostDbStatus.fromID(rs.getInt(
"db_status"))));
1508 }
catch (SQLException ex) {
1509 throw new TskCoreException(String.format(
"Failed to get host list for os account %d", account.getId()), ex);
1527 private OsAccount osAccountFromResultSet(ResultSet rs)
throws SQLException {
1530 int typeId = rs.getInt(
"type");
1531 if (!rs.wasNull()) {
1535 Long creationTime = rs.getLong(
"created_date");
1537 creationTime = null;
1540 return new OsAccount(db, rs.getLong(
"os_account_obj_id"), rs.getLong(
"realm_id"), rs.getString(
"login_name"), rs.getString(
"addr"),
1541 rs.getString(
"signature"), rs.getString(
"full_name"), creationTime, accountType, OsAccount.OsAccountStatus.
fromID(rs.getInt(
"status")),
1542 OsAccount.OsAccountDbStatus.
fromID(rs.getInt(
"db_status")));
1552 private void fireChangeEvent(OsAccount account) {
1553 db.fireTSKEvent(
new OsAccountsUpdatedTskEvent(Collections.singletonList(account)));
1570 static String getOsAccountSignature(String uniqueId, String loginName)
throws TskCoreException {
1573 if (Strings.isNullOrEmpty(uniqueId) ==
false) {
1574 signature = uniqueId;
1575 }
else if (Strings.isNullOrEmpty(loginName) ==
false) {
1576 signature = loginName;
1578 throw new TskCoreException(
"OS Account must have either a uniqueID or a login name.");
1589 private static final long serialVersionUID = 1L;
1595 super(
"No error message available.");
1638 this.updateStatus = updateStatus;
1639 this.updatedAccount = updatedAccount;
1643 return updateStatus;
1647 return Optional.ofNullable(updatedAccount);
NotUserSIDException(String msg, Exception ex)
List< OsAccount > getOsAccounts()
Optional< String > getAddr()
OsAccountRealm newWindowsRealm(String accountSid, String realmName, Host referringHost, OsAccountRealm.RealmScope realmScope)
CaseDbTransaction beginTransaction()
List< Host > getHosts(OsAccount account)
OsAccount getOsAccountByObjectId(long osAccountObjId)
static OsAccountType fromID(int typeId)
void newOsAccountInstance(OsAccount osAccount, DataSource dataSource, OsAccountInstance.OsAccountInstanceType instanceType)
Optional< OsAccount > getWindowsOsAccount(String sid, String loginName, String realmName, Host referringHost)
OsAccountUpdateStatus getUpdateStatusCode()
OsAccountUpdateResult updateStandardOsAccountAttributes(OsAccount osAccount, String fullName, OsAccountType accountType, OsAccountStatus accountStatus, Long creationTime)
Content getContentById(long id)
OsAccount newWindowsOsAccount(String sid, String loginName, OsAccountRealm realm)
NotUserSIDException(String msg)
static OsAccountInstanceType fromID(int typeId)
List< OsAccount > getOsAccounts(Host host)
OsAccountRealmManager getOsAccountRealmManager()
void releaseSingleUserCaseReadLock()
Optional< OsAccountRealm > getWindowsRealm(String accountSid, String realmName, Host referringHost)
List< OsAccountInstance > getOsAccountInstances(List< Long > instanceIDs)
BlackboardAttribute.Type getAttributeType(String attrTypeName)
void acquireSingleUserCaseWriteLock()
void releaseSingleUserCaseWriteLock()
UPDATED
no change was made to account.
Optional< String > getLoginName()
Optional< Host > getScopeHost()
void acquireSingleUserCaseReadLock()
void addExtendedOsAccountAttributes(OsAccount account, List< OsAccountAttribute > accountAttributes)
Optional< OsAccount > getUpdatedAccount()
OsAccountUpdateResult updateCoreWindowsOsAccountAttributes(OsAccount osAccount, String accountSid, String loginName, String realmName, Host referringHost)
OsAccount newWindowsOsAccount(String sid, String loginName, String realmName, Host referringHost, OsAccountRealm.RealmScope realmScope)
List< String > getRealmNames()