SEBWIN-312: Started implementing application whitelist mechanism.
This commit is contained in:
parent
f778d5b848
commit
2b976e8150
6 changed files with 158 additions and 132 deletions
|
@ -97,7 +97,7 @@ namespace SafeExamBrowser.Client.Operations
|
|||
|
||||
private void FinalizeApplications()
|
||||
{
|
||||
|
||||
// TODO: Terminate all running applications!
|
||||
}
|
||||
|
||||
private OperationResult HandleAutoTerminationFailure(IList<RunningApplication> applications)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
|
@ -21,7 +22,6 @@ namespace SafeExamBrowser.Monitoring.Applications
|
|||
{
|
||||
public class ApplicationMonitor : IApplicationMonitor
|
||||
{
|
||||
private IntPtr activeWindow;
|
||||
private IList<BlacklistApplication> blacklist;
|
||||
private Guid? captureHookId;
|
||||
private Guid? foregroundHookId;
|
||||
|
@ -31,6 +31,7 @@ namespace SafeExamBrowser.Monitoring.Applications
|
|||
private IProcessFactory processFactory;
|
||||
private Timer timer;
|
||||
private IList<WhitelistApplication> whitelist;
|
||||
private Window activeWindow;
|
||||
|
||||
public event ExplorerStartedEventHandler ExplorerStarted;
|
||||
public event TerminationFailedEventHandler TerminationFailed;
|
||||
|
@ -50,42 +51,9 @@ namespace SafeExamBrowser.Monitoring.Applications
|
|||
{
|
||||
var result = new InitializationResult();
|
||||
|
||||
foreach (var application in settings.Blacklist)
|
||||
{
|
||||
blacklist.Add(application);
|
||||
}
|
||||
|
||||
foreach (var application in settings.Whitelist)
|
||||
{
|
||||
whitelist.Add(application);
|
||||
}
|
||||
|
||||
logger.Debug($"Initialized blacklist with {blacklist.Count} applications{(blacklist.Any() ? $": {string.Join(", ", blacklist.Select(a => a.ExecutableName))}" : ".")}");
|
||||
logger.Debug($"Initialized whitelist with {whitelist.Count} applications{(whitelist.Any() ? $": {string.Join(", ", whitelist.Select(a => a.ExecutableName))}" : ".")}");
|
||||
|
||||
processes = processFactory.GetAllRunning();
|
||||
|
||||
foreach (var process in processes)
|
||||
{
|
||||
foreach (var application in blacklist)
|
||||
{
|
||||
var isBlacklisted = BelongsToApplication(process, application);
|
||||
|
||||
if (isBlacklisted && !application.AutoTerminate)
|
||||
{
|
||||
AddForTermination(application.ExecutableName, process, result);
|
||||
}
|
||||
else if (isBlacklisted && application.AutoTerminate && !TryTerminate(process))
|
||||
{
|
||||
AddFailed(application.ExecutableName, process, result);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var application in whitelist)
|
||||
{
|
||||
// TODO: Check if application is running, auto-terminate or add to result.
|
||||
}
|
||||
}
|
||||
InitializeProcesses();
|
||||
InitializeBlacklist(settings, result);
|
||||
InitializeWhitelist(settings, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -135,10 +103,13 @@ namespace SafeExamBrowser.Monitoring.Applications
|
|||
return success;
|
||||
}
|
||||
|
||||
private void SystemEvent_WindowChanged(IntPtr window)
|
||||
private void SystemEvent_WindowChanged(IntPtr handle)
|
||||
{
|
||||
if (window != IntPtr.Zero && activeWindow != window)
|
||||
if (handle != IntPtr.Zero && activeWindow?.Handle != handle)
|
||||
{
|
||||
var title = nativeMethods.GetWindowTitle(handle);
|
||||
var window = new Window { Handle = handle, Title = title };
|
||||
|
||||
logger.Debug($"Window has changed from {activeWindow} to {window}.");
|
||||
activeWindow = window;
|
||||
|
||||
|
@ -239,12 +210,28 @@ namespace SafeExamBrowser.Monitoring.Applications
|
|||
return sameName || sameOriginalName;
|
||||
}
|
||||
|
||||
private void Close(IntPtr window)
|
||||
private bool BelongsToApplication(IProcess process, WhitelistApplication application)
|
||||
{
|
||||
var title = nativeMethods.GetWindowTitle(window);
|
||||
// TODO: Window title and renderer process handling!
|
||||
// TODO: WRONG! With original name, both must match!
|
||||
var sameName = process.Name.Equals(Path.GetFileNameWithoutExtension(application.ExecutableName), StringComparison.OrdinalIgnoreCase);
|
||||
var sameOriginalName = process.OriginalName?.Equals(application.OriginalName, StringComparison.OrdinalIgnoreCase) == true;
|
||||
|
||||
nativeMethods.SendCloseMessageTo(window);
|
||||
logger.Info($"Sent close message to window '{title}' with handle = {window}.");
|
||||
return sameName || sameOriginalName;
|
||||
}
|
||||
|
||||
private bool BelongsToSafeExamBrowser(IProcess process)
|
||||
{
|
||||
var isRuntime = process.Name == "SafeExamBrowser" && process.OriginalName == "SafeExamBrowser";
|
||||
var isClient = process.Name == "SafeExamBrowser.Client" && process.OriginalName == "SafeExamBrowser.Client";
|
||||
|
||||
return isRuntime || isClient;
|
||||
}
|
||||
|
||||
private void Close(Window window)
|
||||
{
|
||||
nativeMethods.SendCloseMessageTo(window.Handle);
|
||||
logger.Info($"Sent close message to window {window}.");
|
||||
}
|
||||
|
||||
private void HandleExplorerStart(IProcess process)
|
||||
|
@ -253,25 +240,74 @@ namespace SafeExamBrowser.Monitoring.Applications
|
|||
Task.Run(() => ExplorerStarted?.Invoke());
|
||||
}
|
||||
|
||||
private bool IsAllowed(IntPtr window)
|
||||
private void InitializeProcesses()
|
||||
{
|
||||
var processId = nativeMethods.GetProcessIdFor(window);
|
||||
// TODO: Allow only if in whitelist!
|
||||
//var process = processFactory.GetById(Convert.ToInt32(processId));
|
||||
processes = processFactory.GetAllRunning();
|
||||
logger.Debug($"Initialized {processes.Count} currently running processes.");
|
||||
}
|
||||
|
||||
//if (process != null)
|
||||
//{
|
||||
// var allowed = process.Name == "SafeExamBrowser" || process.Name == "SafeExamBrowser.Client";
|
||||
private void InitializeBlacklist(ApplicationSettings settings, InitializationResult result)
|
||||
{
|
||||
foreach (var application in settings.Blacklist)
|
||||
{
|
||||
blacklist.Add(application);
|
||||
}
|
||||
|
||||
// if (!allowed)
|
||||
// {
|
||||
// logger.Warn($"Window with handle = {window} belongs to not allowed process '{process.Name}'!");
|
||||
// }
|
||||
logger.Debug($"Initialized blacklist with {blacklist.Count} applications{(blacklist.Any() ? $": {string.Join(", ", blacklist.Select(a => a.ExecutableName))}" : ".")}");
|
||||
|
||||
// return allowed;
|
||||
//}
|
||||
foreach (var process in processes)
|
||||
{
|
||||
foreach (var application in blacklist)
|
||||
{
|
||||
var isBlacklisted = BelongsToApplication(process, application);
|
||||
|
||||
return true;
|
||||
if (isBlacklisted)
|
||||
{
|
||||
if (!application.AutoTerminate)
|
||||
{
|
||||
AddForTermination(application.ExecutableName, process, result);
|
||||
}
|
||||
else if (application.AutoTerminate && !TryTerminate(process))
|
||||
{
|
||||
AddFailed(application.ExecutableName, process, result);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeWhitelist(ApplicationSettings settings, InitializationResult result)
|
||||
{
|
||||
foreach (var application in settings.Whitelist)
|
||||
{
|
||||
whitelist.Add(application);
|
||||
}
|
||||
|
||||
logger.Debug($"Initialized whitelist with {whitelist.Count} applications{(whitelist.Any() ? $": {string.Join(", ", whitelist.Select(a => a.ExecutableName))}" : ".")}");
|
||||
|
||||
foreach (var process in processes)
|
||||
{
|
||||
foreach (var application in whitelist)
|
||||
{
|
||||
var isWhitelisted = BelongsToApplication(process, application);
|
||||
|
||||
if (isWhitelisted)
|
||||
{
|
||||
if (!application.AllowRunning && !application.AutoTerminate)
|
||||
{
|
||||
AddForTermination(application.ExecutableName, process, result);
|
||||
}
|
||||
else if (!application.AllowRunning && application.AutoTerminate && !TryTerminate(process))
|
||||
{
|
||||
AddFailed(application.ExecutableName, process, result);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsAllowed(IProcess process)
|
||||
|
@ -289,18 +325,46 @@ namespace SafeExamBrowser.Monitoring.Applications
|
|||
return true;
|
||||
}
|
||||
|
||||
private bool TryHide(IntPtr window)
|
||||
private bool IsAllowed(Window window)
|
||||
{
|
||||
var title = nativeMethods.GetWindowTitle(window);
|
||||
var success = nativeMethods.HideWindow(window);
|
||||
|
||||
if (success)
|
||||
var processId = Convert.ToInt32(nativeMethods.GetProcessIdFor(window.Handle));
|
||||
|
||||
if (processFactory.TryGetById(processId, out var process))
|
||||
{
|
||||
logger.Info($"Hid window '{title}' with handle = {window}.");
|
||||
if (BelongsToSafeExamBrowser(process))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (var application in whitelist)
|
||||
{
|
||||
if (BelongsToApplication(process, application))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
logger.Warn($"Window {window} belongs to not allowed process '{process.Name}'!");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn($"Failed to hide window '{title}' with handle = {window}!");
|
||||
logger.Error($"Could not find process for window {window} and process with ID = {processId}!");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryHide(Window window)
|
||||
{
|
||||
var success = nativeMethods.HideWindow(window.Handle);
|
||||
|
||||
if (success)
|
||||
{
|
||||
logger.Info($"Successfully hid window {window}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn($"Failed to hide window {window}!");
|
||||
}
|
||||
|
||||
return success;
|
||||
|
|
23
SafeExamBrowser.Monitoring/Applications/Window.cs
Normal file
23
SafeExamBrowser.Monitoring/Applications/Window.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Applications
|
||||
{
|
||||
internal class Window
|
||||
{
|
||||
public IntPtr Handle { get; set; }
|
||||
public string Title { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"'{Title}' ({Handle})";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -55,6 +55,7 @@
|
|||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Applications\Window.cs" />
|
||||
<Compile Include="Display\Bounds.cs" />
|
||||
<Compile Include="Display\DisplayMonitor.cs" />
|
||||
<Compile Include="Keyboard\KeyboardInterceptor.cs" />
|
||||
|
|
|
@ -440,7 +440,6 @@ namespace SebWindowsConfig
|
|||
public static ListObj permittedProcessList = new ListObj();
|
||||
public static DictObj permittedProcessData = new DictObj();
|
||||
public static DictObj permittedProcessDataDefault = new DictObj();
|
||||
public static DictObj permittedProcessDataXulRunner = new DictObj();
|
||||
|
||||
public static int permittedArgumentIndex;
|
||||
public static ListObj permittedArgumentList = new ListObj();
|
||||
|
@ -510,7 +509,6 @@ namespace SebWindowsConfig
|
|||
SEBSettings.permittedProcessList = new ListObj();
|
||||
SEBSettings.permittedProcessData = new DictObj();
|
||||
SEBSettings.permittedProcessDataDefault = new DictObj();
|
||||
SEBSettings.permittedProcessDataXulRunner = new DictObj();
|
||||
|
||||
SEBSettings.permittedArgumentList = new ListObj();
|
||||
SEBSettings.permittedArgumentData = new DictObj();
|
||||
|
@ -720,24 +718,6 @@ namespace SebWindowsConfig
|
|||
//SEBSettings.permittedArgumentListXulRunner.Add(SEBSettings.permittedArgumentDataXulRunner1);
|
||||
//SEBSettings.permittedArgumentListXulRunner.Add(SEBSettings.permittedArgumentDataXulRunner2);
|
||||
|
||||
// Create a Firefox process with the SEB argument list
|
||||
SEBSettings.permittedProcessDataXulRunner.Clear();
|
||||
SEBSettings.permittedProcessDataXulRunner.Add(SEBSettings.KeyActive , true);
|
||||
SEBSettings.permittedProcessDataXulRunner.Add(SEBSettings.KeyAutostart , true);
|
||||
SEBSettings.permittedProcessDataXulRunner.Add(SEBSettings.KeyIconInTaskbar , true);
|
||||
SEBSettings.permittedProcessDataXulRunner.Add(SEBSettings.KeyRunInBackground , false);
|
||||
SEBSettings.permittedProcessDataXulRunner.Add(SEBSettings.KeyAllowUser , false);
|
||||
SEBSettings.permittedProcessDataXulRunner.Add(SEBSettings.KeyStrongKill , false);
|
||||
SEBSettings.permittedProcessDataXulRunner.Add(SEBSettings.KeyOS , IntWin);
|
||||
SEBSettings.permittedProcessDataXulRunner.Add(SEBSettings.KeyTitle , "SEB");
|
||||
SEBSettings.permittedProcessDataXulRunner.Add(SEBSettings.KeyDescription, "");
|
||||
SEBSettings.permittedProcessDataXulRunner.Add(SEBSettings.KeyExecutable, SEBClientInfo.XUL_RUNNER);
|
||||
SEBSettings.permittedProcessDataXulRunner.Add(SEBSettings.KeyOriginalName, SEBClientInfo.XUL_RUNNER);
|
||||
SEBSettings.permittedProcessDataXulRunner.Add(SEBSettings.KeyPath , "../xulrunner/");
|
||||
SEBSettings.permittedProcessDataXulRunner.Add(SEBSettings.KeyIdentifier , "Firefox");
|
||||
SEBSettings.permittedProcessDataXulRunner.Add(SEBSettings.KeyWindowHandlingProcess , "");
|
||||
SEBSettings.permittedProcessDataXulRunner.Add(SEBSettings.KeyArguments , new ListObj());
|
||||
|
||||
// Default settings for permitted process data
|
||||
SEBSettings.permittedProcessDataDefault.Clear();
|
||||
SEBSettings.permittedProcessDataDefault.Add(SEBSettings.KeyActive , true);
|
||||
|
@ -1470,48 +1450,6 @@ namespace SebWindowsConfig
|
|||
return ret;
|
||||
}
|
||||
|
||||
// **********************************************
|
||||
// Add XulRunnerProcess to Permitted Process List
|
||||
// **********************************************
|
||||
public static void PermitXulRunnerProcess()
|
||||
{
|
||||
// Get the Permitted Process List
|
||||
SEBSettings.permittedProcessList = (ListObj)SEBSettings.settingsCurrent[SEBSettings.KeyPermittedProcesses];
|
||||
|
||||
// Position of XulRunner process in Permitted Process List
|
||||
int indexOfProcessXulRunnerExe = -1;
|
||||
|
||||
// Traverse Permitted Processes of currently opened file
|
||||
for (int listIndex = 0; listIndex < SEBSettings.permittedProcessList.Count; listIndex++)
|
||||
{
|
||||
SEBSettings.permittedProcessData = (DictObj)SEBSettings.permittedProcessList[listIndex];
|
||||
|
||||
// Check if XulRunner process is in Permitted Process List
|
||||
if (SEBSettings.permittedProcessData[SEBSettings.KeyExecutable].Equals(SEBClientInfo.XUL_RUNNER))
|
||||
{
|
||||
indexOfProcessXulRunnerExe = listIndex;
|
||||
break;
|
||||
}
|
||||
else if (SEBSettings.permittedProcessData[SEBSettings.KeyExecutable].Equals("xulrunner.exe"))
|
||||
{
|
||||
//Backwards Compatibility: Use Firefox instead of Xulrunner as SEB Browser
|
||||
((DictObj)SEBSettings.permittedProcessList[listIndex])[SEBSettings.KeyExecutable] = SEBClientInfo.XUL_RUNNER;
|
||||
((DictObj)SEBSettings.permittedProcessList[listIndex])[SEBSettings.KeyOriginalName] = SEBClientInfo.XUL_RUNNER;
|
||||
((DictObj)SEBSettings.permittedProcessList[listIndex])[SEBSettings.KeyIdentifier] = "Firefox";
|
||||
indexOfProcessXulRunnerExe = listIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If XulRunner process was not in Permitted Process List, insert it at the beginning
|
||||
if (indexOfProcessXulRunnerExe == -1)
|
||||
{
|
||||
SEBSettings.permittedProcessList.Insert(0, SEBSettings.permittedProcessDataXulRunner);
|
||||
}
|
||||
|
||||
AddDefaultProhibitedProcesses();
|
||||
}
|
||||
|
||||
public static void AddDefaultProhibitedProcesses()
|
||||
{
|
||||
// Get the Prohibited Process list
|
||||
|
@ -1773,7 +1711,7 @@ namespace SebWindowsConfig
|
|||
SEBSettings.FillSettingsArrays();
|
||||
|
||||
// Add the XulRunner process to the Permitted Process List, if necessary
|
||||
SEBSettings.PermitXulRunnerProcess();
|
||||
SEBSettings.AddDefaultProhibitedProcesses();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1818,7 +1756,7 @@ namespace SebWindowsConfig
|
|||
// Add the XulRunner process to the Permitted Process List, if necessary
|
||||
//SEBSettings.LoggSettingsDictionary(ref SEBSettings.settingsDefault, "DebugSettingsDefaultInReadSebConfigurationFilePermitBefore.txt");
|
||||
//SEBSettings.LoggSettingsDictionary(ref SEBSettings.settingsCurrent, "DebugSettingsCurrentInReadSebConfigurationFilePermitBefore.txt");
|
||||
SEBSettings.PermitXulRunnerProcess();
|
||||
SEBSettings.AddDefaultProhibitedProcesses();
|
||||
//SEBSettings.LoggSettingsDictionary(ref SEBSettings.settingsDefault, "DebugSettingsDefaultInReadSebConfigurationFilePermitAfter.txt");
|
||||
//SEBSettings.LoggSettingsDictionary(ref SEBSettings.settingsCurrent, "DebugSettingsCurrentInReadSebConfigurationFilePermitAfter.txt");
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ namespace SebWindowsConfig
|
|||
|
||||
// Set all the default values for the Plist structure "SEBSettings.settingsCurrent"
|
||||
SEBSettings.RestoreDefaultAndCurrentSettings();
|
||||
SEBSettings.PermitXulRunnerProcess();
|
||||
SEBSettings.AddDefaultProhibitedProcesses();
|
||||
|
||||
// Initialise the global variables for the GUI widgets
|
||||
InitialiseGlobalVariablesForGUIWidgets();
|
||||
|
@ -1385,7 +1385,7 @@ namespace SebWindowsConfig
|
|||
settingsPassword = "";
|
||||
settingsPasswordFieldsContainHash = false;
|
||||
SEBSettings.RestoreDefaultAndCurrentSettings();
|
||||
SEBSettings.PermitXulRunnerProcess();
|
||||
SEBSettings.AddDefaultProhibitedProcesses();
|
||||
|
||||
// Check if currently edited settings are local client settings (in %appdata% or %commonappdata%) or the default settings (no client settings saved yet)
|
||||
if (!currentPathSebConfigFile.Equals(SEBClientInfo.SebClientSettingsAppDataFile) && !currentPathSebConfigFile.Equals(SEBClientInfo.SebClientSettingsProgramDataFile) && !currentPathSebConfigFile.Equals(SEBUIStrings.settingsTitleDefaultSettings))
|
||||
|
@ -1435,7 +1435,7 @@ namespace SebWindowsConfig
|
|||
settingsPassword = "";
|
||||
settingsPasswordFieldsContainHash = false;
|
||||
SEBSettings.RestoreDefaultAndCurrentSettings();
|
||||
SEBSettings.PermitXulRunnerProcess();
|
||||
SEBSettings.AddDefaultProhibitedProcesses();
|
||||
currentPathSebConfigFile = SEBUIStrings.settingsTitleDefaultSettings;
|
||||
// Update URL filter rules, also the seb-Browser white/blacklist keys,
|
||||
// which are necessary for compatibility to SEB 2.1.x
|
||||
|
|
Loading…
Reference in a new issue