2using System.Diagnostics.CodeAnalysis;
3using System.DirectoryServices.AccountManagement;
4using System.Runtime.Versioning;
5using System.Security.Principal;
7using System.Threading.Tasks;
9using Microsoft.Extensions.Logging;
10using Microsoft.Win32.SafeHandles;
21 [SupportedOSPlatform(
"windows")]
27 readonly ILogger<WindowsSystemIdentityFactory>
logger;
37 var splits = input.Split(
'\\');
38 username = splits.Length > 1 ? splits[1] : splits[0];
39 domainName = splits.Length > 1 ? splits[0] :
null;
48 this.logger =
logger ??
throw new ArgumentNullException(nameof(
logger));
58 ArgumentNullException.ThrowIfNull(user);
60 if (user.SystemIdentifier ==
null)
61 throw new InvalidOperationException(
"User's SystemIdentifier must not be null!");
63 PrincipalContext? pc =
null;
66 bool TryGetPrincipalFromContextType(ContextType contextType, [NotNullWhen(
true)] out UserPrincipal? principal)
71 pc = domainName !=
null
72 ?
new PrincipalContext(contextType, domainName)
73 :
new PrincipalContext(contextType);
74 cancellationToken.ThrowIfCancellationRequested();
75 principal = UserPrincipal.FindByIdentity(pc, user.SystemIdentifier);
77 catch (OperationCanceledException)
85 "Error loading user for context type {contextType} and principal \"{domainName}\"!",
91 if (principal ==
null)
94 cancellationToken.ThrowIfCancellationRequested();
98 return principal !=
null;
101 if (!TryGetPrincipalFromContextType(ContextType.Machine, out var principal) && !TryGetPrincipalFromContextType(ContextType.Domain, out principal))
107 TaskScheduler.Current);
110 public Task<ISystemIdentity?>
CreateSystemIdentity(
string username,
string password, CancellationToken cancellationToken) => Task.Factory.StartNew(
113 ArgumentNullException.ThrowIfNull(username);
114 ArgumentNullException.ThrowIfNull(password);
116 var originalUsername = username;
122 logger.LogTrace(
"Invalid system identity/password combo for username {0}!", originalUsername);
126 logger.LogTrace(
"Authenticated username {0} using system identity!", originalUsername);
129 using var handle =
new SafeAccessTokenHandle(token);
131 new WindowsIdentity(handle.DangerousGetHandle()));
135 TaskScheduler.Current);
IIOManager that resolves paths to Environment.CurrentDirectory.
const TaskCreationOptions BlockingTaskCreationOptions
The TaskCreationOptions used to spawn Tasks for potentially long running, blocking operations.
ISystemIdentityFactory for windows systems. Uses long running tasks due to potential networked domain...
readonly ILogger< WindowsSystemIdentityFactory > logger
The ILogger for the WindowsSystemIdentityFactory.
WindowsSystemIdentityFactory(ILogger< WindowsSystemIdentityFactory > logger)
Initializes a new instance of the WindowsSystemIdentityFactory class.
static void GetUserAndDomainName(string input, out string username, out string? domainName)
Extract the username and domain name from a string in the format "username\\domainname".
ISystemIdentity GetCurrent()
Retrieves a ISystemIdentity representing the user executing tgstation-server. A ISystemIdentity repre...
Task< ISystemIdentity?> CreateSystemIdentity(User user, CancellationToken cancellationToken)
Create a ISystemIdentity for a given user . A Task<TResult> resulting in a new ISystemIdentity based ...
Task< ISystemIdentity?> CreateSystemIdentity(string username, string password, CancellationToken cancellationToken)
Create a ISystemIdentity for a given username and password. A Task<TResult> resulting in a new ISyste...
ISystemIdentity for windows systems.
Native methods used by the code.
static bool LogonUser(string lpszUsername, string? lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken)
See https://msdn.microsoft.com/en-us/library/windows/desktop/aa378184(v=vs.85).aspx.
Factory for ISystemIdentitys.
Represents a user on the current global::System.Runtime.InteropServices.OSPlatform.