19 package org.sleuthkit.datamodel;
21 import com.google.common.collect.ImmutableMap;
22 import com.google.common.collect.ImmutableSet;
24 import java.util.Map.Entry;
25 import java.util.Objects;
26 import java.util.Optional;
28 import java.util.regex.Matcher;
29 import java.util.regex.Pattern;
30 import org.apache.commons.lang3.StringUtils;
31 import com.google.common.collect.HashBasedTable;
32 import com.google.common.collect.Table;
33 import java.util.Locale;
43 final class WindowsAccountUtils {
46 final static String SPECIAL_WINDOWS_BACK_UP_POSTFIX =
".bak";
50 final static String WINDOWS_NULL_SID =
"S-1-0-0";
55 private static final Set<String> GROUP_SIDS = ImmutableSet.of(
85 private static final Set<String> GROUP_SID_PREFIX = ImmutableSet.of(
92 private static final String NTAUTHORITY_SID_PREFIX =
"S-1-5";
93 private static final String NTAUTHORITY_REALM_NAME =
"NT AUTHORITY";
96 private static final Set<String> DOMAIN_GROUP_SID_SUFFIX = ImmutableSet.of(
131 WellKnownSidInfo(
boolean isUserSID, String addr, String realmName, String loginName, String description) {
132 this.realmAddr = addr;
133 this.isUserSID = isUserSID;
134 this.realmName = realmName;
135 this.loginName = this.isUserSID ? loginName :
"";
136 this.description = description;
139 private final String realmAddr;
140 private final boolean isUserSID;
141 private final String realmName;
142 private final String loginName;
143 private final String description;
172 private static final Map<String, WellKnownSidInfo> SPECIAL_SIDS_MAP = ImmutableMap.<String, WellKnownSidInfo>builder()
173 .put(
"S-1-5-17",
new WellKnownSidInfo(
true,
"S-1-5", NTAUTHORITY_REALM_NAME,
"IUSR",
"IIS Default Account"))
174 .put(
"S-1-5-18",
new WellKnownSidInfo(
true,
"S-1-5", NTAUTHORITY_REALM_NAME,
"SYSTEM",
"Local System Account"))
175 .put(
"S-1-5-19",
new WellKnownSidInfo(
true,
"S-1-5", NTAUTHORITY_REALM_NAME,
"LOCAL SERVICE",
"Local Service Account"))
176 .put(
"S-1-5-20",
new WellKnownSidInfo(
true,
"S-1-5", NTAUTHORITY_REALM_NAME,
"NETWORK SERVICE",
"Network Service Account"))
182 private static final Map<String, WellKnownSidInfo> SPECIAL_SID_PREFIXES_MAP = ImmutableMap.<String, WellKnownSidInfo>builder()
183 .put(
"S-1-5-80",
new WellKnownSidInfo(
false,
"S-1-5-80",
"NT SERVICE",
"",
"NT Service Virtual Account"))
184 .put(
"S-1-5-82",
new WellKnownSidInfo(
false,
"S-1-5-82",
"IIS APPPOOL",
"",
"IIS AppPool Virtual Account"))
185 .put(
"S-1-5-83",
new WellKnownSidInfo(
false,
"S-1-5-83",
"NT VIRTUAL MACHINE",
"",
"Virtual Machine Virtual Account") )
186 .put(
"S-1-5-90",
new WellKnownSidInfo(
false,
"S-1-5-90",
"Window Manager",
"",
"Windows Manager Virtual Account"))
187 .put(
"S-1-5-94",
new WellKnownSidInfo(
false,
"S-1-5-94",
"WinRM Virtual Users",
"",
"Windows Remoting Virtual Account"))
188 .put(
"S-1-5-96",
new WellKnownSidInfo(
false,
"S-1-5-96",
"Font Driver Host",
"",
"Font Driver Host Virtual Account"))
196 private static final Pattern WINDOWS_SPECIAL_ACCOUNT_PREFIX_REGEX = Pattern.compile(
"^[sS]\\-1\\-5\\-(\\d+)\\-");
200 private static final Table<String, String, String> SPECIAL_ACCOUNTS_TO_SID_MAP = HashBasedTable.create();
202 SPECIAL_ACCOUNTS_TO_SID_MAP.put(NTAUTHORITY_REALM_NAME,
"SYSTEM",
"S-1-5-18");
203 SPECIAL_ACCOUNTS_TO_SID_MAP.put(NTAUTHORITY_REALM_NAME,
"LOCAL SERVICE",
"S-1-5-19");
204 SPECIAL_ACCOUNTS_TO_SID_MAP.put(NTAUTHORITY_REALM_NAME,
"NETWORK SERVICE",
"S-1-5-20");
210 private static final Map<String, String> REALM_NAME_TO_ENGLISH_MAP = ImmutableMap.<String, String>builder()
211 .put(
"NT AUTHORITY", NTAUTHORITY_REALM_NAME)
212 .put(
"NT-AUTORIT�T", NTAUTHORITY_REALM_NAME)
213 .put(
"AUTORITE NT", NTAUTHORITY_REALM_NAME)
214 .put(
"NT INSTANS", NTAUTHORITY_REALM_NAME)
220 private static final Map<String, String> LOGINNAME_TO_ENGLISH_MAP = ImmutableMap.<String, String>builder()
221 .put(
"SYSTEM",
"SYSTEM")
222 .put(
"SYST�ME",
"SYSTEM")
224 .put(
"LOCAL SERVICE",
"LOCAL SERVICE")
225 .put(
"LOKALER DIENST",
"LOCAL SERVICE")
226 .put(
"SERVICE LOCAL",
"LOCAL SERVICE")
227 .put(
"SERVIZIO LOCALE",
"LOCAL SERVICE")
228 .put(
"SERVICIO LOC",
"LOCAL SERVICE")
230 .put(
"NETWORK SERVICE",
"NETWORK SERVICE")
231 .put(
"NETZWERKDIENST",
"NETWORK SERVICE")
232 .put(
"N�TVERKSTJ�NST",
"NETWORK SERVICE")
233 .put(
"SERVICE R�SEAU",
"NETWORK SERVICE")
234 .put(
"SERVIZIO DI RETE",
"NETWORK SERVICE")
235 .put(
"SERVICIO DE RED",
"NETWORK SERVICE")
245 static boolean isWindowsWellKnownSid(String sid) {
247 String tempSID = stripWindowsBackupPostfix(sid);
248 if (SPECIAL_SIDS_MAP.containsKey(tempSID)) {
251 for (String specialPrefix: SPECIAL_SID_PREFIXES_MAP.keySet()) {
252 if (tempSID.startsWith(specialPrefix)) {
257 Matcher match = WINDOWS_SPECIAL_ACCOUNT_PREFIX_REGEX.matcher(tempSID);
259 Integer domainIdentifier = Integer.valueOf(match.group(1));
261 if (domainIdentifier != null && domainIdentifier >= 80 && domainIdentifier <= 111) {
276 static boolean isWindowsWellKnownAccountName(String loginName, String realmName) {
278 String resolvedRealmName = toWellknownEnglishRealmName(realmName);
279 String resolvedLoginName = toWellknownEnglishLoginName(loginName);
280 if (StringUtils.isBlank(resolvedRealmName) || StringUtils.isBlank(resolvedLoginName)) {
284 return SPECIAL_ACCOUNTS_TO_SID_MAP.contains(resolvedRealmName.toUpperCase(), resolvedLoginName.toUpperCase());
296 private static String getWindowsWellKnownSidRealmAddr(String sid)
throws TskCoreException {
297 String tempSID = stripWindowsBackupPostfix(sid);
299 if (SPECIAL_SIDS_MAP.containsKey(tempSID)) {
300 return SPECIAL_SIDS_MAP.get(tempSID).getRealmAddr();
303 for (Entry<String, WellKnownSidInfo> specialPrefixEntry : SPECIAL_SID_PREFIXES_MAP.entrySet()) {
304 if (tempSID.startsWith(specialPrefixEntry.getKey())) {
305 return specialPrefixEntry.getValue().getRealmAddr();
309 Matcher match = WINDOWS_SPECIAL_ACCOUNT_PREFIX_REGEX.matcher(tempSID);
311 Integer domainIdentifier = Integer.valueOf(match.group(1));
313 if (domainIdentifier != null && domainIdentifier >= 80 && domainIdentifier <= 111) {
314 String realmAddr = String.format(
"%s-%d", NTAUTHORITY_SID_PREFIX, domainIdentifier);
328 private static WellKnownSidInfo getWindowsWellKnownInfo(String sid) {
329 String tempSID = stripWindowsBackupPostfix(sid);
331 if (SPECIAL_SIDS_MAP.containsKey(tempSID)) {
332 return SPECIAL_SIDS_MAP.get(tempSID);
334 for (Entry<String, WellKnownSidInfo> specialPrefixEntry: SPECIAL_SID_PREFIXES_MAP.entrySet()) {
335 if (tempSID.startsWith(specialPrefixEntry.getKey())) {
336 return specialPrefixEntry.getValue();
349 static String getWindowsWellKnownSidFullName(String sid) {
350 WellKnownSidInfo wellKnownSidInfo = getWindowsWellKnownInfo(sid);
351 return Objects.nonNull(wellKnownSidInfo) ? wellKnownSidInfo.getDescription() :
"";
361 static String getWindowsWellKnownSidRealmName(String sid) {
363 if (StringUtils.isNotBlank(sid) && sid.equals(NTAUTHORITY_SID_PREFIX)) {
364 return NTAUTHORITY_REALM_NAME;
367 WellKnownSidInfo wellKnownSidInfo = getWindowsWellKnownInfo(sid);
368 return Objects.nonNull(wellKnownSidInfo)
369 ? wellKnownSidInfo.getRealmName()
380 static String getWindowsWellKnownSidLoginName(String sid) {
382 WellKnownSidInfo wellKnownSidInfo = getWindowsWellKnownInfo(sid);
383 return Objects.nonNull(wellKnownSidInfo)
384 ? wellKnownSidInfo.getLoginName()
397 static String getWindowsWellKnownAccountSid( String loginName, String realmName) {
399 String resolvedRealmName = toWellknownEnglishRealmName(realmName);
400 String resolvedLoginName = toWellknownEnglishLoginName(loginName);
401 if (StringUtils.isBlank(resolvedRealmName) || StringUtils.isBlank(resolvedLoginName)) {
405 return SPECIAL_ACCOUNTS_TO_SID_MAP.get(resolvedRealmName.toUpperCase(), resolvedLoginName.toUpperCase());
417 static String toWellknownEnglishRealmName(String name) {
418 return StringUtils.isNotBlank(name)
419 ? REALM_NAME_TO_ENGLISH_MAP.getOrDefault(name.toUpperCase(), name)
431 static String toWellknownEnglishLoginName(String name) {
432 return StringUtils.isNotBlank(name)
433 ? LOGINNAME_TO_ENGLISH_MAP.getOrDefault(name.toUpperCase(), name)
446 static boolean isWindowsUserSid(String sid) {
448 String tempSID = stripWindowsBackupPostfix(sid);
450 if (GROUP_SIDS.contains(tempSID)) {
454 for (String prefix: GROUP_SID_PREFIX) {
455 if (tempSID.startsWith(prefix)) {
461 if (tempSID.startsWith(NTAUTHORITY_SID_PREFIX)) {
462 for (String suffix : DOMAIN_GROUP_SID_SUFFIX) {
463 if (tempSID.endsWith(suffix)) {
486 public static String getWindowsRealmAddress(String sid)
throws TskCoreException {
489 String tempSID = stripWindowsBackupPostfix(sid);
491 if ( isWindowsWellKnownSid(tempSID)) {
492 realmAddr = getWindowsWellKnownSidRealmAddr(sid);
497 if (
org.apache.commons.lang3.StringUtils.countMatches(tempSID,
"-") < 3) {
498 throw new TskCoreException(String.format(
"Invalid SID %s for a host/domain", tempSID));
501 realmAddr = sid.substring(0, tempSID.lastIndexOf(
'-'));
515 private static String stripWindowsBackupPostfix(String sid) {
516 String tempSID = sid;
518 if(tempSID.endsWith(SPECIAL_WINDOWS_BACK_UP_POSTFIX)) {
519 tempSID = tempSID.replace(SPECIAL_WINDOWS_BACK_UP_POSTFIX,
"");