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-18",
new WellKnownSidInfo(
true,
"S-1-5", NTAUTHORITY_REALM_NAME,
"SYSTEM",
"Local System Account"))
174 .put(
"S-1-5-19",
new WellKnownSidInfo(
true,
"S-1-5", NTAUTHORITY_REALM_NAME,
"LOCAL SERVICE",
"Local Service Account"))
175 .put(
"S-1-5-20",
new WellKnownSidInfo(
true,
"S-1-5", NTAUTHORITY_REALM_NAME,
"NETWORK SERVICE",
"Network Service Account"))
181 private static final Map<String, WellKnownSidInfo> SPECIAL_SID_PREFIXES_MAP = ImmutableMap.<String, WellKnownSidInfo>builder()
182 .put(
"S-1-5-80",
new WellKnownSidInfo(
false,
"S-1-5-80",
"NT SERVICE",
"",
"NT Service Virtual Account"))
183 .put(
"S-1-5-82",
new WellKnownSidInfo(
false,
"S-1-5-82",
"IIS APPPOOL",
"",
"IIS AppPool Virtual Account"))
184 .put(
"S-1-5-83",
new WellKnownSidInfo(
false,
"S-1-5-83",
"NT VIRTUAL MACHINE",
"",
"Virtual Machine Virtual Account") )
185 .put(
"S-1-5-90",
new WellKnownSidInfo(
false,
"S-1-5-90",
"Window Manager",
"",
"Windows Manager Virtual Account"))
186 .put(
"S-1-5-94",
new WellKnownSidInfo(
false,
"S-1-5-94",
"WinRM Virtual Users",
"",
"Windows Remoting Virtual Account"))
187 .put(
"S-1-5-96",
new WellKnownSidInfo(
false,
"S-1-5-96",
"Font Driver Host",
"",
"Font Driver Host Virtual Account"))
195 private static final Pattern WINDOWS_SPECIAL_ACCOUNT_PREFIX_REGEX = Pattern.compile(
"^[sS]\\-1\\-5\\-(\\d+)\\-");
199 private static final Table<String, String, String> SPECIAL_ACCOUNTS_TO_SID_MAP = HashBasedTable.create();
201 SPECIAL_ACCOUNTS_TO_SID_MAP.put(NTAUTHORITY_REALM_NAME,
"SYSTEM",
"S-1-5-18");
202 SPECIAL_ACCOUNTS_TO_SID_MAP.put(NTAUTHORITY_REALM_NAME,
"LOCAL SERVICE",
"S-1-5-19");
203 SPECIAL_ACCOUNTS_TO_SID_MAP.put(NTAUTHORITY_REALM_NAME,
"NETWORK SERVICE",
"S-1-5-20");
209 private static final Map<String, String> REALM_NAME_TO_ENGLISH_MAP = ImmutableMap.<String, String>builder()
210 .put(
"NT AUTHORITY", NTAUTHORITY_REALM_NAME)
211 .put(
"NT-AUTORIT�T", NTAUTHORITY_REALM_NAME)
212 .put(
"AUTORITE NT", NTAUTHORITY_REALM_NAME)
213 .put(
"NT INSTANS", NTAUTHORITY_REALM_NAME)
219 private static final Map<String, String> LOGINNAME_TO_ENGLISH_MAP = ImmutableMap.<String, String>builder()
220 .put(
"SYSTEM",
"SYSTEM")
221 .put(
"SYST�ME",
"SYSTEM")
223 .put(
"LOCAL SERVICE",
"LOCAL SERVICE")
224 .put(
"LOKALER DIENST",
"LOCAL SERVICE")
225 .put(
"SERVICE LOCAL",
"LOCAL SERVICE")
226 .put(
"SERVIZIO LOCALE",
"LOCAL SERVICE")
227 .put(
"SERVICIO LOC",
"LOCAL SERVICE")
229 .put(
"NETWORK SERVICE",
"NETWORK SERVICE")
230 .put(
"NETZWERKDIENST",
"NETWORK SERVICE")
231 .put(
"N�TVERKSTJ�NST",
"NETWORK SERVICE")
232 .put(
"SERVICE R�SEAU",
"NETWORK SERVICE")
233 .put(
"SERVIZIO DI RETE",
"NETWORK SERVICE")
234 .put(
"SERVICIO DE RED",
"NETWORK SERVICE")
244 static boolean isWindowsWellKnownSid(String sid) {
246 String tempSID = stripWindowsBackupPostfix(sid);
247 if (SPECIAL_SIDS_MAP.containsKey(tempSID)) {
250 for (String specialPrefix: SPECIAL_SID_PREFIXES_MAP.keySet()) {
251 if (tempSID.startsWith(specialPrefix)) {
256 Matcher match = WINDOWS_SPECIAL_ACCOUNT_PREFIX_REGEX.matcher(tempSID);
258 Integer domainIdentifier = Integer.valueOf(match.group(1));
260 if (domainIdentifier != null && domainIdentifier >= 80 && domainIdentifier <= 111) {
275 static boolean isWindowsWellKnownAccountName(String loginName, String realmName) {
277 String resolvedRealmName = toWellknownEnglishRealmName(realmName);
278 String resolvedLoginName = toWellknownEnglishLoginName(loginName);
279 if (StringUtils.isBlank(resolvedRealmName) || StringUtils.isBlank(resolvedLoginName)) {
283 return SPECIAL_ACCOUNTS_TO_SID_MAP.contains(resolvedRealmName.toUpperCase(), resolvedLoginName.toUpperCase());
295 private static String getWindowsWellKnownSidRealmAddr(String sid)
throws TskCoreException {
296 String tempSID = stripWindowsBackupPostfix(sid);
298 if (SPECIAL_SIDS_MAP.containsKey(tempSID)) {
299 return SPECIAL_SIDS_MAP.get(tempSID).getRealmAddr();
302 for (Entry<String, WellKnownSidInfo> specialPrefixEntry : SPECIAL_SID_PREFIXES_MAP.entrySet()) {
303 if (tempSID.startsWith(specialPrefixEntry.getKey())) {
304 return specialPrefixEntry.getValue().getRealmAddr();
308 Matcher match = WINDOWS_SPECIAL_ACCOUNT_PREFIX_REGEX.matcher(tempSID);
310 Integer domainIdentifier = Integer.valueOf(match.group(1));
312 if (domainIdentifier != null && domainIdentifier >= 80 && domainIdentifier <= 111) {
313 String realmAddr = String.format(
"%s-%d", NTAUTHORITY_SID_PREFIX, domainIdentifier);
327 private static WellKnownSidInfo getWindowsWellKnownInfo(String sid) {
328 String tempSID = stripWindowsBackupPostfix(sid);
330 if (SPECIAL_SIDS_MAP.containsKey(tempSID)) {
331 return SPECIAL_SIDS_MAP.get(tempSID);
333 for (Entry<String, WellKnownSidInfo> specialPrefixEntry: SPECIAL_SID_PREFIXES_MAP.entrySet()) {
334 if (tempSID.startsWith(specialPrefixEntry.getKey())) {
335 return specialPrefixEntry.getValue();
348 static String getWindowsWellKnownSidFullName(String sid) {
349 WellKnownSidInfo wellKnownSidInfo = getWindowsWellKnownInfo(sid);
350 return Objects.nonNull(wellKnownSidInfo) ? wellKnownSidInfo.getDescription() :
"";
360 static String getWindowsWellKnownSidRealmName(String sid) {
362 if (StringUtils.isNotBlank(sid) && sid.equals(NTAUTHORITY_SID_PREFIX)) {
363 return NTAUTHORITY_REALM_NAME;
366 WellKnownSidInfo wellKnownSidInfo = getWindowsWellKnownInfo(sid);
367 return Objects.nonNull(wellKnownSidInfo)
368 ? wellKnownSidInfo.getRealmName()
379 static String getWindowsWellKnownSidLoginName(String sid) {
381 WellKnownSidInfo wellKnownSidInfo = getWindowsWellKnownInfo(sid);
382 return Objects.nonNull(wellKnownSidInfo)
383 ? wellKnownSidInfo.getLoginName()
396 static String getWindowsWellKnownAccountSid( String loginName, String realmName) {
398 String resolvedRealmName = toWellknownEnglishRealmName(realmName);
399 String resolvedLoginName = toWellknownEnglishLoginName(loginName);
400 if (StringUtils.isBlank(resolvedRealmName) || StringUtils.isBlank(resolvedLoginName)) {
404 return SPECIAL_ACCOUNTS_TO_SID_MAP.get(resolvedRealmName.toUpperCase(), resolvedLoginName.toUpperCase());
416 static String toWellknownEnglishRealmName(String name) {
417 return StringUtils.isNotBlank(name)
418 ? REALM_NAME_TO_ENGLISH_MAP.getOrDefault(name.toUpperCase(), name)
430 static String toWellknownEnglishLoginName(String name) {
431 return StringUtils.isNotBlank(name)
432 ? LOGINNAME_TO_ENGLISH_MAP.getOrDefault(name.toUpperCase(), name)
445 static boolean isWindowsUserSid(String sid) {
447 String tempSID = stripWindowsBackupPostfix(sid);
449 if (GROUP_SIDS.contains(tempSID)) {
453 for (String prefix: GROUP_SID_PREFIX) {
454 if (tempSID.startsWith(prefix)) {
460 if (tempSID.startsWith(NTAUTHORITY_SID_PREFIX)) {
461 for (String suffix : DOMAIN_GROUP_SID_SUFFIX) {
462 if (tempSID.endsWith(suffix)) {
485 public static String getWindowsRealmAddress(String sid)
throws TskCoreException {
488 String tempSID = stripWindowsBackupPostfix(sid);
490 if ( isWindowsWellKnownSid(tempSID)) {
491 realmAddr = getWindowsWellKnownSidRealmAddr(sid);
496 if (
org.apache.commons.lang3.StringUtils.countMatches(tempSID,
"-") < 3) {
497 throw new TskCoreException(String.format(
"Invalid SID %s for a host/domain", tempSID));
500 realmAddr = sid.substring(0, tempSID.lastIndexOf(
'-'));
514 private static String stripWindowsBackupPostfix(String sid) {
515 String tempSID = sid;
517 if(tempSID.endsWith(SPECIAL_WINDOWS_BACK_UP_POSTFIX)) {
518 tempSID = tempSID.replace(SPECIAL_WINDOWS_BACK_UP_POSTFIX,
"");