private void OnAppSessionEnding(object sender, SessionEndingEventArgs e) { m_logger.Info("Session ending."); // THIS MUST BE DONE HERE ALWAYS, otherwise, we get BSOD. CriticalKernelProcessUtility.SetMyProcessAsNonKernelCritical(); Environment.Exit((int)ExitCodes.ShutdownWithSafeguards); }
private void OnAppSessionEnding(object sender, SessionEndingCancelEventArgs e) { m_logger.Info("Session ending."); // THIS MUST BE DONE HERE ALWAYS, otherwise, we get BSOD. CriticalKernelProcessUtility.SetMyProcessAsNonKernelCritical(); Application.Current.Shutdown(ExitCodes.ShutdownWithSafeguards); // Does this cause a hand up?? m_ipcClient.Dispose(); }
// XXX FIXME private void DoCleanShutdown() { lock (m_cleanShutdownLock) { if (!m_cleanShutdownComplete) { m_ipcClient.Dispose(); try { // Pull our icon from the task tray. if (m_trayIcon != null) { m_trayIcon.Visible = false; } } catch (Exception e) { LoggerUtil.RecursivelyLogException(m_logger, e); } try { // Pull our critical status. CriticalKernelProcessUtility.SetMyProcessAsNonKernelCritical(); } catch (Exception e) { LoggerUtil.RecursivelyLogException(m_logger, e); } // Flag that clean shutdown was completed already. m_cleanShutdownComplete = true; } } }
public static void Main(string[] args) { var sentry = SentrySdk.Init(o => { o.Dsn = new Dsn(CloudVeil.CompileSecrets.SentryDsn); o.BeforeBreadcrumb = (breadcrumb) => { if (breadcrumb.Message.Contains("Request")) { return(null); } else { return(breadcrumb); } }; }); LoggerUtil.LoggerName = "CitadelGUI"; bool startMinimized = false; foreach (string arg in args) { if (arg.IndexOf("StartMinimized") != -1) { startMinimized = true; break; } } try { if (Process.GetCurrentProcess().SessionId <= 0) { try { LoggerUtil.GetAppWideLogger().Error("GUI client started in session 0 isolation. Exiting. This should not happen."); Environment.Exit((int)ExitCodes.ShutdownWithoutSafeguards); return; } catch (Exception e) { // XXX TODO - We can't really log here unless we do a direct to-file write. Environment.Exit((int)ExitCodes.ShutdownWithoutSafeguards); return; } } Citadel.Core.Windows.Platform.Init(); PlatformTypes.Register <IGuiServices>((arr) => new WindowsGuiServices()); PlatformTypes.Register <ITrayIconController>((arr) => new WindowsTrayIconController()); } catch { // Lets assume that if we can't even read our session ID, that we're in session 0. Environment.Exit((int)ExitCodes.ShutdownWithoutSafeguards); return; } var guiChecks = PlatformTypes.New <IGUIChecks>(); try { RunGuiChecks(startMinimized); } catch (Exception e) { // The only way we got here is if the server isn't running, in which case we can do // nothing because its beyond our domain. LoggerUtil.RecursivelyLogException(LoggerUtil.GetAppWideLogger(), e); return; } try { MainLogger = LoggerUtil.GetAppWideLogger(); } catch { } try { var app = new CitadelApp(); app.InitializeComponent(); app.Run(); // Always release mutex. guiChecks.UnpublishRunningApp(); } catch (Exception e) { try { SentrySdk.CaptureException(e); MainLogger = LoggerUtil.GetAppWideLogger(); LoggerUtil.RecursivelyLogException(MainLogger, e); } catch (Exception be) { // XXX TODO - We can't really log here unless we do a direct to-file write. } } sentry.Dispose(); // No matter what, always ensure that critical flags are removed from our process before exiting. CriticalKernelProcessUtility.SetMyProcessAsNonKernelCritical(); }
/// <summary> /// Called whenever the app is shut down with an authorized key, or when the system is /// shutting down, or when the user is logging off. /// </summary> /// <param name="installSafeguards"> /// Indicates whether or not safeguards should be put in place when we exit the application /// here. Safeguards means that we're going to do all that we can to ensure that our function /// is not bypassed, and that we're going to be forced to run again. /// </param> private void DoCleanShutdown(bool installSafeguards) { // No matter what, ensure that all GUI instances for all users are // immediately shut down, because we, the service, are shutting down. lock (m_cleanShutdownLock) { if (!m_cleanShutdownComplete) { try { // Pull our critical status. CriticalKernelProcessUtility.SetMyProcessAsNonKernelCritical(); } catch (Exception e) { LoggerUtil.RecursivelyLogException(m_logger, e); } if (installSafeguards) { try { // Ensure we're automatically running at startup. var scProcNfo = new ProcessStartInfo("sc.exe"); scProcNfo.UseShellExecute = false; scProcNfo.WindowStyle = ProcessWindowStyle.Hidden; scProcNfo.Arguments = "config \"FilterServiceProvider\" start= auto"; Process.Start(scProcNfo).WaitForExit(); } catch (Exception e) { LoggerUtil.RecursivelyLogException(m_logger, e); } try { var cfg = m_provider.PolicyConfiguration.Configuration; if (cfg != null && cfg.BlockInternet) { // While we're here, let's disable the internet so that the user // can't browse the web without us. Only do this of course if configured. try { WFPUtility.DisableInternet(); } catch { } } } catch (Exception e) { LoggerUtil.RecursivelyLogException(m_logger, e); } } else { // Means that our user got a granted deactivation request, or installed but // never activated. m_logger.Info("Shutting down without safeguards."); } // Flag that clean shutdown was completed already. m_cleanShutdownComplete = true; } } }
public static void Main(string[] args) { try { if (Process.GetCurrentProcess().SessionId <= 0) { try { LoggerUtil.GetAppWideLogger().Error("GUI client started in session 0 isolation. Exiting. This should not happen."); Environment.Exit((int)ExitCodes.ShutdownWithoutSafeguards); return; } catch (Exception e) { // XXX TODO - We can't really log here unless we do a direct to-file write. Environment.Exit((int)ExitCodes.ShutdownWithoutSafeguards); return; } } } catch { // Lets assume that if we can't even read our session ID, that we're in session 0. Environment.Exit((int)ExitCodes.ShutdownWithoutSafeguards); return; } try { string appVerStr = System.Diagnostics.Process.GetCurrentProcess().ProcessName; System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly(); appVerStr += "." + System.Reflection.AssemblyName.GetAssemblyName(assembly.Location).Version.ToString(); bool createdNew; try { InstanceMutex = new Mutex(true, string.Format(@"Local\{0}", GuidUtility.Create(GuidUtility.DnsNamespace, appVerStr).ToString("B")), out createdNew); } catch { // We can get access denied if SYSTEM is running this. createdNew = false; } if (!createdNew) { try { var thisProcess = Process.GetCurrentProcess(); var processes = Process.GetProcessesByName(thisProcess.ProcessName).Where(p => p.Id != thisProcess.Id); foreach (Process runningProcess in processes) { foreach (var handle in WindowHelpers.EnumerateProcessWindowHandles(runningProcess.Id)) { // Send window show. WindowHelpers.SendMessage(handle, (uint)WindowMessages.SHOWWINDOW, 9, 0); } } } catch (Exception e) { LoggerUtil.RecursivelyLogException(LoggerUtil.GetAppWideLogger(), e); } // In case we have some out of sync state where the app is running at a higher // privilege level than us, the app won't get our messages. So, let's attempt an // IPC named pipe to deliver the message as well. try { using (var ipcClient = new IPCClient()) { ipcClient.RequestPrimaryClientShowUI(); // Wait plenty of time before dispose to allow delivery of the msg. Task.Delay(500).Wait(); } } catch (Exception e) { // The only way we got here is if the server isn't running, in which case we // can do nothing because its beyond our domain. LoggerUtil.RecursivelyLogException(LoggerUtil.GetAppWideLogger(), e); } // Close this instance. Environment.Exit(-1); return; } } catch (Exception e) { // The only way we got here is if the server isn't running, in which case we can do // nothing because its beyond our domain. LoggerUtil.RecursivelyLogException(LoggerUtil.GetAppWideLogger(), e); return; } try { MainLogger = LoggerUtil.GetAppWideLogger(); } catch { } try { var app = new CitadelApp(); app.InitializeComponent(); app.Run(); // Always release mutex. InstanceMutex.ReleaseMutex(); } catch (Exception e) { try { MainLogger = LoggerUtil.GetAppWideLogger(); LoggerUtil.RecursivelyLogException(MainLogger, e); } catch (Exception be) { // XXX TODO - We can't really log here unless we do a direct to-file write. } } // No matter what, always ensure that critical flags are removed from our process before exiting. CriticalKernelProcessUtility.SetMyProcessAsNonKernelCritical(); }
private void CitadelOnStartup(object sender, StartupEventArgs e) { // Here we need to check 2 things. First, we need to check to make sure that our filter // service is running. Second, and if the first condition proves to be false, we need to // check if we are running as an admin. If we are not admin, we need to schedule a // restart of the app to force us to run as admin. If we are admin, then we will create // an instance of the service starter class that will take care of forcing our service // into existence. bool needRestartAsAdmin = false; bool mainServiceViable = true; try { var sc = new ServiceController("FilterServiceProvider"); switch (sc.Status) { case ServiceControllerStatus.Stopped: case ServiceControllerStatus.StopPending: { mainServiceViable = false; } break; } } catch (Exception ae) { mainServiceViable = false; } if (!mainServiceViable) { var id = WindowsIdentity.GetCurrent(); var principal = new WindowsPrincipal(id); if (principal.IsInRole(WindowsBuiltInRole.Administrator)) { needRestartAsAdmin = false; } else { needRestartAsAdmin = id.Owner == id.User; } if (needRestartAsAdmin) { m_logger.Info("Restarting as admin."); try { // Restart program and run as admin ProcessStartInfo updaterStartupInfo = new ProcessStartInfo(); updaterStartupInfo.FileName = "cmd.exe"; updaterStartupInfo.Arguments = string.Format("/C TIMEOUT {0} && \"{1}\"", 3, Process.GetCurrentProcess().MainModule.FileName); updaterStartupInfo.WindowStyle = ProcessWindowStyle.Hidden; updaterStartupInfo.Verb = "runas"; updaterStartupInfo.CreateNoWindow = true; Process.Start(updaterStartupInfo); } catch (Exception se) { LoggerUtil.RecursivelyLogException(m_logger, se); } Environment.Exit(-1); return; } else { // Just creating an instance of this will do the job of forcing our service to // start. Letting it fly off into garbage collection land should have no effect. // The service is self-sustaining after this point. var provider = new ServiceRunner(); } } // Hook the shutdown/logoff event. Current.SessionEnding += OnAppSessionEnding; // Hook app exiting function. This must be done on this main app thread. this.Exit += OnApplicationExiting; // Do stuff that must be done on the UI thread first. Here we HAVE to set our initial // view state BEFORE we initialize IPC. If we change it after, then we're going to get // desynchronized in our state. try { InitViews(); OnViewChangeRequest(typeof(ProgressWait)); } catch (Exception ve) { LoggerUtil.RecursivelyLogException(m_logger, ve); } try { // XXX FIXME m_ipcClient = IPCClient.InitDefault(); m_ipcClient.AuthenticationResultReceived = (authenticationFailureResult) => { switch (authenticationFailureResult.Action) { case AuthenticationAction.Denied: case AuthenticationAction.Required: case AuthenticationAction.InvalidInput: { // User needs to log in. BringAppToFocus(); OnViewChangeRequest(typeof(LoginView)); } break; case AuthenticationAction.Authenticated: case AuthenticationAction.ErrorNoInternet: case AuthenticationAction.ErrorUnknown: { OnViewChangeRequest(typeof(DashboardView)); } break; } }; m_ipcClient.ServerAppUpdateRequestReceived = async(args) => { string updateSettingsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "CloudVeil", "update.settings"); if (File.Exists(updateSettingsPath)) { using (StreamReader reader = File.OpenText(updateSettingsPath)) { string command = reader.ReadLine(); string[] commandParts = command.Split(new char[] { ':' }, 2); if (commandParts[0] == "RemindLater") { DateTime remindLater; if (DateTime.TryParse(commandParts[1], out remindLater)) { if (DateTime.Now < remindLater) { return; } } } else if (commandParts[0] == "SkipVersion") { if (commandParts[1] == args.NewVersionString) { return; } } } } BringAppToFocus(); var updateAvailableString = string.Format("An update to version {0} is available. You are currently running version {1}. Would you like to update now?", args.NewVersionString, args.CurrentVersionString); if (args.IsRestartRequired) { updateAvailableString += "\r\n\r\nThis update WILL require a reboot. Save all your work before continuing."; } await Current.Dispatcher.BeginInvoke( System.Windows.Threading.DispatcherPriority.Normal, (Action)async delegate() { if (m_mainWindow != null) { var result = await m_mainWindow.AskUserUpdateQuestion("Update Available", updateAvailableString); switch (result) { case UpdateDialogResult.UpdateNow: m_ipcClient.NotifyAcceptUpdateRequest(); m_mainWindow.ShowUserMessage("Updating", "The update is being downloaded. The application will automatically update and restart when the download is complete."); break; case UpdateDialogResult.RemindLater: using (StreamWriter writer = new StreamWriter(File.Open(updateSettingsPath, FileMode.Create))) { writer.WriteLine("RemindLater:{0}", DateTime.Now.AddDays(1).ToString("o")); } break; case UpdateDialogResult.SkipVersion: using (StreamWriter writer = new StreamWriter(File.Open(updateSettingsPath, FileMode.Create))) { writer.WriteLine("SkipVersion:{0}", args.NewVersionString); } break; } } }); }; m_ipcClient.ServerUpdateStarting = () => { Application.Current.Shutdown(ExitCodes.ShutdownForUpdate); }; m_ipcClient.DeactivationResultReceived = (deactivationCmd) => { m_logger.Info("Deactivation command is: {0}", deactivationCmd.ToString()); if (deactivationCmd == DeactivationCommand.Granted) { if (CriticalKernelProcessUtility.IsMyProcessKernelCritical) { CriticalKernelProcessUtility.SetMyProcessAsNonKernelCritical(); } m_logger.Info("Deactivation request granted on client."); // Init the shutdown of this application. Application.Current.Shutdown(ExitCodes.ShutdownWithoutSafeguards); } else { m_logger.Info("Deactivation request denied on client."); Current.Dispatcher.BeginInvoke( System.Windows.Threading.DispatcherPriority.Normal, (Action) delegate() { if (m_mainWindow != null) { string message = null; string title = null; switch (deactivationCmd) { case DeactivationCommand.Requested: message = "Your deactivation request has been received, but approval is still pending."; title = "Request Received"; break; case DeactivationCommand.Denied: // A little bit of tact will keep the mob and their pitchforks // from slaughtering us. message = "Your deactivation request has been received, but approval is still pending."; title = "Request Received"; //message = "Your deactivation request has been denied."; //title = "Request Denied"; break; case DeactivationCommand.Granted: message = "Your request was granted."; title = "Request Granted"; break; case DeactivationCommand.NoResponse: message = "Your deactivation request did not reach the server. Check your internet connection and try again."; title = "No Response Received"; break; } m_mainWindow.ShowUserMessage(title, message); } } ); } }; m_ipcClient.BlockActionReceived = (args) => { // Add this blocked request to the dashboard. Current.Dispatcher.BeginInvoke( System.Windows.Threading.DispatcherPriority.Normal, (Action) delegate() { if (m_viewDashboard != null) { m_viewDashboard.AppendBlockActionEvent(args.Category, args.Resource.ToString()); } } ); }; m_ipcClient.ConnectedToServer = () => { m_logger.Info("Connected to IPC server."); }; m_ipcClient.DisconnectedFromServer = () => { m_logger.Warn("Disconnected from IPC server! Automatically attempting reconnect."); }; m_ipcClient.RelaxedPolicyExpired = () => { // We don't have to do anything here on our side, but we may want to do something // here in the future if we modify how our UI shows relaxed policy timer stuff. // Like perhaps changing views etc. }; m_ipcClient.RelaxedPolicyInfoReceived = (args) => { Current.Dispatcher.BeginInvoke( System.Windows.Threading.DispatcherPriority.Normal, (Action) delegate() { // Bypass lists have been enabled. if (args.PolicyInfo != null && m_viewDashboard.DataContext != null && m_viewDashboard.DataContext is DashboardViewModel) { var dashboardViewModel = ((DashboardViewModel)m_viewDashboard.DataContext); dashboardViewModel.AvailableRelaxedRequests = args.PolicyInfo.NumberAvailableToday; dashboardViewModel.RelaxedDuration = new DateTime(args.PolicyInfo.RelaxDuration.Ticks).ToString("HH:mm"); // Ensure we don't overlap this event multiple times by decrementing first. dashboardViewModel.Model.RelaxedPolicyRequested -= OnRelaxedPolicyRequested; dashboardViewModel.Model.RelaxedPolicyRequested += OnRelaxedPolicyRequested; // Ensure we don't overlap this event multiple times by decrementing first. dashboardViewModel.Model.RelinquishRelaxedPolicyRequested -= OnRelinquishRelaxedPolicyRequested; dashboardViewModel.Model.RelinquishRelaxedPolicyRequested += OnRelinquishRelaxedPolicyRequested; } } ); }; m_ipcClient.StateChanged = (args) => { m_logger.Info("Filter status from server is: {0}", args.State.ToString()); switch (args.State) { case FilterStatus.CooldownPeriodEnforced: { // Add this blocked request to the dashboard. Current.Dispatcher.BeginInvoke( System.Windows.Threading.DispatcherPriority.Normal, (Action) delegate() { if (m_viewDashboard != null) { m_viewDashboard.ShowDisabledInternetMessage(DateTime.Now.Add(args.CooldownPeriod)); } } ); } break; case FilterStatus.Running: { OnViewChangeRequest(typeof(DashboardView)); // Change UI state of dashboard to not show disabled message anymore. // If we're not already in a disabled state, this will have no effect. Current.Dispatcher.BeginInvoke( System.Windows.Threading.DispatcherPriority.Normal, (Action) delegate() { if (m_viewDashboard != null) { m_viewDashboard.HideDisabledInternetMessage(); } } ); } break; case FilterStatus.Synchronizing: { // Update our timestamps for last sync. OnViewChangeRequest(typeof(ProgressWait)); lock (m_synchronizingTimerLockObj) { if (m_synchronizingTimer != null) { m_synchronizingTimer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); m_synchronizingTimer.Dispose(); } m_synchronizingTimer = new Timer((state) => { m_ipcClient.RequestStatusRefresh(); m_synchronizingTimer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); m_synchronizingTimer.Dispose(); }); m_synchronizingTimer.Change(TimeSpan.FromSeconds(5), Timeout.InfiniteTimeSpan); } } break; case FilterStatus.Synchronized: { // Update our timestamps for last sync. OnViewChangeRequest(typeof(DashboardView)); // Change UI state of dashboard to not show disabled message anymore. // If we're not already in a disabled state, this will have no effect. Current.Dispatcher.BeginInvoke( System.Windows.Threading.DispatcherPriority.Normal, (Action) delegate() { if (m_viewDashboard != null && m_viewDashboard.DataContext != null) { var dashboardViewModel = ((DashboardViewModel)m_viewDashboard.DataContext); dashboardViewModel.LastSync = DateTime.Now; } } ); } break; } }; m_ipcClient.ClientToClientCommandReceived = (args) => { switch (args.Command) { case ClientToClientCommand.ShowYourself: { BringAppToFocus(); } break; } }; m_ipcClient.CaptivePortalDetectionReceived = (msg) => { // C# doesn't like cross-thread GUI variable access, so run this on window thread. m_mainWindow.Dispatcher.InvokeAsync(() => { ((MainWindowViewModel)m_mainWindow.DataContext).ShowIsGuestNetwork = msg.IsCaptivePortalDetected; }); }; #if CAPTIVE_PORTAL_GUI_ENABLED m_ipcClient.CaptivePortalDetectionReceived = (msg) => { if (msg.IsCaptivePortalDetected && !m_captivePortalShownToUser) { if (m_mainWindow.Visibility == Visibility.Visible) { if (!m_mainWindow.IsVisible) { BringAppToFocus(); } ((MainWindowViewModel)m_mainWindow.DataContext).ShowIsGuestNetwork = true; } else { DisplayCaptivePortalToolTip(); } m_captivePortalShownToUser = true; } else if (!msg.IsCaptivePortalDetected) { m_captivePortalShownToUser = false; } }; #endif } catch (Exception ipce) { LoggerUtil.RecursivelyLogException(m_logger, ipce); } AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; // Run the background init worker for non-UI related initialization. m_backgroundInitWorker = new BackgroundWorker(); m_backgroundInitWorker.DoWork += DoBackgroundInit; m_backgroundInitWorker.RunWorkerCompleted += OnBackgroundInitComplete; m_backgroundInitWorker.RunWorkerAsync(e); }
public void DisableProcessProtection() { CriticalKernelProcessUtility.SetMyProcessAsNonKernelCritical(); }