19 package org.sleuthkit.datamodel;
21 import com.google.common.annotations.Beta;
22 import com.google.common.base.Strings;
23 import org.apache.commons.lang3.StringUtils;
24 import java.sql.PreparedStatement;
25 import java.sql.ResultSet;
26 import java.sql.SQLException;
27 import java.sql.Statement;
28 import java.sql.Types;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.Locale;
32 import java.util.Objects;
33 import java.util.Optional;
34 import java.util.UUID;
35 import java.util.logging.Logger;
48 private static final String LOCAL_REALM_NAME =
"local";
82 if (realmScope == null) {
83 throw new TskCoreException(
"RealmScope cannot be null. Use UNKNOWN if scope is not known.");
85 if (referringHost == null) {
86 throw new TskCoreException(
"A referring host is required to create a realm.");
88 if ((StringUtils.isBlank(accountSid) || accountSid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID))
89 && StringUtils.isBlank(realmName)) {
90 throw new TskCoreException(
"Either an address or a name is required to create a realm.");
93 if (StringUtils.isNotBlank(accountSid)) {
95 accountSid = accountSid.toUpperCase(Locale.ENGLISH);
97 if (StringUtils.isNotBlank(realmName)) {
99 realmName = realmName.toLowerCase(Locale.ENGLISH);
105 switch (realmScope) {
111 scopeHost = referringHost;
119 boolean isHostRealmKnown = isHostRealmKnown(referringHost);
120 if (isHostRealmKnown) {
124 scopeHost = referringHost;
132 String realmAddr = null;
133 String resolvedRealmName = WindowsAccountUtils.toWellknownEnglishRealmName(realmName);
134 if (!Strings.isNullOrEmpty(accountSid) && !accountSid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID)) {
136 if (!WindowsAccountUtils.isWindowsUserSid(accountSid)) {
140 realmAddr = WindowsAccountUtils.getWindowsRealmAddress(accountSid);
143 if (WindowsAccountUtils.isWindowsWellKnownSid(accountSid)) {
146 scopeHost = referringHost;
150 String wellKnownRealmName = WindowsAccountUtils.getWindowsWellKnownSidRealmName(accountSid);
151 if (!StringUtils.isEmpty(wellKnownRealmName)) {
152 resolvedRealmName = wellKnownRealmName;
157 String signature = makeRealmSignature(realmAddr, resolvedRealmName, scopeHost);
160 return newRealm(resolvedRealmName, realmAddr, signature, scopeHost, scopeConfidence);
176 if (referringHost == null) {
177 throw new TskCoreException(
"A referring host is required to create a realm.");
180 String realmName = LOCAL_REALM_NAME;
182 String signature = makeRealmSignature(
"", realmName, referringHost);
185 return newRealm(realmName,
"", signature, referringHost, scopeConfidence);
200 if (referringHost == null) {
204 try (CaseDbConnection connection = this.db.getConnection()) {
205 return getRealmByName(LOCAL_REALM_NAME, referringHost, connection);
228 if (referringHost == null) {
229 throw new TskCoreException(
"A referring host is required get a realm.");
233 if ((Strings.isNullOrEmpty(accountSid) || accountSid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID) )
234 && Strings.isNullOrEmpty(realmName)) {
235 throw new TskCoreException(
"Realm address or name is required get a realm.");
237 if (StringUtils.isNotBlank(accountSid)) {
239 accountSid = accountSid.toUpperCase(Locale.ENGLISH);
241 if (StringUtils.isNotBlank(realmName)) {
243 realmName = realmName.toLowerCase(Locale.ENGLISH);
246 try (CaseDbConnection connection = this.db.getConnection()) {
247 return getWindowsRealm(accountSid, realmName, referringHost, connection);
268 if (referringHost == null) {
269 throw new TskCoreException(
"A referring host is required get a realm.");
273 if ((StringUtils.isBlank(accountSid) || accountSid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID))
274 && StringUtils.isBlank(realmName)) {
275 throw new TskCoreException(
"Realm address or name is required get a realm.");
279 if (!Strings.isNullOrEmpty(accountSid) && !accountSid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID)) {
281 if (!WindowsAccountUtils.isWindowsUserSid(accountSid)) {
282 throw new OsAccountManager.NotUserSIDException(String.format(
"SID = %s is not a user SID.", accountSid ));
285 String realmAddr = WindowsAccountUtils.getWindowsRealmAddress(accountSid);
286 Optional<OsAccountRealm> realm = getRealmByAddr(realmAddr, referringHost, connection);
287 if (realm.isPresent()) {
293 String resolvedRealmName = WindowsAccountUtils.toWellknownEnglishRealmName(realmName);
296 Optional<OsAccountRealm> realm = getRealmByName(resolvedRealmName, referringHost, connection);
297 if (realm.isPresent() && !Strings.isNullOrEmpty(accountSid) && !accountSid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID)) {
300 if (realm.get().getRealmAddr().isPresent()) {
301 return Optional.empty();
326 OsRealmUpdateResult getAndUpdateWindowsRealm(String accountSid, String realmName, Host referringHost, CaseDbConnection connection)
throws TskCoreException, OsAccountManager.NotUserSIDException {
329 Optional<OsAccountRealm> realmOptional =
getWindowsRealm(accountSid, realmName, referringHost, connection);
332 if (realmOptional.isPresent()) {
333 String realmAddr = (StringUtils.isNotBlank(accountSid) && !accountSid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID)) ? WindowsAccountUtils.getWindowsRealmAddress(accountSid) : null;
334 OsRealmUpdateResult realmUpdateResult =
updateRealm(realmOptional.get(), realmAddr, realmName, connection);
336 return realmUpdateResult;
339 return new OsRealmUpdateResult(OsRealmUpdateStatus.NO_CHANGE, null);
367 try (CaseDbConnection connection = db.getConnection()) {
368 return updateRealm(realm, realmAddr, realmName, connection);
394 if ( (StringUtils.isBlank(realmAddr) || realmAddr.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID))
395 && StringUtils.isBlank(realmName)) {
396 throw new TskCoreException(
"Realm address or name is required to update realm.");
399 OsRealmUpdateStatus updateStatusCode = OsRealmUpdateStatus.NO_CHANGE;
400 OsAccountRealm updatedRealm = null;
404 String currRealmAddr = realm.getRealmAddr().orElse(null);
407 if ((StringUtils.isBlank(currRealmAddr) && StringUtils.isNotBlank(realmAddr) && !realmAddr.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID))) {
408 updateRealmColumn(realm.getRealmId(),
"realm_addr", realmAddr, connection);
409 currRealmAddr = realmAddr;
410 updateStatusCode = OsRealmUpdateStatus.UPDATED;
413 List<String> realmNames = realm.getRealmNames();
414 String currRealmName = realmNames.isEmpty() ? null : realmNames.get(0);
419 if (StringUtils.isBlank(currRealmName) && StringUtils.isNotBlank(realmName)) {
420 updateRealmColumn(realm.getRealmId(),
"realm_name", realmName, connection);
421 updateStatusCode = OsRealmUpdateStatus.UPDATED;
425 if (updateStatusCode == OsRealmUpdateStatus.NO_CHANGE) {
426 return new OsRealmUpdateResult(updateStatusCode, realm);
431 String newRealmAddr = currRealm.
getRealmAddr().orElse(null);
432 String newRealmName = (currRealm.getRealmNames().isEmpty() ==
false) ? currRealm.getRealmNames().get(0) : null;
435 String newSignature = makeRealmSignature(newRealmAddr, newRealmName, realm.getScopeHost().orElse(null));
438 String updateSQL =
"UPDATE tsk_os_account_realms SET "
439 +
" realm_signature = "
440 +
" CASE WHEN db_status = " + OsAccountRealm.RealmDbStatus.ACTIVE.getId() +
" THEN ? ELSE realm_signature END "
442 PreparedStatement preparedStatement = connection.getPreparedStatement(updateSQL, Statement.NO_GENERATED_KEYS);
443 preparedStatement.clearParameters();
445 preparedStatement.setString(1, newSignature);
446 preparedStatement.setLong(2, realm.getRealmId());
447 connection.executeUpdate(preparedStatement);
452 return new OsRealmUpdateResult(updateStatusCode, updatedRealm);
453 }
catch (SQLException ex) {
454 throw new TskCoreException(String.format(
"Error updating realm with id = %d, name = %s, addr = %s", realm.getRealmId(), realmName != null ? realmName :
"Null", realm.getRealmAddr().orElse(
"Null")), ex);
473 private <T>
void updateRealmColumn(
long realmId, String colName, T colValue, CaseDbConnection connection)
throws SQLException, TskCoreException {
475 String updateSQL =
"UPDATE tsk_os_account_realms "
476 +
" SET " + colName +
" = ? "
481 PreparedStatement preparedStatement = connection.getPreparedStatement(updateSQL, Statement.NO_GENERATED_KEYS);
482 preparedStatement.clearParameters();
484 if (Objects.isNull(colValue)) {
485 preparedStatement.setNull(1, Types.NULL);
487 if (colValue instanceof String) {
488 preparedStatement.setString(1, (String) colValue);
489 }
else if (colValue instanceof Long) {
490 preparedStatement.setLong(1, (Long) colValue);
491 }
else if (colValue instanceof Integer) {
492 preparedStatement.setInt(1, (Integer) colValue);
494 throw new TskCoreException(String.format(
"Unhandled column data type received while updating the realm (id = %d) ", realmId));
498 preparedStatement.setLong(2, realmId);
500 connection.executeUpdate(preparedStatement);
506 private final static String REALM_QUERY_STRING =
"SELECT realms.id as realm_id, realms.realm_name as realm_name,"
507 +
" realms.realm_addr as realm_addr, realms.realm_signature as realm_signature, realms.scope_host_id, realms.scope_confidence, realms.db_status,"
508 +
" hosts.id, hosts.name as host_name "
509 +
" FROM tsk_os_account_realms as realms"
510 +
" LEFT JOIN tsk_hosts as hosts"
511 +
" ON realms.scope_host_id = hosts.id";
523 try (CaseDbConnection connection = this.db.getConnection()) {
539 String queryString = REALM_QUERY_STRING
540 +
" WHERE realms.id = " + id;
543 try ( Statement s = connection.createStatement();
544 ResultSet rs = connection.executeQuery(s, queryString)) {
547 accountRealm = resultSetToAccountRealm(rs);
549 throw new TskCoreException(String.format(
"No realm found with id = %d",
id));
553 }
catch (SQLException ex) {
554 throw new TskCoreException(String.format(
"Error running the realms query = %s", queryString), ex);
572 Optional<OsAccountRealm> getRealmByAddr(String realmAddr, Host host, CaseDbConnection connection)
throws TskCoreException {
576 String whereHostClause = (host == null)
578 :
" ( realms.scope_host_id = " + host.getHostId() +
" OR realms.scope_host_id IS NULL) ";
579 String queryString = REALM_QUERY_STRING
580 +
" WHERE realms.realm_addr = '"+ realmAddr +
"' "
581 +
" AND " + whereHostClause
582 +
" AND realms.db_status = " + OsAccountRealm.RealmDbStatus.ACTIVE.getId()
583 +
" ORDER BY realms.scope_host_id IS NOT NULL, realms.scope_host_id";
585 return getRealmUsingQuery(queryString, host, connection);
600 Optional<OsAccountRealm> getAnotherRealmByAddr(OsAccountRealm realm, String realmAddr, Host host, CaseDbConnection connection)
throws TskCoreException {
604 String whereHostClause = realm.getScopeHost().isPresent()
605 ?
" ( realms.scope_host_id = " + realm.getScopeHost().get().getHostId() +
" ) "
606 :
" realms.scope_host_id IS NULL ";
607 String queryString = REALM_QUERY_STRING
608 +
" WHERE realms.realm_addr = '"+ realmAddr +
"' "
609 +
" AND " + whereHostClause
610 +
" AND realms.id <> " + realm.getRealmId()
611 +
" AND realms.db_status = " + OsAccountRealm.RealmDbStatus.ACTIVE.getId()
612 +
" ORDER BY realms.scope_host_id IS NOT NULL, realms.scope_host_id";
614 return getRealmUsingQuery(queryString, host, connection);
627 Optional<OsAccountRealm> getRealmByName(String realmName, Host host, CaseDbConnection connection)
throws TskCoreException {
631 String whereHostClause = (host == null)
633 :
" ( realms.scope_host_id = " + host.getHostId() +
" OR realms.scope_host_id IS NULL ) ";
634 String queryString = REALM_QUERY_STRING
635 +
" WHERE realms.realm_name = '" + realmName +
"'"
636 +
" AND " + whereHostClause
637 +
" AND realms.db_status = " + OsAccountRealm.RealmDbStatus.ACTIVE.getId()
638 +
" ORDER BY realms.scope_host_id IS NOT NULL, realms.scope_host_id";
640 return getRealmUsingQuery(queryString, host, connection);
655 Optional<OsAccountRealm> getAnotherRealmByName(OsAccountRealm realm, String realmName, Host host, CaseDbConnection connection)
throws TskCoreException {
659 String whereHostClause = realm.getScopeHost().isPresent()
660 ?
" ( realms.scope_host_id = " + realm.getScopeHost().get().getHostId() +
" ) "
661 :
" realms.scope_host_id IS NULL ";
662 String queryString = REALM_QUERY_STRING
663 +
" WHERE realms.realm_name = '" + realmName +
"'"
664 +
" AND " + whereHostClause
665 +
" AND realms.id <> " + realm.getRealmId()
666 +
" AND realms.db_status = " + OsAccountRealm.RealmDbStatus.ACTIVE.getId()
667 +
" ORDER BY realms.scope_host_id IS NOT NULL, realms.scope_host_id";
669 return getRealmUsingQuery(queryString, host, connection);
684 private Optional<OsAccountRealm> getRealmUsingQuery(String queryString, Host host, CaseDbConnection connection)
throws TskCoreException {
687 try (Statement s = connection.createStatement();
688 ResultSet rs = connection.executeQuery(s, queryString)) {
690 OsAccountRealm accountRealm = null;
692 Host realmHost = null;
693 long hostId = rs.getLong(
"scope_host_id");
698 realmHost =
new Host(hostId, rs.getString(
"host_name"));
702 accountRealm =
new OsAccountRealm(rs.getLong(
"realm_id"), rs.getString(
"realm_name"),
703 rs.getString(
"realm_addr"), rs.getString(
"realm_signature"),
704 realmHost, ScopeConfidence.fromID(rs.getInt(
"scope_confidence")),
705 OsAccountRealm.RealmDbStatus.fromID(rs.getInt(
"db_status")));
708 return Optional.ofNullable(accountRealm);
709 }
catch (SQLException ex) {
710 throw new TskCoreException(String.format(
"Error getting realm using query = %s", queryString), ex);
731 private boolean isHostRealmKnown(Host host)
throws TskCoreException {
734 String queryString = REALM_QUERY_STRING
735 +
" WHERE realms.scope_host_id = " + host.getHostId()
736 +
" AND realms.scope_confidence = " + OsAccountRealm.ScopeConfidence.KNOWN.getId()
737 +
" AND realms.db_status = " + OsAccountRealm.RealmDbStatus.ACTIVE.getId();
740 try (CaseDbConnection connection = this.db.getConnection();
741 Statement s = connection.createStatement();
742 ResultSet rs = connection.executeQuery(s, queryString)) {
746 }
catch (SQLException ex) {
747 throw new TskCoreException(String.format(
"Error getting account realm for with host = %s", host.getName()), ex);
762 private OsAccountRealm resultSetToAccountRealm(ResultSet rs)
throws SQLException {
764 long hostId = rs.getLong(
"scope_host_id");
765 Host realmHost = null;
767 realmHost =
new Host(hostId, rs.getString(
"host_name"));
770 return new OsAccountRealm(rs.getLong(
"realm_id"), rs.getString(
"realm_name"),
771 rs.getString(
"realm_addr"), rs.getString(
"realm_signature"),
772 realmHost, ScopeConfidence.fromID(rs.getInt(
"scope_confidence")),
773 OsAccountRealm.RealmDbStatus.fromID(rs.getInt(
"db_status")));
833 private OsAccountRealm newRealm(String realmName, String realmAddr, String signature, Host host, OsAccountRealm.ScopeConfidence scopeConfidence) throws TskCoreException {
836 try (CaseDbConnection connection = this.db.getConnection()) {
837 String realmInsertSQL =
"INSERT INTO tsk_os_account_realms(realm_name, realm_addr, realm_signature, scope_host_id, scope_confidence)"
838 +
" VALUES (?, ?, ?, ?, ?)";
840 PreparedStatement preparedStatement = connection.getPreparedStatement(realmInsertSQL, Statement.RETURN_GENERATED_KEYS);
841 preparedStatement.clearParameters();
843 preparedStatement.setString(1, realmName);
844 preparedStatement.setString(2, realmAddr);
845 preparedStatement.setString(3, signature);
847 preparedStatement.setLong(4, host.getHostId());
849 preparedStatement.setNull(4, java.sql.Types.BIGINT);
851 preparedStatement.setInt(5, scopeConfidence.getId());
853 connection.executeUpdate(preparedStatement);
856 try (ResultSet resultSet = preparedStatement.getGeneratedKeys();) {
857 long rowId = resultSet.getLong(1);
858 return new OsAccountRealm(rowId, realmName, realmAddr, signature, host, scopeConfidence, OsAccountRealm.RealmDbStatus.ACTIVE);
861 }
catch (SQLException ex) {
863 try (CaseDbConnection connection = this.db.getConnection()) {
864 if (!Strings.isNullOrEmpty(realmAddr)) {
865 Optional<OsAccountRealm> accountRealm = this.getRealmByAddr(realmAddr, host, connection);
866 if (accountRealm.isPresent()) {
867 return accountRealm.get();
869 }
else if (!Strings.isNullOrEmpty(realmName)) {
870 Optional<OsAccountRealm> accountRealm = this.getRealmByName(realmName, host, connection);
871 if (accountRealm.isPresent()) {
872 return accountRealm.get();
877 throw new TskCoreException(String.format(
"Error creating realm with address = %s and name = %s, with host = %s",
878 realmAddr != null ? realmAddr :
"", realmName != null ? realmName :
"", host != null ? host.getName() :
""), ex);
902 static String makeRealmSignature(String realmAddr, String realmName, Host scopeHost)
throws TskCoreException {
905 if (Strings.isNullOrEmpty(realmAddr) && Strings.isNullOrEmpty(realmName)) {
906 throw new TskCoreException(
"Realm address and name can't both be null.");
909 String signature = String.format(
"%s_%s", !Strings.isNullOrEmpty(realmAddr) ? realmAddr : realmName,
910 scopeHost != null ? scopeHost.getHostId() :
"DOMAIN");
919 private String makeMergedRealmSignature() {
920 return "MERGED " + UUID.randomUUID().toString();
932 void moveOrMergeRealm(OsAccountRealm sourceRealm, Host destHost, CaseDbTransaction trans)
throws TskCoreException {
934 Optional<OsAccountRealm> optDestRealmAddr = Optional.empty();
935 if (sourceRealm.getRealmAddr().isPresent()) {
936 optDestRealmAddr = db.
getOsAccountRealmManager().getRealmByAddr(sourceRealm.getRealmAddr().get(), destHost, trans.getConnection());
940 Optional<OsAccountRealm> optDestRealmName = Optional.empty();
941 if (!sourceRealm.getRealmNames().isEmpty()) {
942 optDestRealmName = db.
getOsAccountRealmManager().getRealmByName(sourceRealm.getRealmNames().get(0), destHost, trans.getConnection());
957 OsAccountRealm destRealm = null;
958 if (optDestRealmAddr.isPresent() && optDestRealmName.isPresent()) {
959 if (optDestRealmAddr.get().getRealmId() == optDestRealmName.get().getRealmId()) {
961 destRealm = optDestRealmAddr.get();
963 if (optDestRealmName.get().getRealmAddr().isPresent()) {
965 destRealm = optDestRealmAddr.get();
969 mergeRealms(optDestRealmName.get(), optDestRealmAddr.get(), trans);
970 destRealm =
getRealmByRealmId(optDestRealmAddr.get().getRealmId(), trans.getConnection());
973 }
else if (optDestRealmAddr.isPresent()) {
975 destRealm = optDestRealmAddr.get();
976 }
else if (optDestRealmName.isPresent()) {
980 if (! (optDestRealmName.get().getRealmAddr().isPresent() && sourceRealm.getRealmAddr().isPresent())) {
981 destRealm = optDestRealmName.get();
986 if (destRealm == null) {
987 moveRealm(sourceRealm, destHost, trans);
989 mergeRealms(sourceRealm, destRealm, trans);
1004 private void moveRealm(OsAccountRealm sourceRealm, Host destHost, CaseDbTransaction trans)
throws TskCoreException {
1005 try(Statement s = trans.getConnection().createStatement()) {
1006 String query =
"UPDATE tsk_os_account_realms SET scope_host_id = " + destHost.getHostId() +
" WHERE id = " + sourceRealm.getRealmId();
1007 s.executeUpdate(query);
1008 }
catch (SQLException ex) {
1009 throw new TskCoreException(
"Error moving realm with id: " + sourceRealm.getRealmId() +
" to host with id: " + destHost.getHostId(), ex);
1023 void mergeRealms(OsAccountRealm sourceRealm, OsAccountRealm destRealm, CaseDbTransaction trans)
throws TskCoreException {
1029 CaseDbConnection connection = trans.getConnection();
1030 try (Statement statement = connection.createStatement()) {
1031 String updateStr =
"UPDATE tsk_os_account_realms SET db_status = " + OsAccountRealm.RealmDbStatus.MERGED.getId()
1032 +
", merged_into = " + destRealm.getRealmId()
1033 +
", realm_signature = '" + makeMergedRealmSignature() +
"' "
1034 +
" WHERE id = " + sourceRealm.getRealmId();
1035 connection.executeUpdate(statement, updateStr);
1036 }
catch (SQLException ex) {
1037 throw new TskCoreException (
"Error updating status of realm with id: " + sourceRealm.getRealmId(), ex);
1041 if (!destRealm.getRealmAddr().isPresent() && sourceRealm.getRealmAddr().isPresent()) {
1042 updateRealm(destRealm, sourceRealm.getRealmAddr().get(), null, trans.getConnection());
1043 }
else if (destRealm.getRealmNames().isEmpty() && !sourceRealm.getRealmNames().isEmpty()) {
1044 updateRealm(destRealm, null, sourceRealm.getRealmNames().get(0), trans.getConnection());
1058 List<OsAccountRealm> getRealmsByHost(Host host, CaseDbConnection connection)
throws TskCoreException {
1059 List<OsAccountRealm> results =
new ArrayList<>();
1060 String queryString = REALM_QUERY_STRING
1061 +
" WHERE realms.scope_host_id = " + host.getHostId();
1064 try ( Statement s = connection.createStatement();
1065 ResultSet rs = connection.executeQuery(s, queryString)) {
1067 results.add(resultSetToAccountRealm(rs));
1070 }
catch (SQLException ex) {
1071 throw new TskCoreException(String.format(
"Error gettings realms for host with id = " + host.getHostId()), ex);
1098 this.updateStatus = updateStatus;
1099 this.updatedRealm = updatedRealm;
1103 return updateStatus;
1107 return Optional.ofNullable(updatedRealm);
OsAccountRealm newWindowsRealm(String accountSid, String realmName, Host referringHost, OsAccountRealm.RealmScope realmScope)
Optional< OsAccountRealm > getUpdatedRealm()
OsAccountRealm newLocalLinuxRealm(Host referringHost)
Optional< OsAccountRealm > getLocalLinuxRealm(Host referringHost)
OsRealmUpdateResult updateRealm(OsAccountRealm realm, String realmAddr, String realmName)
OsAccountRealmManager getOsAccountRealmManager()
void releaseSingleUserCaseReadLock()
Optional< OsAccountRealm > getWindowsRealm(String accountSid, String realmName, Host referringHost)
void acquireSingleUserCaseWriteLock()
void releaseSingleUserCaseWriteLock()
Optional< String > getRealmAddr()
OsAccountManager getOsAccountManager()
void acquireSingleUserCaseReadLock()
UPDATED
no change was made to account.
OsAccountRealm getRealmByRealmId(long id)
OsRealmUpdateStatus getUpdateStatus()