private Native.NativeMethods.PROCESS_INFORMATION NativeCreateProcessAsUser(bool interactive, string filename, string arguments, string curDir, string envBlock, PipeStream stdinPipeName, PipeStream stdoutPipeName, PipeStream stderrPipeName)
        {
            var startupInfo = new Native.NativeMethods.STARTUPINFO();
            var processInfo = new Native.NativeMethods.PROCESS_INFORMATION();

            startupInfo = new Native.NativeMethods.STARTUPINFO();

            if (this.prison.RuleEnabled(RuleTypes.WindowStation))
            {
                startupInfo.lpDesktop = this.prison.desktopName;
            }

            NativeMethods.ProcessCreationFlags creationFlags = NativeMethods.ProcessCreationFlags.ZERO_FLAG;

            // Exclude flags
            creationFlags &=
                ~NativeMethods.ProcessCreationFlags.CREATE_PRESERVE_CODE_AUTHZ_LEVEL &
                ~NativeMethods.ProcessCreationFlags.CREATE_BREAKAWAY_FROM_JOB;

            // Include flags
            creationFlags |=
                NativeMethods.ProcessCreationFlags.CREATE_DEFAULT_ERROR_MODE |
                NativeMethods.ProcessCreationFlags.CREATE_NEW_PROCESS_GROUP |
                NativeMethods.ProcessCreationFlags.CREATE_SUSPENDED |
                NativeMethods.ProcessCreationFlags.CREATE_UNICODE_ENVIRONMENT |
                NativeMethods.ProcessCreationFlags.CREATE_NEW_CONSOLE;

            // TODO: extra steps for interactive to work:
            // http://blogs.msdn.com/b/winsdk/archive/2013/05/01/how-to-launch-a-process-interactively-from-a-windows-service.aspx
            if (interactive)
            {
                startupInfo.lpDesktop = string.Empty;
            }
            else
            {
                // creationFlags |= Native.ProcessCreationFlags.CREATE_NO_WINDOW;

                // startupInfo.dwFlags |= 0x00000100; // STARTF_USESTDHANDLES

                // Dangerous and maybe insecure to give a handle like that an untrusted processes
                // startupInfo.hStdInput = Native.GetStdHandle(Native.STD_INPUT_HANDLE);
                // startupInfo.hStdOutput = Native.GetStdHandle(Native.STD_OUTPUT_HANDLE);
                // startupInfo.hStdError = Native.GetStdHandle(Native.STD_ERROR_HANDLE);

                if (stdinPipeName != null || stdoutPipeName != null || stderrPipeName != null)
                {
                    startupInfo.dwFlags |= 0x00000100; // STARTF_USESTDHANDLES
                }

                if (stdinPipeName != null)
                {
                    startupInfo.hStdInput = GetHandleFromPipe(stdinPipeName);
                }

                if (stdoutPipeName != null)
                {
                    startupInfo.hStdOutput = GetHandleFromPipe(stdoutPipeName);
                }

                if (stderrPipeName != null)
                {
                    startupInfo.hStdError = GetHandleFromPipe(stderrPipeName);
                }
            }

            if (string.IsNullOrWhiteSpace(curDir))
            {
                curDir = this.prison.PrisonHomePath;
            }

            NativeMethods.SECURITY_ATTRIBUTES processAttributes = new NativeMethods.SECURITY_ATTRIBUTES();
            NativeMethods.SECURITY_ATTRIBUTES threadAttributes = new NativeMethods.SECURITY_ATTRIBUTES();
            processAttributes.nLength = Marshal.SizeOf(processAttributes);
            threadAttributes.nLength = Marshal.SizeOf(threadAttributes);

            if (!NativeMethods.CreateProcessAsUser(
                hToken: this.prison.User.LogonToken.DangerousGetHandle(),
                lpApplicationName: filename,
                lpCommandLine: arguments,
                lpProcessAttributes: ref processAttributes,
                lpThreadAttributes: ref threadAttributes,
                bInheritHandles: true,
                dwCreationFlags: creationFlags,
                lpEnvironment: envBlock,
                lpCurrentDirectory: curDir,
                lpStartupInfo: ref startupInfo,
                lpProcessInformation: out processInfo))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            return processInfo;
        }
Example #2
0
        private Native.NativeMethods.PROCESS_INFORMATION NativeCreateProcessAsUser(bool interactive, string filename, string arguments, string curDir, string envBlock, PipeStream stdinPipeName, PipeStream stdoutPipeName, PipeStream stderrPipeName)
        {
            var startupInfo = new Native.NativeMethods.STARTUPINFO();
            var processInfo = new Native.NativeMethods.PROCESS_INFORMATION();

            startupInfo = new Native.NativeMethods.STARTUPINFO();

            if (this.prison.RuleEnabled(RuleTypes.WindowStation))
            {
                startupInfo.lpDesktop = this.prison.desktopName;
            }

            NativeMethods.ProcessCreationFlags creationFlags = NativeMethods.ProcessCreationFlags.ZERO_FLAG;

            // Exclude flags
            creationFlags &=
                ~NativeMethods.ProcessCreationFlags.CREATE_PRESERVE_CODE_AUTHZ_LEVEL &
                ~NativeMethods.ProcessCreationFlags.CREATE_BREAKAWAY_FROM_JOB;

            // Include flags
            creationFlags |=
                NativeMethods.ProcessCreationFlags.CREATE_DEFAULT_ERROR_MODE |
                NativeMethods.ProcessCreationFlags.CREATE_NEW_PROCESS_GROUP |
                NativeMethods.ProcessCreationFlags.CREATE_SUSPENDED |
                NativeMethods.ProcessCreationFlags.CREATE_UNICODE_ENVIRONMENT |
                NativeMethods.ProcessCreationFlags.CREATE_NEW_CONSOLE;

            // TODO: extra steps for interactive to work:
            // http://blogs.msdn.com/b/winsdk/archive/2013/05/01/how-to-launch-a-process-interactively-from-a-windows-service.aspx
            if (interactive)
            {
                startupInfo.lpDesktop = string.Empty;
            }
            else
            {
                // creationFlags |= Native.ProcessCreationFlags.CREATE_NO_WINDOW;

                // startupInfo.dwFlags |= 0x00000100; // STARTF_USESTDHANDLES

                // Dangerous and maybe insecure to give a handle like that an untrusted processes
                // startupInfo.hStdInput = Native.GetStdHandle(Native.STD_INPUT_HANDLE);
                // startupInfo.hStdOutput = Native.GetStdHandle(Native.STD_OUTPUT_HANDLE);
                // startupInfo.hStdError = Native.GetStdHandle(Native.STD_ERROR_HANDLE);

                if (stdinPipeName != null || stdoutPipeName != null || stderrPipeName != null)
                {
                    startupInfo.dwFlags |= 0x00000100; // STARTF_USESTDHANDLES
                }

                if (stdinPipeName != null)
                {
                    startupInfo.hStdInput = GetHandleFromPipe(stdinPipeName);
                }

                if (stdoutPipeName != null)
                {
                    startupInfo.hStdOutput = GetHandleFromPipe(stdoutPipeName);
                }

                if (stderrPipeName != null)
                {
                    startupInfo.hStdError = GetHandleFromPipe(stderrPipeName);
                }
            }

            if (string.IsNullOrWhiteSpace(curDir))
            {
                curDir = this.prison.PrisonHomePath;
            }

            NativeMethods.SECURITY_ATTRIBUTES processAttributes = new NativeMethods.SECURITY_ATTRIBUTES();
            NativeMethods.SECURITY_ATTRIBUTES threadAttributes  = new NativeMethods.SECURITY_ATTRIBUTES();
            processAttributes.nLength = Marshal.SizeOf(processAttributes);
            threadAttributes.nLength  = Marshal.SizeOf(threadAttributes);

            if (!NativeMethods.CreateProcessAsUser(
                    hToken: this.prison.User.LogonToken.DangerousGetHandle(),
                    lpApplicationName: filename,
                    lpCommandLine: arguments,
                    lpProcessAttributes: ref processAttributes,
                    lpThreadAttributes: ref threadAttributes,
                    bInheritHandles: true,
                    dwCreationFlags: creationFlags,
                    lpEnvironment: envBlock,
                    lpCurrentDirectory: curDir,
                    lpStartupInfo: ref startupInfo,
                    lpProcessInformation: out processInfo))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            return(processInfo);
        }