diff --git a/SafeExamBrowser.Client/ClientController.cs b/SafeExamBrowser.Client/ClientController.cs
index 18e3e77b..b8983f5c 100644
--- a/SafeExamBrowser.Client/ClientController.cs
+++ b/SafeExamBrowser.Client/ClientController.cs
@@ -14,6 +14,7 @@ using SafeExamBrowser.Contracts.Communication.Events;
using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Communication.Proxies;
using SafeExamBrowser.Contracts.Configuration;
+using SafeExamBrowser.Contracts.Configuration.Cryptography;
using SafeExamBrowser.Contracts.Configuration.Settings;
using SafeExamBrowser.Contracts.Core;
using SafeExamBrowser.Contracts.Core.OperationModel;
@@ -33,6 +34,7 @@ namespace SafeExamBrowser.Client
{
private IDisplayMonitor displayMonitor;
private IExplorerShell explorerShell;
+ private IHashAlgorithm hashAlgorithm;
private ILogger logger;
private IMessageBox messageBox;
private IOperationSequence operations;
@@ -67,6 +69,7 @@ namespace SafeExamBrowser.Client
public ClientController(
IDisplayMonitor displayMonitor,
IExplorerShell explorerShell,
+ IHashAlgorithm hashAlgorithm,
ILogger logger,
IMessageBox messageBox,
IOperationSequence operations,
@@ -80,6 +83,7 @@ namespace SafeExamBrowser.Client
{
this.displayMonitor = displayMonitor;
this.explorerShell = explorerShell;
+ this.hashAlgorithm = hashAlgorithm;
this.logger = logger;
this.messageBox = messageBox;
this.operations = operations;
@@ -342,9 +346,19 @@ namespace SafeExamBrowser.Client
private void Taskbar_QuitButtonClicked(System.ComponentModel.CancelEventArgs args)
{
- var result = messageBox.Show(TextKey.MessageBox_Quit, TextKey.MessageBox_QuitTitle, MessageBoxAction.YesNo, MessageBoxIcon.Question);
+ var hasQuitPassword = !String.IsNullOrEmpty(Settings.QuitPasswordHash);
+ var requestShutdown = false;
- if (result == MessageBoxResult.Yes)
+ if (hasQuitPassword)
+ {
+ requestShutdown = TryValidateQuitPassword();
+ }
+ else
+ {
+ requestShutdown = TryConfirmShutdown();
+ }
+
+ if (requestShutdown)
{
var communication = runtime.RequestShutdown();
@@ -374,5 +388,44 @@ namespace SafeExamBrowser.Client
}
}
}
+
+ private bool TryConfirmShutdown()
+ {
+ var result = messageBox.Show(TextKey.MessageBox_Quit, TextKey.MessageBox_QuitTitle, MessageBoxAction.YesNo, MessageBoxIcon.Question);
+ var quit = result == MessageBoxResult.Yes;
+
+ if (quit)
+ {
+ logger.Info("The user chose to terminate the application.");
+ }
+
+ return quit;
+ }
+
+ private bool TryValidateQuitPassword()
+ {
+ var dialog = uiFactory.CreatePasswordDialog(TextKey.PasswordDialog_QuitPasswordRequired, TextKey.PasswordDialog_QuitPasswordRequiredTitle);
+ var result = dialog.Show();
+
+ if (result.Success)
+ {
+ var passwordHash = hashAlgorithm.GenerateHashFor(result.Password);
+ var isCorrect = Settings.QuitPasswordHash.Equals(passwordHash, StringComparison.OrdinalIgnoreCase);
+
+ if (isCorrect)
+ {
+ logger.Info("The user entered the correct quit password, the application will now terminate.");
+ }
+ else
+ {
+ logger.Info("The user entered the wrong quit password.");
+ messageBox.Show(TextKey.MessageBox_InvalidQuitPassword, TextKey.MessageBox_InvalidQuitPasswordTitle, icon: MessageBoxIcon.Warning);
+ }
+
+ return isCorrect;
+ }
+
+ return false;
+ }
}
}
diff --git a/SafeExamBrowser.Client/CompositionRoot.cs b/SafeExamBrowser.Client/CompositionRoot.cs
index 0086dc3a..c3cfc453 100644
--- a/SafeExamBrowser.Client/CompositionRoot.cs
+++ b/SafeExamBrowser.Client/CompositionRoot.cs
@@ -18,6 +18,7 @@ using SafeExamBrowser.Client.Operations;
using SafeExamBrowser.Communication.Hosts;
using SafeExamBrowser.Communication.Proxies;
using SafeExamBrowser.Configuration;
+using SafeExamBrowser.Configuration.Cryptography;
using SafeExamBrowser.Contracts.Browser;
using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Communication.Proxies;
@@ -88,6 +89,7 @@ namespace SafeExamBrowser.Client
var displayMonitor = new DisplayMonitor(new ModuleLogger(logger, nameof(DisplayMonitor)), nativeMethods);
var explorerShell = new ExplorerShell(new ModuleLogger(logger, nameof(ExplorerShell)), nativeMethods);
+ var hashAlgorithm = new HashAlgorithm();
Taskbar = new Taskbar(new ModuleLogger(logger, nameof(Taskbar)));
@@ -111,7 +113,7 @@ namespace SafeExamBrowser.Client
var sequence = new OperationSequence(logger, operations);
- ClientController = new ClientController(displayMonitor, explorerShell, logger, messageBox, sequence, processMonitor, runtimeProxy, shutdown, Taskbar, text, uiFactory, windowMonitor);
+ ClientController = new ClientController(displayMonitor, explorerShell, hashAlgorithm, logger, messageBox, sequence, processMonitor, runtimeProxy, shutdown, Taskbar, text, uiFactory, windowMonitor);
}
internal void LogStartupInformation()
diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.General.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.General.cs
index a116da61..5d1f7046 100644
--- a/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.General.cs
+++ b/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.General.cs
@@ -20,6 +20,14 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
}
}
+ private void MapQuitPasswordHash(Settings settings, object value)
+ {
+ if (value is string hash)
+ {
+ settings.QuitPasswordHash = hash;
+ }
+ }
+
private void MapStartUrl(Settings settings, object value)
{
if (value is string url)
diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.cs
index 77b32b44..14052b45 100644
--- a/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.cs
+++ b/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.cs
@@ -31,6 +31,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
case Keys.General.AdminPasswordHash:
MapAdminPasswordHash(settings, value);
break;
+ case Keys.General.QuitPasswordHash:
+ MapQuitPasswordHash(settings, value);
+ break;
case Keys.General.StartUrl:
MapStartUrl(settings, value);
break;
diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs
index 975f3aa6..5dce77d0 100644
--- a/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs
+++ b/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs
@@ -89,12 +89,47 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
{
var settings = new Settings();
- // TODO: Specify default settings
+ settings.Browser.StartUrl = "https://www.safeexambrowser.org/start";
+ settings.Browser.AllowAddressBar = false;
+ settings.Browser.AllowBackwardNavigation = false;
+ settings.Browser.AllowConfigurationDownloads = true;
+ settings.Browser.AllowDeveloperConsole = false;
+ settings.Browser.AllowDownloads = false;
+ settings.Browser.AllowForwardNavigation = false;
+ settings.Browser.AllowReloading = true;
+
+ settings.Keyboard.AllowAltEsc = false;
+ settings.Keyboard.AllowAltF4 = false;
+ settings.Keyboard.AllowAltTab = true;
+ settings.Keyboard.AllowCtrlEsc = false;
+ settings.Keyboard.AllowEsc = true;
+ settings.Keyboard.AllowF1 = true;
+ settings.Keyboard.AllowF2 = true;
+ settings.Keyboard.AllowF3 = true;
+ settings.Keyboard.AllowF4 = true;
+ settings.Keyboard.AllowF5 = true;
+ settings.Keyboard.AllowF6 = true;
+ settings.Keyboard.AllowF7 = true;
+ settings.Keyboard.AllowF8 = true;
+ settings.Keyboard.AllowF9 = true;
+ settings.Keyboard.AllowF10 = true;
+ settings.Keyboard.AllowF11 = true;
+ settings.Keyboard.AllowF12 = true;
+ settings.Keyboard.AllowPrintScreen = false;
+ settings.Keyboard.AllowSystemKey = false;
+
+ settings.KioskMode = KioskMode.CreateNewDesktop;
+
+ settings.Mouse.AllowMiddleButton = false;
+ settings.Mouse.AllowRightButton = true;
- settings.KioskMode = KioskMode.None;
settings.ServicePolicy = ServicePolicy.Optional;
- settings.Browser.StartUrl = "https://www.safeexambrowser.org/testing";
+ settings.Taskbar.AllowApplicationLog = false;
+ settings.Taskbar.AllowKeyboardLayout = true;
+ settings.Taskbar.AllowWirelessNetwork = false;
+
+ // TODO: Default values for alpha version only, remove for final release!
settings.Browser.AllowAddressBar = true;
settings.Browser.AllowBackwardNavigation = true;
settings.Browser.AllowConfigurationDownloads = true;
@@ -102,9 +137,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
settings.Browser.AllowDownloads = true;
settings.Browser.AllowForwardNavigation = true;
settings.Browser.AllowReloading = true;
-
+ settings.KioskMode = KioskMode.None;
+ settings.ServicePolicy = ServicePolicy.Optional;
settings.Taskbar.AllowApplicationLog = true;
- settings.Taskbar.AllowKeyboardLayout = true;
settings.Taskbar.AllowWirelessNetwork = true;
return settings;
diff --git a/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs b/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs
index 698a068e..702c2c32 100644
--- a/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs
+++ b/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs
@@ -35,6 +35,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
internal static class General
{
internal const string AdminPasswordHash = "hashedAdminPassword";
+ internal const string QuitPasswordHash = "hashedQuitPassword";
internal const string StartUrl = "startURL";
}
@@ -42,30 +43,30 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
{
internal static class Keyboard
{
- public const string EnableAltEsc = "enableAltEsc";
- public const string EnableAltTab = "enableAltTab";
- public const string EnableAltF4 = "enableAltF4";
- public const string EnableCtrlEsc = "enableCtrlEsc";
- public const string EnableEsc = "enableEsc";
- public const string EnableF1 = "enableF1";
- public const string EnableF2 = "enableF2";
- public const string EnableF3 = "enableF3";
- public const string EnableF4 = "enableF4";
- public const string EnableF5 = "enableF5";
- public const string EnableF6 = "enableF6";
- public const string EnableF7 = "enableF7";
- public const string EnableF8 = "enableF8";
- public const string EnableF9 = "enableF9";
- public const string EnableF10 = "enableF10";
- public const string EnableF11 = "enableF11";
- public const string EnableF12 = "enableF12";
- public const string EnablePrintScreen = "enablePrintScreen";
- public const string EnableSystemKey = "enableStartMenu";
+ internal const string EnableAltEsc = "enableAltEsc";
+ internal const string EnableAltTab = "enableAltTab";
+ internal const string EnableAltF4 = "enableAltF4";
+ internal const string EnableCtrlEsc = "enableCtrlEsc";
+ internal const string EnableEsc = "enableEsc";
+ internal const string EnableF1 = "enableF1";
+ internal const string EnableF2 = "enableF2";
+ internal const string EnableF3 = "enableF3";
+ internal const string EnableF4 = "enableF4";
+ internal const string EnableF5 = "enableF5";
+ internal const string EnableF6 = "enableF6";
+ internal const string EnableF7 = "enableF7";
+ internal const string EnableF8 = "enableF8";
+ internal const string EnableF9 = "enableF9";
+ internal const string EnableF10 = "enableF10";
+ internal const string EnableF11 = "enableF11";
+ internal const string EnableF12 = "enableF12";
+ internal const string EnablePrintScreen = "enablePrintScreen";
+ internal const string EnableSystemKey = "enableStartMenu";
}
internal static class Mouse
{
- public const string EnableRightMouse = "enableRightMouse";
+ internal const string EnableRightMouse = "enableRightMouse";
}
}
diff --git a/SafeExamBrowser.Contracts/Configuration/Settings/Settings.cs b/SafeExamBrowser.Contracts/Configuration/Settings/Settings.cs
index efca2e41..c4fcf1ef 100644
--- a/SafeExamBrowser.Contracts/Configuration/Settings/Settings.cs
+++ b/SafeExamBrowser.Contracts/Configuration/Settings/Settings.cs
@@ -46,6 +46,11 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
///
public MouseSettings Mouse { get; set; }
+ ///
+ /// The hash code of the quit password.
+ ///
+ public string QuitPasswordHash { get; set; }
+
///
/// The active policy for the service component.
///
@@ -62,10 +67,6 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
Keyboard = new KeyboardSettings();
Mouse = new MouseSettings();
Taskbar = new TaskbarSettings();
-
- // TODO: For version 3.0 Alpha only, remove for final release!
- ServicePolicy = ServicePolicy.Optional;
- Taskbar.AllowApplicationLog = true;
}
}
}
diff --git a/SafeExamBrowser.Contracts/I18n/TextKey.cs b/SafeExamBrowser.Contracts/I18n/TextKey.cs
index 28ad1dc7..670fa473 100644
--- a/SafeExamBrowser.Contracts/I18n/TextKey.cs
+++ b/SafeExamBrowser.Contracts/I18n/TextKey.cs
@@ -28,6 +28,8 @@ namespace SafeExamBrowser.Contracts.I18n
MessageBox_InvalidConfigurationDataTitle,
MessageBox_InvalidPasswordError,
MessageBox_InvalidPasswordErrorTitle,
+ MessageBox_InvalidQuitPassword,
+ MessageBox_InvalidQuitPasswordTitle,
MessageBox_NotSupportedConfigurationResource,
MessageBox_NotSupportedConfigurationResourceTitle,
MessageBox_Quit,
@@ -88,6 +90,8 @@ namespace SafeExamBrowser.Contracts.I18n
PasswordDialog_AdminPasswordRequiredTitle,
PasswordDialog_Cancel,
PasswordDialog_Confirm,
+ PasswordDialog_QuitPasswordRequired,
+ PasswordDialog_QuitPasswordRequiredTitle,
PasswordDialog_SettingsPasswordRequired,
PasswordDialog_SettingsPasswordRequiredTitle,
RuntimeWindow_ApplicationRunning,
diff --git a/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs b/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs
index 50c7e96c..400400e9 100644
--- a/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs
+++ b/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs
@@ -8,6 +8,7 @@
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings;
+using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.UserInterface.Browser;
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
@@ -57,6 +58,11 @@ namespace SafeExamBrowser.Contracts.UserInterface
///
IPasswordDialog CreatePasswordDialog(string message, string title);
+ ///
+ /// Creates a password dialog with the given message and title.
+ ///
+ IPasswordDialog CreatePasswordDialog(TextKey message, TextKey title);
+
///
/// Creates a system control displaying the power supply status of the computer.
///
diff --git a/SafeExamBrowser.I18n/Text.xml b/SafeExamBrowser.I18n/Text.xml
index 810b609e..a1926ce7 100644
--- a/SafeExamBrowser.I18n/Text.xml
+++ b/SafeExamBrowser.I18n/Text.xml
@@ -42,6 +42,12 @@
Invalid Password
+
+ The application can only be terminated by entering the correct quit password.
+
+
+ Invalid Quit Password
+
The configuration resource '%%URI%%' is not supported!
@@ -216,6 +222,12 @@
Confirm
+
+ Please enter the quit password in order to terminate the application:
+
+
+ Quit Password Required
+
Please enter the settings password for the application configuration:
diff --git a/SafeExamBrowser.UserInterface.Classic/UserInterfaceFactory.cs b/SafeExamBrowser.UserInterface.Classic/UserInterfaceFactory.cs
index b556ab53..c57a94b5 100644
--- a/SafeExamBrowser.UserInterface.Classic/UserInterfaceFactory.cs
+++ b/SafeExamBrowser.UserInterface.Classic/UserInterfaceFactory.cs
@@ -87,6 +87,11 @@ namespace SafeExamBrowser.UserInterface.Classic
return Application.Current.Dispatcher.Invoke(() => new PasswordDialog(message, title, text));
}
+ public IPasswordDialog CreatePasswordDialog(TextKey message, TextKey title)
+ {
+ return Application.Current.Dispatcher.Invoke(() => new PasswordDialog(text.Get(message), text.Get(title), text));
+ }
+
public ISystemPowerSupplyControl CreatePowerSupplyControl()
{
return new PowerSupplyControl();
diff --git a/SafeExamBrowser.UserInterface.Windows10/UserInterfaceFactory.cs b/SafeExamBrowser.UserInterface.Windows10/UserInterfaceFactory.cs
index 999eff4e..f0cac923 100644
--- a/SafeExamBrowser.UserInterface.Windows10/UserInterfaceFactory.cs
+++ b/SafeExamBrowser.UserInterface.Windows10/UserInterfaceFactory.cs
@@ -86,6 +86,12 @@ namespace SafeExamBrowser.UserInterface.Windows10
throw new System.NotImplementedException();
}
+ public IPasswordDialog CreatePasswordDialog(TextKey message, TextKey title)
+ {
+ // TODO
+ throw new System.NotImplementedException();
+ }
+
public ISystemPowerSupplyControl CreatePowerSupplyControl()
{
return new PowerSupplyControl();