/// <summary> /// Constructor. Starts the impersonation with the given credentials. /// Please note that the account that instantiates the Impersonator class /// needs to have the 'Act as part of operating system' privilege set. /// </summary> /// <param name="userName">The name of the user to act as.</param> /// <param name="domainName">The domain name of the user to act as.</param> /// <param name="password">The password of the user to act as.</param> public WindowsImpersonatedIdentity(string userName, string domainName, string password) { if (string.IsNullOrEmpty(userName) && string.IsNullOrEmpty(domainName) && string.IsNullOrEmpty(password)) { identity = WindowsIdentity.GetCurrent(); } else { if (Advapi32.LogonUser(userName, domainName, password, domainName == null ? LOGON_TYPE_NEW_CREDENTIALS : LOGON32_LOGON_INTERACTIVE, domainName == null ? LOGON32_PROVIDER_WINNT50 : LOGON32_PROVIDER_DEFAULT, out token) != 0) { #if NETSTANDARD || NETCOREAPP if (!NativeMethods.ImpersonateLoggedOnUser(token.DangerousGetHandle())) { throw new Win32Exception(); } #else identity = new WindowsIdentity(token.DangerousGetHandle()); impersonationContext = identity.Impersonate(); #endif } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } }
public static WindowsIdentity DuplicateToken(WindowsIdentity id) { SafeTokenHandle duplicateTokenHandle = SafeTokenHandle.InvalidHandle; try { bool bRetVal = DuplicateToken(id.Token, 2, out duplicateTokenHandle); if (false == bRetVal) { int nErrorCode = Marshal.GetLastWin32Error(); string sResult = "DuplicateToken() failed with error code: " + nErrorCode + Environment.NewLine; throw new Exception(sResult); } return(new WindowsIdentity(duplicateTokenHandle.DangerousGetHandle())); } finally { if (!duplicateTokenHandle.IsInvalid) { duplicateTokenHandle.Close(); } } }
public static void AdjustTokenPrivileges(SafeTokenHandle tokenHandle, bool disableAllPrivileges, ref TokenPrivileges newState, ref TokenPrivileges previousState) { Contract.Requires <ArgumentNullException>(tokenHandle != null, "tokenHandle cannot be null"); uint temp; if (!AdjustTokenPrivileges(tokenHandle.DangerousGetHandle(), disableAllPrivileges, ref newState, (uint)Marshal.SizeOf(previousState), ref previousState, out temp)) { WindowsApi.NativeMethods.ReportWin32Exception(); } var error = Marshal.GetLastWin32Error(); if (error == ErrorCodes.NotAllAssigned) { try { throw new PrivilegeNotHeldException(GetPrivilegeName(PrivilegeFromLuid(newState.Privileges[0].Luid))); } catch (InvalidOperationException) { throw new PrivilegeNotHeldException(); } } }
// ReSharper restore InconsistentNaming #endregion #region ImpersonateLoggedOnUser public static void ImpersonateLoggedOnUser(SafeTokenHandle tokenHandle) { Contract.Requires <ArgumentNullException>(tokenHandle != null, TokenExceptionMessage); if (!ImpersonateLoggedOnUser(tokenHandle.DangerousGetHandle())) { WindowsApi.NativeMethods.ReportWin32Exception(); } }
public void BeginImpersonation() { bool returnValue = LogonUser(userName, domainName, password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle); if (returnValue == false) { int ret = Marshal.GetLastWin32Error(); throw new System.ComponentModel.Win32Exception(ret); } impersonatedUser = WindowsIdentity.Impersonate(safeTokenHandle.DangerousGetHandle()); }
public static uint GetExitCodeProcess(SafeTokenHandle processHandle) { Contract.Requires <ArgumentNullException>(processHandle != null, "processHandle cannot be null"); uint exitCode; if (!GetExitCodeProcess(processHandle.DangerousGetHandle(), out exitCode)) { ReportWin32Exception(); } return(exitCode); }
/// <summary> /// Initialize constructor. /// </summary> /// <param name="processHandle">process handle</param> public ProcessExtended(SafeTokenHandle processHandle) { Contract.Requires <ArgumentNullException>(processHandle != null, "processHandle cannot be null"); Contract.Ensures(Process != null); Contract.Ensures(_processHandle != null); var handle = processHandle.DangerousGetHandle(); Process = Process.GetProcesses().Single(p => p.Id != 0 && p.Handle == handle); _processHandle = processHandle; _initializedByProcessHandle = true; }
public static bool WaitForSingleObject(SafeTokenHandle tokenHandle, uint milliseconds = InfiniteTimeout) { Contract.Requires <ArgumentNullException>(tokenHandle != null, TokenHandleExceptionMessage); var waitResult = (WaitResult)WaitForSingleObject(tokenHandle.DangerousGetHandle(), milliseconds); if (waitResult == WaitResult.Failed) { WindowsApi.NativeMethods.ReportWin32Exception(); } return(waitResult != WaitResult.Timeout); }
public ImpersonationIdentity(SafeTokenHandle token) { try { this.token = token; this.identity = new WindowsIdentity(token.DangerousGetHandle()); } catch (Exception e) { Util.Logging.Log(e); this.Dispose(); throw; } }
public static SafeTokenHandle DuplicateTokenEx(SafeTokenHandle existingToken, System.Security.Principal.TokenAccessLevels desiredAccess, System.Security.Principal.TokenImpersonationLevel impersonationLevel, TokenType tokenType) { Contract.Requires <ArgumentNullException>(existingToken != null, ExistingTokenExceptionMessage); IntPtr token; if (!DuplicateTokenEx(existingToken.DangerousGetHandle(), (uint)desiredAccess, IntPtr.Zero, impersonationLevel, tokenType, out token)) { WindowsApi.NativeMethods.ReportWin32Exception(); } return(new SafeTokenHandle(token)); }
public Impersonator(string domain, string userName, string password, bool service) { var type = service ? LOGON32_LOGON_BATCH : LOGON32_LOGON_INTERACTIVE; var ok = LogonUser(userName, domain, password, type, 0, out handle); if (!ok) { var error = Marshal.GetLastWin32Error(); throw $"Couldn't impersonate user: error code {error}".Throws(); } else { context = WindowsIdentity.Impersonate(handle.DangerousGetHandle()); } }
public TokenProvider Duplicate(uint desiredAccess = 0x02000000) { if (!TokensApi.DuplicateTokenEx(Token.DangerousGetHandle(), desiredAccess, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenPrimary, out var newToken)) { throw new Win32Exception(); } Token.Close(); Token = newToken; return(this); }
public static SafeTokenHandle DuplicateHandle(SafeTokenHandle sourceProcessHandle, SafeTokenHandle sourceHandle, SafeTokenHandle targetProcessHandle, uint desiredAccess, bool inheritHandle, DuplicateOptions options) { Contract.Requires <ArgumentNullException>(sourceProcessHandle != null, "sourceProcessHandle cannot be null"); Contract.Requires <ArgumentNullException>(sourceHandle != null, "sourceHandle cannot be null"); Contract.Requires <ArgumentNullException>(targetProcessHandle != null, "targetProcessHandle cannot be null"); IntPtr handle; if (!DuplicateHandle(sourceProcessHandle.DangerousGetHandle(), sourceHandle.DangerousGetHandle(), targetProcessHandle.DangerousGetHandle(), out handle, desiredAccess, inheritHandle, (uint)options)) { ReportWin32Exception(); } return(new SafeTokenHandle(handle)); }
/// <summary> /// Impersonates the specified user name. /// </summary> /// <param name="userName">Name of the user.</param> /// <param name="domain">The domain.</param> /// <param name="password">The password.</param> /// <param name="impersonationLevel">The impersonation level.</param> /// <param name="logonType">Type of the logon.</param> /// <exception cref="Win32Exception"> /// </exception> private void Impersonate(string userName, string domain, SecureString password, ImpersonationLevel impersonationLevel, LogonType logonType) { if (UnsafeWindowMethods.RevertToSelf()) { var token = Marshal.SecureStringToGlobalAllocUnicode(password); var logonProvider = (logonType == LogonType.NewCredentials) ? UnsafeWindowMethods.LogonProvider.WinNT50 : UnsafeWindowMethods.LogonProvider.Default; try { SafeTokenHandle safeTokenHandle; if (UnsafeWindowMethods.LogonUser(userName, domain, token, logonType, logonProvider, out safeTokenHandle) != 0) { using (safeTokenHandle) { if (UnsafeWindowMethods.DuplicateToken(safeTokenHandle.DangerousGetHandle(), (int)impersonationLevel, out _SafeDuplicateTokenHandle) != 0) { _ImpersonationContext = WindowsIdentity.Impersonate(_SafeDuplicateTokenHandle.DangerousGetHandle()); } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } finally { // Perform cleanup whether or not the call succeeded. // Zero-out and free the unmanaged string reference. Marshal.ZeroFreeGlobalAllocUnicode(token); } } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } }
/// <summary> /// Retrieves user by username and password. /// </summary> /// <param name="username">User name.</param> /// <param name="domain">Domain.</param> /// <param name="password">Password.</param> /// <exception cref="Exception">If user cannot be authenticated.</exception> /// <returns>Authenticated user.</returns> public static WindowsIdentity GetUser(string username, string domain, string password) { SafeTokenHandle existingTokenHandle = SafeTokenHandle.InvalidHandle; if (string.IsNullOrEmpty(domain)) { domain = Environment.MachineName; } try { const int LOGON32_PROVIDER_DEFAULT = 0; const int LOGON32_LOGON_INTERACTIVE = 2; bool impersonated = LogonUser( username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out existingTokenHandle); if (false == impersonated) { int errorCode = Marshal.GetLastWin32Error(); string result = "LogonUser() failed with error code: " + errorCode + Environment.NewLine; throw new Exception(result); } return(new WindowsIdentity(existingTokenHandle.DangerousGetHandle())); } finally { if (!existingTokenHandle.IsInvalid) { existingTokenHandle.Close(); } } }
public bool start() { try { if (winIC != null || safeTokenHandle != null) { return(false); } // Convert SecureString password to string insecure_pass. var insecure_pass = new System.Net.NetworkCredential("", password).Password; // Check if the username and password work on the given domain. using (var pc = new PrincipalContext(ContextType.Domain, domain)) if (!pc.ValidateCredentials(name, insecure_pass)) { throw new System.Security.Authentication.AuthenticationException("The user name or password is incorrect."); } // Call LogonUser to obtain a handle to an access token. var logonSuccess = LogonUser(name, domain, insecure_pass, (int)Logon32.Logon.NewCredentials, (int)Logon32.Provider.WinNT50, out safeTokenHandle); if (!logonSuccess) { throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); } // Use the token handle returned by LogonUser. winIC = WindowsIdentity.Impersonate(safeTokenHandle.DangerousGetHandle()); return(true); } catch (Exception ex) { stop(); System.Windows.Forms.MessageBox.Show(ex.Message); return(false); } }
/// <summary> /// Tries to logon a user represented by <paramref name="credential"/> via the native <see cref="LogonUser"/> function /// </summary> /// <param name="credential"><see cref="NetworkCredential"/> used to log on.</param> /// <param name="type"><see cref="LogonType"/> used to log on.</param> /// <param name="provider"><see cref="LogonProvider"/> used to log on.</param> /// <param name="id"><see cref="WindowsIdentity"/> of the logged on user if the call was successful; otherwise <c>null</c></param> /// <returns><c>true</c> if the call was successful; otherwise <c>false</c></returns> internal bool TryLogon(NetworkCredential credential, LogonType type, LogonProvider provider, out WindowsIdentity id) { id = null; // Log parameters to debug log _debugLogger.Info("LogonHelper: Trying to logon:"); _debugLogger.Info(" User: '******'", credential.UserName); _debugLogger.Info(" Domain: '{0}'", credential.Domain); _debugLogger.Info(" LogonType: '{0}'", type); _debugLogger.Info(" LogonProvider: '{0}'", provider); // Parameter Checks if (!TryCheckUserNameAndDomain(credential)) { return(false); } CheckTypeAndProvider(ref type, ref provider); // Prepare for call to LogonUser API function var passwordPtr = IntPtr.Zero; bool success; SafeTokenHandle safeTokenHandle = null; try { // Copy password in cleartext into unmanaged memory passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(credential.SecurePassword); success = LogonUser(credential.UserName, credential.Domain, passwordPtr, type, provider, out safeTokenHandle); } catch (Exception e) { if (safeTokenHandle != null) { safeTokenHandle.Dispose(); } _debugLogger.Error("LogonHelper: Exception while calling LogonUser:"******"LogonHelper: LogonUser was not successful (ErrorCode:{0}, Message:{1})", error, new Win32Exception(error).Message); return(false); } // Store Token in WindowsIdentity if LogonUser was successful _debugLogger.Info("LogonHelper: User logged on successfully"); try { id = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()); } catch (Exception e) { _debugLogger.Error("LogonHelper: Error creating WindowsIdentity:", e); return(false); } _debugLogger.Info("LogonHelper: WindowsIdentity successfully created"); return(true); } }
public NativeToken Reopen(TokenAccessLevels rights = TokenAccessLevels.AllAccess, bool inheritable = false) { var rawHandle = SafeKernelObjHandle.DuplicateHandleLocal(tokenHandle.DangerousGetHandle(), (uint)rights, inheritable, SafeKernelObjHandle.DuplicateOptions.None); return(new NativeToken(new SafeTokenHandle(rawHandle))); }
public Collection<PSObject> RunPowerShell(Dictionary<string, object> arguments, LoginViewModel clientId) { // Start with identity assigned by IIS Application Pool var poolIdentity = System.Security.Principal.WindowsIdentity.GetCurrent(); // TODO: remove, this is for initial testing //scriptPath = Path.Combine(DT2.Properties.Settings.Default.PowerShellScriptsFolder, "TestScript.ps1"); Command command = new Command(scriptPath); if (arguments != null) { foreach (var argument in arguments) { command.Parameters.Add(argument.Key, argument.Value); } } if (debug) { command.Parameters.Add("debug"); } command.Parameters.Add("log", logger); // add the ndc context string ndcContext = log4net.NDC.Pop(); log4net.NDC.Push(ndcContext); command.Parameters.Add("ndcContext", ndcContext); try { logger.Debug("Application Pool identity is " + poolIdentity.Name + ", but we will impersonate " + clientId.UserName); if (System.Security.SecurityContext.IsWindowsIdentityFlowSuppressed()) { logger.Error("PowerShell calls will fail, because IsWindowsIdentityFlowSuppressed true"); } // A RunSpace defines the operating system environment, which references HKCU\Environment // We create it now before impersonating an identity that might not have HKCU\Environment access // TODO: it may be possible to improve performance by using a RunSpacePool using (PowerShell powerShell = PowerShell.Create()) { Runspace runspace = RunspaceFactory.CreateRunspace(); runspace.Open(); powerShell.Runspace = runspace; Collection<PSObject> results; IntPtr handle; SafeTokenHandle _handle; /// Test: generate primary login token /// LOGON32_PROVIDER_DEFAULT = 0 /// logger.Debug("LogonUser call for " + clientId.UserNameNoDomain); bool logonSuccess = NativeMethods.LogonUser(clientId.UserNameNoDomain, clientId.DomainName, clientId.Password, (int) LogonType.Interactive, 0, out handle); _handle = new SafeTokenHandle(handle); if (!logonSuccess) { string errMsg = "LogonUser() for " + clientId.UserName + "failed - no handle for user credentials:" + Marshal.GetLastWin32Error(); throw new Win32Exception(errMsg); } // When 'using' block ends, the thread reverts back to previous Windows identity, // because under the hood WindowsImpersonationContext.Undo() is called by Dispose() try { using ( WindowsImpersonationContext wic = WindowsIdentity.Impersonate(_handle.DangerousGetHandle())) { // WindowsIdentity will have changed to match clientId var clientIdentity = System.Security.Principal.WindowsIdentity.GetCurrent(); logger.Debug("Application Pool identity is now " + clientIdentity.Name); powerShell.Commands.AddCommand(command); logger.Debug("Calling " + scriptPath); results = powerShell.Invoke(); } } // Back to the original identity finally { // dispose of the LogonUser handle _handle.Dispose(); // clean up RunSpace used by the PowerShell object runspace.Close(); runspace.Dispose(); } // The order is important here. Debug messages are flushed to the log *before* checking for errors // so the debug traces leading up to an error are not lost Collection<PSObject> filteredResults = new Collection<PSObject>(); foreach (PSObject result in results) { string output = result.BaseObject as string; if ((output != null) && output.StartsWith(DebugPrefix)) { if (debug) { logger.Info(output.Substring(DebugPrefix.Length)); } } else { filteredResults.Add(result); } } foreach (DebugRecord r in powerShell.Streams.Debug) { logger.Info(r.Message); } logger.Debug("Examining powershell error records"); foreach (ErrorRecord r in powerShell.Streams.Error) { // If the exception doesn't match a "to be ignored" exception, then throw it if (IgnoreExceptions.SingleOrDefault(i => i.Equals(r.Exception.GetType().FullName, StringComparison.InvariantCultureIgnoreCase)) == null) { logger.Error("Powershell reported exception:" + r.ErrorDetails); throw r.Exception; } } return filteredResults; } } catch (Exception e) { logger.Error(e); logger.Error(e.Message); logger.Error(e.StackTrace); throw; } }
internal WindowsIdentity(SafeTokenHandle safeTokenHandle) : this(safeTokenHandle.DangerousGetHandle(), null, -1) { GC.KeepAlive(safeTokenHandle); }