Example #1
0
        public async Task <int> Execute()
        {
            //Logger.Instance.Log("Params: " + Newtonsoft.Json.JsonConvert.SerializeObject(this), LogLevel.Debug);

            var  currentProcess = System.Diagnostics.Process.GetCurrentProcess();
            bool emptyArgs      = string.IsNullOrEmpty(CommandToRun.FirstOrDefault());

            CommandToRun = ArgumentsHelper.AugmentCommand(CommandToRun.ToArray());
            bool isWindowsApp = ProcessFactory.IsWindowsApp(CommandToRun.FirstOrDefault());
            var  consoleMode  = GetConsoleMode(isWindowsApp);

            if (!RunningAsDesiredUser())
            {
                CommandToRun = AddCopyEnvironment(CommandToRun);
            }
            var exeName = CommandToRun.FirstOrDefault();

            var elevationRequest = new ElevationRequest()
            {
                FileName         = exeName,
                Arguments        = GetArguments(),
                StartFolder      = Environment.CurrentDirectory,
                NewWindow        = GlobalSettings.NewWindow,
                Wait             = (!isWindowsApp && !GlobalSettings.NewWindow) || GlobalSettings.Wait,
                Mode             = consoleMode,
                ConsoleProcessId = currentProcess.Id,
                Prompt           = consoleMode != ElevationRequest.ConsoleMode.Raw || GlobalSettings.NewWindow ? GlobalSettings.Prompt : GlobalSettings.RawPrompt
            };

            Logger.Instance.Log($"Command to run: {elevationRequest.FileName} {elevationRequest.Arguments}", LogLevel.Debug);

            if (elevationRequest.Mode == ElevationRequest.ConsoleMode.VT)
            {
                elevationRequest.ConsoleWidth  = Console.WindowWidth;
                elevationRequest.ConsoleHeight = Console.WindowHeight;

                if (TerminalHelper.IsConEmu())
                {
                    elevationRequest.ConsoleWidth--; // weird ConEmu/Cmder fix
                }
            }

            if (RunningAsDesiredUser()) // already elevated or running as correct user. No service needed.
            {
                if (emptyArgs && !GlobalSettings.NewWindow)
                {
                    Logger.Instance.Log("Already elevated (and no parameters specified). Exiting...", LogLevel.Error);
                    return(Constants.GSUDO_ERROR_EXITCODE);
                }

                Logger.Instance.Log("Already elevated. Running in-process", LogLevel.Debug);

                // No need to escalate. Run in-process

                if (elevationRequest.Mode == ElevationRequest.ConsoleMode.Raw && !elevationRequest.NewWindow)
                {
                    if (!string.IsNullOrEmpty(GlobalSettings.RawPrompt.Value))
                    {
                        Environment.SetEnvironmentVariable("PROMPT", Environment.ExpandEnvironmentVariables(GlobalSettings.RawPrompt.Value));
                    }
                }
                else
                {
                    if (!string.IsNullOrEmpty(GlobalSettings.Prompt.Value))
                    {
                        Environment.SetEnvironmentVariable("PROMPT", Environment.ExpandEnvironmentVariables(GlobalSettings.Prompt.Value));
                    }
                }

                if (GlobalSettings.NewWindow)
                {
                    using (Process process = ProcessFactory.StartDetached(exeName, GetArguments(), Environment.CurrentDirectory, false))
                    {
                        if (elevationRequest.Wait)
                        {
                            process.WaitForExit();
                            var exitCode = process.ExitCode;
                            Logger.Instance.Log($"Elevated process exited with code {exitCode}", exitCode == 0 ? LogLevel.Debug : LogLevel.Info);
                            return(exitCode);
                        }
                        return(0);
                    }
                }
                else
                {
                    using (Process process = ProcessFactory.StartInProcessAtached(exeName, GetArguments()))
                    {
                        process.WaitForExit();
                        var exitCode = process.ExitCode;
                        Logger.Instance.Log($"Elevated process exited with code {exitCode}", exitCode == 0 ? LogLevel.Debug : LogLevel.Info);
                        return(exitCode);
                    }
                }
            }
            else
            {
                Logger.Instance.Log($"Using Console mode {elevationRequest.Mode}", LogLevel.Debug);
                var callingPid = GetCallingPid(currentProcess);
                var callingSid = WindowsIdentity.GetCurrent().User.Value;
                Logger.Instance.Log($"Caller PID: {callingPid}", LogLevel.Debug);
                Logger.Instance.Log($"Caller SID: {callingSid}", LogLevel.Debug);

                var cmd = CommandToRun.FirstOrDefault();

                var            rpcClient  = GetClient(elevationRequest);
                Rpc.Connection connection = null;

                try
                {
                    try
                    {
                        connection = await rpcClient.Connect(elevationRequest, null, 300).ConfigureAwait(false);
                    }
                    catch (System.IO.IOException) { }
                    catch (TimeoutException) { }
                    catch (Exception ex)
                    {
                        Logger.Instance.Log(ex.ToString(), LogLevel.Warning);
                    }

                    if (connection == null) // service is not running or listening.
                    {
                        // Start elevated service instance
                        if (!StartElevatedService(currentProcess, callingPid, callingSid))
                        {
                            return(Constants.GSUDO_ERROR_EXITCODE);
                        }

                        connection = await rpcClient.Connect(elevationRequest, callingPid, 5000).ConfigureAwait(false);
                    }

                    if (connection == null) // service is not running or listening.
                    {
                        Logger.Instance.Log("Unable to connect to the elevated service.", LogLevel.Error);
                        return(Constants.GSUDO_ERROR_EXITCODE);
                    }

                    await WriteElevationRequest(elevationRequest, connection).ConfigureAwait(false);

                    ConnectionKeepAliveThread.Start(connection);

                    var renderer = GetRenderer(connection, elevationRequest);
                    var exitCode = await renderer.Start().ConfigureAwait(false);

                    if (!(elevationRequest.NewWindow && !elevationRequest.Wait))
                    {
                        Logger.Instance.Log($"Elevated process exited with code {exitCode}", exitCode == 0 ? LogLevel.Debug : LogLevel.Info);
                    }

                    return(exitCode);
                }
                finally
                {
                    connection?.Dispose();
                }
            }
        }
Example #2
0
        public async Task <int> Execute()
        {
            int? exitCode;
            bool isRunningAsDesiredUser = IsRunningAsDesiredUser();
            bool isElevationRequired    = IsElevationRequired();

            bool isShellElevation = string.IsNullOrEmpty(CommandToRun.FirstOrDefault()); // are we auto elevating the current shell?

            if (isElevationRequired & ProcessHelper.GetCurrentIntegrityLevel() < (int)IntegrityLevel.Medium)
            {
                throw new ApplicationException("Sorry, gsudo doesn't allow to elevate from low integrity level."); // This message is not a security feature, but a nicer error message. It would have failed anyway since the named pipe's ACL restricts it.
            }
            CommandToRun = ArgumentsHelper.AugmentCommand(CommandToRun.ToArray());
            bool isWindowsApp = ProcessFactory.IsWindowsApp(CommandToRun.FirstOrDefault());

            var elevationMode = GetElevationMode(isWindowsApp);

            if (!isRunningAsDesiredUser)
            {
                CommandToRun = AddCopyEnvironment(CommandToRun, elevationMode);
            }

            var exeName = CommandToRun.FirstOrDefault();

            var elevationRequest = new ElevationRequest()
            {
                FileName         = exeName,
                Arguments        = GetArguments(),
                StartFolder      = Environment.CurrentDirectory,
                NewWindow        = InputArguments.NewWindow,
                Wait             = (!isWindowsApp && !InputArguments.NewWindow) || InputArguments.Wait,
                Mode             = elevationMode,
                ConsoleProcessId = Process.GetCurrentProcess().Id,
                IntegrityLevel   = InputArguments.GetIntegrityLevel(),
            };

            if (isElevationRequired && Settings.SecurityEnforceUacIsolation)
            {
                AdjustUacIsolationRequest(elevationRequest, isShellElevation);
            }

            SetRequestPrompt(elevationRequest);

            Logger.Instance.Log($"Command to run: {elevationRequest.FileName} {elevationRequest.Arguments}", LogLevel.Debug);

            if (elevationRequest.Mode == ElevationRequest.ConsoleMode.VT)
            {
                elevationRequest.ConsoleWidth  = Console.WindowWidth;
                elevationRequest.ConsoleHeight = Console.WindowHeight;

                if (TerminalHelper.IsConEmu())
                {
                    elevationRequest.ConsoleWidth--; // weird ConEmu/Cmder fix
                }
            }

            if (isRunningAsDesiredUser && isShellElevation && !InputArguments.NewWindow)
            {
                Logger.Instance.Log("Already running as the specified user/permission-level (and no command specified). Exiting...", LogLevel.Error);
                return(Constants.GSUDO_ERROR_EXITCODE);
            }

            if (isRunningAsDesiredUser || !isElevationRequired) // already elevated or running as correct user. No service needed.
            {
                return(RunWithoutService(exeName, GetArguments(), elevationRequest));
            }

            if (Settings.CacheMode.Value.In(CacheMode.Disabled) ||
                Math.Abs(Settings.CacheDuration.Value.TotalSeconds) < 1 ||
                (InputArguments.KillCache && !IsServiceAvailable()))
            {
                exitCode = await RunUsingSingleUseElevation(elevationRequest).ConfigureAwait(false);
            }
            else if (Settings.CacheMode.Value.In(CacheMode.Auto) ||
                     elevationRequest.Mode != ElevationRequest.ConsoleMode.TokenSwitch)
            {
                exitCode = await RunUsingElevatedService(elevationRequest).ConfigureAwait(false);
            }
            else if (Settings.CacheMode.Value == CacheMode.Explicit && IsServiceAvailable())
            {
                exitCode = await RunUsingElevatedService(elevationRequest).ConfigureAwait(false);
            }
            else
            {
                exitCode = await RunUsingSingleUseElevation(elevationRequest).ConfigureAwait(false);
            }

            if (exitCode.HasValue && exitCode.Value != Constants.GSUDO_ERROR_EXITCODE)
            {
                Logger.Instance.Log($"Process exited with code {exitCode}", exitCode == 0 ? LogLevel.Debug : LogLevel.Info);
            }

            return(exitCode ?? 0);
        }