public Task <int> Execute() { Native.ConsoleApi.FreeConsole(); if (!Native.ConsoleApi.AttachConsole(-1)) { Native.ConsoleApi.AllocConsole(); Logger.Instance.Log($"Failed to attach console.\r\n{new Win32Exception().ToString()}", LogLevel.Error); } var app = CommandToRun.First(); var args = string.Join(" ", CommandToRun.Skip(1).ToArray()); if (InputArguments.IntegrityLevel.HasValue && (int)InputArguments.IntegrityLevel != ProcessHelper.GetCurrentIntegrityLevel() && Environment.GetEnvironmentVariable("gsudoAttachRun") != "1") { Environment.SetEnvironmentVariable("gsudoAttachRun", "1"); // prevents infinite loop on machines with UAC disabled. var process = ProcessFactory.StartAttachedWithIntegrity( InputArguments.GetIntegrityLevel(), app, args, Directory.GetCurrentDirectory(), false, true); process.GetProcessWaitHandle().WaitOne(); if (ProcessApi.GetExitCodeProcess(process, out var exitCode)) { return(Task.FromResult(exitCode)); } } else { Helpers.ProcessFactory.StartAttached(app, args).WaitForExit(); } return(Task.FromResult(0)); }
private static int RunWithoutService(string exeName, string args, ElevationRequest elevationRequest) { Logger.Instance.Log("Already running as the specified user/permission-level. Running in-process...", LogLevel.Debug); var sameIntegrity = (int)InputArguments.GetIntegrityLevel() == ProcessHelper.GetCurrentIntegrityLevel(); // No need to escalate. Run in-process if (!string.IsNullOrEmpty(elevationRequest.Prompt)) { Environment.SetEnvironmentVariable("PROMPT", Environment.ExpandEnvironmentVariables(elevationRequest.Prompt)); } if (sameIntegrity) { if (elevationRequest.NewWindow) { using (var process = ProcessFactory.StartDetached(exeName, args, Environment.CurrentDirectory, false)) { if (elevationRequest.Wait) { process.WaitForExit(); var exitCode = process.ExitCode; Logger.Instance.Log($"Process exited with code {exitCode}", exitCode == 0 ? LogLevel.Debug : LogLevel.Info); return(exitCode); } return(0); } } else { using (Process process = ProcessFactory.StartAttached(exeName, args)) { process.WaitForExit(); var exitCode = process.ExitCode; Logger.Instance.Log($"Process exited with code {exitCode}", exitCode == 0 ? LogLevel.Debug : LogLevel.Info); return(exitCode); } } } else // lower integrity { var p = ProcessFactory.StartAttachedWithIntegrity(InputArguments.GetIntegrityLevel(), exeName, args, elevationRequest.StartFolder, InputArguments.NewWindow, !InputArguments.NewWindow); if (p == null || p.IsInvalid) { return(Constants.GSUDO_ERROR_EXITCODE); } if (elevationRequest.Wait) { ProcessHelper.GetProcessWaitHandle(p.DangerousGetHandle()).WaitOne(); ProcessApi.GetExitCodeProcess(p, out var exitCode); Logger.Instance.Log($"Process exited with code {exitCode}", exitCode == 0 ? LogLevel.Debug : LogLevel.Info); return(exitCode); } return(0); } }
private static void SetRequestPrompt(ElevationRequest elevationRequest) { if ((int)InputArguments.GetIntegrityLevel() < (int)IntegrityLevel.High) elevationRequest.Prompt = Environment.GetEnvironmentVariable("PROMPT", EnvironmentVariableTarget.User) ?? Environment.GetEnvironmentVariable("PROMPT", EnvironmentVariableTarget.Machine) ?? "$P$G"; else if (elevationRequest.Mode != ElevationRequest.ConsoleMode.Piped || InputArguments.NewWindow) elevationRequest.Prompt = Settings.Prompt; else elevationRequest.Prompt = Settings.PipedPrompt; }
private static bool IsRunningAsDesiredUser() { if (InputArguments.RunAsSystem && !WindowsIdentity.GetCurrent().IsSystem) return false; if ((int)InputArguments.GetIntegrityLevel() != ProcessHelper.GetCurrentIntegrityLevel()) return false; return true; }
public Task <int> Execute() { var elevationRequest = new ElevationRequest() { IntegrityLevel = InputArguments.GetIntegrityLevel(), TargetProcessId = ProcessId, }; TokenSwitcher.ReplaceProcessToken(elevationRequest); return(Task.FromResult(0)); }
private static bool IsElevationRequired() { if (InputArguments.RunAsSystem && !WindowsIdentity.GetCurrent().IsSystem) return true; var integrityLevel = InputArguments.GetIntegrityLevel(); if (integrityLevel == IntegrityLevel.MediumRestricted) return true; return (int)integrityLevel > ProcessHelper.GetCurrentIntegrityLevel(); }
public static string GetPipeName(string connectingUser, int connectingPid) { if (connectingPid < 0) { connectingPid = 0; } string integrity = InputArguments.GetIntegrityLevel().ToString(); var data = $"{connectingUser}_{connectingPid}"; #if !DEBUG data = GetHash(data); #endif return($"{GetPipePrefix()}_{data}"); }
// Enforce SecurityEnforceUacIsolation private void AdjustUacIsolationRequest(ElevationRequest elevationRequest, bool isShellElevation) { if ((int)(InputArguments.GetIntegrityLevel()) >= ProcessHelper.GetCurrentIntegrityLevel()) { if (!elevationRequest.NewWindow) { if (isShellElevation) { // force auto shell elevation in new window elevationRequest.NewWindow = true; // do not wait by default on this scenario, only if user has requested it. elevationRequest.Wait = InputArguments.Wait; Logger.Instance.Log("Elevating shell in a new console window because of SecurityEnforceUacIsolation", LogLevel.Info); } else { // force raw mode (that disables user input with SecurityEnforceUacIsolation) elevationRequest.Mode = ElevationRequest.ConsoleMode.Piped; Logger.Instance.Log("User Input disabled because of SecurityEnforceUacIsolation. Press Ctrl-C three times to abort. Or use -n argument to elevate in new window.", LogLevel.Warning); } } } }
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); }