private void Run(ExecConfig e, string section, int seq, bool isAsync = true) { ProgramWrapper wrapper; if (Globals.Config.User == null || e.ExecLaunchPrivilegeLevel == ExecLaunchPrivilegeLevel.IgnoreUser || e.ExecLaunchPrivilegeLevel == ExecLaunchPrivilegeLevel.Full) { wrapper = new ManagedProgramWrapper(e.ProgramPath, e.Arguments); wrapper.Start(); } else { // Get the privilege for impersonation var currentProcess = new CProcess(); if (!currentProcess.SetPrivilege("SeTcbPrivilege", true)) { throw new InvalidOperationException("Required privilege SeTcbPrivilege failed"); } if (!currentProcess.SetPrivilege("SeDelegateSessionUserImpersonatePrivilege", true)) { throw new InvalidOperationException("Required privilege SeDelegateSessionUserImpersonatePrivilege failed"); } // Get the identity we needed var identity = new WindowsIdentity(Globals.Config.User); if (identity.ImpersonationLevel != TokenImpersonationLevel.Impersonation) { throw new InvalidOperationException("Insufficient permission"); } // Run the helper process as that identity using (identity.Impersonate()) { LogMuxer.Instance.Debug($"After impersonation, User={WindowsIdentity.GetCurrent().Name}, ImpersonationLevel={identity.ImpersonationLevel}");; wrapper = new NativeProgramWrapper(section, seq, identity.Token); wrapper.Start(); } } if (isAsync) { _programPool.Add(wrapper); wrapper.ProgramExited += SubprocessQuit; } else { wrapper.WaitForExit(); } }
// ReSharper disable once UnusedMember.Global public void OnExecute() { AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException; AppDomain.CurrentDomain.ProcessExit += OnProcessExit; var currentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (currentDirectory != null) { Directory.SetCurrentDirectory(currentDirectory); } // If this is a helper process if (IsImpersonatedProcess) { LoadConfig(); LogMuxer.Instance.Debug("Executing impersonation helper routine"); ExecConfig execConfig; switch (ExecConfigLaunchType) { case "ExecStart": execConfig = Globals.Config.ExecStart[ExecConfigIndex]; break; default: throw new ArgumentException(); } Wrapper = new ManagedProgramWrapper(execConfig.ProgramPath, execConfig.Arguments); var hasExited = false; Wrapper.ProgramExited += (sender, eventArgs) => { hasExited = true; }; Wrapper.Start(); while (!hasExited) { Thread.Sleep(1000); } return; } if (Environment.UserInteractive) { var configOk = true; try { LoadConfig(); } catch { configOk = false; } LogMuxer.Instance.Debug($"IsElevated: {UACHelper.IsRunAsAdmin()}"); LogMuxer.Instance.Debug($"Cmdline: {Environment.CommandLine}"); if (!UACHelper.IsRunAsAdmin()) { LogMuxer.Instance.Warning("Warning: you may not have sufficient privilege to install services."); } //if (!DoNotElevate && !UACHelper.IsRunAsAdmin()) //{ // TryElevate(); //} if (Install && Uninstall) { LogMuxer.Instance.Fatal("Self-contradictory arguments?"); Environment.Exit(1); } else if (Install) { if (!configOk) { LogMuxer.Instance.Fatal("Cannot read config"); Environment.Exit(1); } InstallService(); } else if (Uninstall) { if (!configOk) { LogMuxer.Instance.Fatal("Cannot read config"); Environment.Exit(1); } UninstallService(); } else if (RunOnly) { if (!configOk) { LogMuxer.Instance.Fatal("Cannot read config"); Environment.Exit(1); } var s = new Supervisor(); s.Start(); s.WaitForExit(); } else { LogMuxer.Instance.Info("Searching for unit files in program directory..."); // Let's install every service in this folder try { var txtFiles = Directory.EnumerateFiles(Globals.ExecutableDirectory, "*.service", SearchOption.TopDirectoryOnly); foreach (string currentFile in txtFiles) { var proceed = Prompt.GetYesNo($"Do you want to register {Path.GetFileName(currentFile)}?", defaultAnswer: true); if (proceed) { RegisterService(currentFile); } } } catch (Exception e) { LogMuxer.Instance.Error(e.Message); } } } else { LoadConfig(); ServiceBase.Run(new Service()); } }