/// <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();
                }
            }
        }
Example #3
0
        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();
                }
            }
        }
Example #4
0
        // 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());
 }
Example #6
0
        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);
        }
Example #7
0
        /// <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;
        }
Example #8
0
        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);
        }
Example #9
0
 public ImpersonationIdentity(SafeTokenHandle token)
 {
     try
     {
         this.token    = token;
         this.identity = new WindowsIdentity(token.DangerousGetHandle());
     }
     catch (Exception e)
     {
         Util.Logging.Log(e);
         this.Dispose();
         throw;
     }
 }
Example #10
0
        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));
        }
Example #11
0
        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());
            }
        }
Example #12
0
        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);
        }
Example #13
0
        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));
        }
Example #14
0
        /// <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);
            }
        }
Example #17
0
        /// <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);
            }
        }
Example #18
0
        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)));
        }
Example #19
0
        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);
 }