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(); } } }
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); }