Exemplo n.º 1
0
 public static extern bool CreateProcessWithTokenW(
     SafeNativeHandle hToken,
     LogonFlags dwLogonFlags,
     [MarshalAs(UnmanagedType.LPWStr)] string lpApplicationName,
     StringBuilder lpCommandLine,
     Process.NativeHelpers.ProcessCreationFlags dwCreationFlags,
     Process.SafeMemoryBuffer lpEnvironment,
     [MarshalAs(UnmanagedType.LPWStr)] string lpCurrentDirectory,
     Process.NativeHelpers.STARTUPINFOEX lpStartupInfo,
     out Process.NativeHelpers.PROCESS_INFORMATION lpProcessInformation);
Exemplo n.º 2
0
        /// <summary>
        /// Creates a process as another user account. This method will attempt to run as another user with the
        /// highest possible permissions available. The main privilege required is the SeDebugPrivilege, without
        /// this privilege you can only run as a local or domain user if the username and password is specified.
        /// </summary>
        /// <param name="username">The username of the runas user</param>
        /// <param name="password">The password of the runas user</param>
        /// <param name="logonFlags">LogonFlags to control how to logon a user when the password is specified</param>
        /// <param name="logonType">Controls what type of logon is used, this only applies when the password is specified</param>
        /// <param name="lpApplicationName">The name of the executable or batch file to executable</param>
        /// <param name="lpCommandLine">The command line to execute, typically this includes lpApplication as the first argument</param>
        /// <param name="lpCurrentDirectory">The full path to the current directory for the process, null will have the same cwd as the calling process</param>
        /// <param name="environment">A dictionary of key/value pairs to define the new process environment</param>
        /// <param name="stdin">Bytes sent to the stdin pipe</param>
        /// <returns>Ansible.Process.Result object that contains the command output and return code</returns>
        public static Result CreateProcessAsUser(string username, string password, LogonFlags logonFlags, LogonType logonType,
                                                 string lpApplicationName, string lpCommandLine, string lpCurrentDirectory, IDictionary environment, byte[] stdin)
        {
            // While we use STARTUPINFOEX having EXTENDED_STARTUPINFO_PRESENT causes a parameter validation error
            Process.NativeHelpers.ProcessCreationFlags creationFlags = Process.NativeHelpers.ProcessCreationFlags.CREATE_UNICODE_ENVIRONMENT;
            Process.NativeHelpers.PROCESS_INFORMATION  pi            = new Process.NativeHelpers.PROCESS_INFORMATION();
            Process.NativeHelpers.STARTUPINFOEX        si            = new Process.NativeHelpers.STARTUPINFOEX();
            si.startupInfo.dwFlags = Process.NativeHelpers.StartupInfoFlags.USESTDHANDLES;

            SafeFileHandle stdoutRead, stdoutWrite, stderrRead, stderrWrite, stdinRead, stdinWrite;

            ProcessUtil.CreateStdioPipes(si, out stdoutRead, out stdoutWrite, out stderrRead, out stderrWrite,
                                         out stdinRead, out stdinWrite);
            FileStream stdinStream = new FileStream(stdinWrite, FileAccess.Write);

            // $null from PowerShell ends up as an empty string, we need to convert back as an empty string doesn't
            // make sense for these parameters
            if (lpApplicationName == "")
            {
                lpApplicationName = null;
            }

            if (lpCurrentDirectory == "")
            {
                lpCurrentDirectory = null;
            }

            using (SafeMemoryBuffer lpEnvironment = ProcessUtil.CreateEnvironmentPointer(environment))
            {
                // A user may have 2 tokens, 1 limited and 1 elevated. GetUserToken will try and get both but we will
                // only find out if the elevated token is valid when running here.
                List <SafeNativeHandle> userTokens = GetUserTokens(username, password, logonType);

                bool          launchSuccess = false;
                StringBuilder commandLine   = new StringBuilder(lpCommandLine);
                foreach (SafeNativeHandle token in userTokens)
                {
                    if (NativeMethods.CreateProcessWithTokenW(token, logonFlags, lpApplicationName, commandLine,
                                                              creationFlags, lpEnvironment, lpCurrentDirectory, si, out pi))
                    {
                        launchSuccess = true;
                        break;
                    }
                }

                if (!launchSuccess)
                {
                    throw new Win32Exception("CreateProcessWithTokenW() failed");
                }
            }
            return(ProcessUtil.WaitProcess(stdoutRead, stdoutWrite, stderrRead, stderrWrite, stdinStream, stdin, pi.hProcess));
        }
Exemplo n.º 3
0
        /// <summary>
        /// Creates a process as another user account. This method will attempt to run as another user with the
        /// highest possible permissions available. The main privilege required is the SeDebugPrivilege, without
        /// this privilege you can only run as a local or domain user if the username and password is specified.
        /// </summary>
        /// <param name="username">The username of the runas user</param>
        /// <param name="password">The password of the runas user</param>
        /// <param name="logonFlags">LogonFlags to control how to logon a user when the password is specified</param>
        /// <param name="logonType">Controls what type of logon is used, this only applies when the password is specified</param>
        /// <param name="lpApplicationName">The name of the executable or batch file to executable</param>
        /// <param name="lpCommandLine">The command line to execute, typically this includes lpApplication as the first argument</param>
        /// <param name="lpCurrentDirectory">The full path to the current directory for the process, null will have the same cwd as the calling process</param>
        /// <param name="environment">A dictionary of key/value pairs to define the new process environment</param>
        /// <param name="stdin">Bytes sent to the stdin pipe</param>
        /// <returns>Ansible.Process.Result object that contains the command output and return code</returns>
        public static Result CreateProcessAsUser(string username, string password, LogonFlags logonFlags, LogonType logonType,
                                                 string lpApplicationName, string lpCommandLine, string lpCurrentDirectory, IDictionary environment, byte[] stdin)
        {
            // While we use STARTUPINFOEX having EXTENDED_STARTUPINFO_PRESENT causes a parameter validation error
            Process.NativeHelpers.ProcessCreationFlags creationFlags = Process.NativeHelpers.ProcessCreationFlags.CREATE_UNICODE_ENVIRONMENT;
            Process.NativeHelpers.PROCESS_INFORMATION  pi            = new Process.NativeHelpers.PROCESS_INFORMATION();
            Process.NativeHelpers.STARTUPINFOEX        si            = new Process.NativeHelpers.STARTUPINFOEX();
            si.startupInfo.dwFlags = Process.NativeHelpers.StartupInfoFlags.USESTDHANDLES;

            SafeFileHandle stdoutRead, stdoutWrite, stderrRead, stderrWrite, stdinRead, stdinWrite;

            ProcessUtil.CreateStdioPipes(si, out stdoutRead, out stdoutWrite, out stderrRead, out stderrWrite,
                                         out stdinRead, out stdinWrite);
            FileStream stdinStream = new FileStream(stdinWrite, FileAccess.Write);

            // $null from PowerShell ends up as an empty string, we need to convert back as an empty string doesn't
            // make sense for these parameters
            if (lpApplicationName == "")
            {
                lpApplicationName = null;
            }

            if (lpCurrentDirectory == "")
            {
                lpCurrentDirectory = null;
            }

            using (Process.SafeMemoryBuffer lpEnvironment = ProcessUtil.CreateEnvironmentPointer(environment))
                using (SafeNativeHandle hToken = GetUserToken(username, password, logonType))
                {
                    StringBuilder commandLine = new StringBuilder(lpCommandLine);
                    if (!NativeMethods.CreateProcessWithTokenW(hToken, logonFlags, lpApplicationName, commandLine,
                                                               creationFlags, lpEnvironment, lpCurrentDirectory, si, out pi))
                    {
                        throw new Process.Win32Exception("CreateProcessWithTokenW() failed");
                    }
                }
            return(ProcessUtil.WaitProcess(stdoutRead, stdoutWrite, stderrRead, stderrWrite, stdinStream, stdin, pi.hProcess));
        }
Exemplo n.º 4
0
        /// <summary>
        /// Creates a process as another user account. This method will attempt to run as another user with the
        /// highest possible permissions available. The main privilege required is the SeDebugPrivilege, without
        /// this privilege you can only run as a local or domain user if the username and password is specified.
        /// </summary>
        /// <param name="username">The username of the runas user</param>
        /// <param name="password">The password of the runas user</param>
        /// <param name="logonFlags">LogonFlags to control how to logon a user when the password is specified</param>
        /// <param name="logonType">Controls what type of logon is used, this only applies when the password is specified</param>
        /// <param name="lpApplicationName">The name of the executable or batch file to executable</param>
        /// <param name="lpCommandLine">The command line to execute, typically this includes lpApplication as the first argument</param>
        /// <param name="lpCurrentDirectory">The full path to the current directory for the process, null will have the same cwd as the calling process</param>
        /// <param name="environment">A dictionary of key/value pairs to define the new process environment</param>
        /// <param name="stdin">Bytes sent to the stdin pipe</param>
        /// <returns>Ansible.Process.Result object that contains the command output and return code</returns>
        public static Result CreateProcessAsUser(string username, string password, LogonFlags logonFlags, LogonType logonType,
                                                 string lpApplicationName, string lpCommandLine, string lpCurrentDirectory, IDictionary environment, byte[] stdin)
        {
            // While we use STARTUPINFOEX having EXTENDED_STARTUPINFO_PRESENT causes a parameter validation error
            Process.NativeHelpers.ProcessCreationFlags creationFlags = Process.NativeHelpers.ProcessCreationFlags.CREATE_UNICODE_ENVIRONMENT;
            Process.NativeHelpers.PROCESS_INFORMATION  pi            = new Process.NativeHelpers.PROCESS_INFORMATION();
            Process.NativeHelpers.STARTUPINFOEX        si            = new Process.NativeHelpers.STARTUPINFOEX();
            si.startupInfo.dwFlags = Process.NativeHelpers.StartupInfoFlags.USESTDHANDLES;

            SafeFileHandle stdoutRead, stdoutWrite, stderrRead, stderrWrite, stdinRead, stdinWrite;

            ProcessUtil.CreateStdioPipes(si, out stdoutRead, out stdoutWrite, out stderrRead, out stderrWrite,
                                         out stdinRead, out stdinWrite);
            FileStream stdinStream = new FileStream(stdinWrite, FileAccess.Write);

            // $null from PowerShell ends up as an empty string, we need to convert back as an empty string doesn't
            // make sense for these parameters
            if (lpApplicationName == "")
            {
                lpApplicationName = null;
            }

            if (lpCurrentDirectory == "")
            {
                lpCurrentDirectory = null;
            }

            // A user may have 2 tokens, 1 limited and 1 elevated. GetUserTokens will return both token to ensure
            // we don't close one of the pairs while the process is still running. If the process tries to retrieve
            // one of the pairs and the token handle is closed then it will fail with ERROR_NO_SUCH_LOGON_SESSION.
            List <SafeNativeHandle> userTokens = GetUserTokens(username, password, logonType);

            try
            {
                using (Process.SafeMemoryBuffer lpEnvironment = ProcessUtil.CreateEnvironmentPointer(environment))
                {
                    bool          launchSuccess = false;
                    StringBuilder commandLine   = new StringBuilder(lpCommandLine);
                    foreach (SafeNativeHandle token in userTokens)
                    {
                        // GetUserTokens could return null if an elevated token could not be retrieved.
                        if (token == null)
                        {
                            continue;
                        }

                        if (NativeMethods.CreateProcessWithTokenW(token, logonFlags, lpApplicationName,
                                                                  commandLine, creationFlags, lpEnvironment, lpCurrentDirectory, si, out pi))
                        {
                            launchSuccess = true;
                            break;
                        }
                    }

                    if (!launchSuccess)
                    {
                        throw new Process.Win32Exception("CreateProcessWithTokenW() failed");
                    }
                }
                return(ProcessUtil.WaitProcess(stdoutRead, stdoutWrite, stderrRead, stderrWrite, stdinStream, stdin,
                                               pi.hProcess));
            }
            finally
            {
                userTokens.Where(t => t != null).ToList().ForEach(t => t.Dispose());
            }
        }