SEBWIN-508: Implemented basic JavaScript API.
This commit is contained in:
parent
deccb3340c
commit
0da587e521
19 changed files with 311 additions and 100 deletions
|
@ -13,6 +13,7 @@ using Moq;
|
||||||
using SafeExamBrowser.Browser.Contracts.Filters;
|
using SafeExamBrowser.Browser.Contracts.Filters;
|
||||||
using SafeExamBrowser.Browser.Handlers;
|
using SafeExamBrowser.Browser.Handlers;
|
||||||
using SafeExamBrowser.Configuration.Contracts;
|
using SafeExamBrowser.Configuration.Contracts;
|
||||||
|
using SafeExamBrowser.Configuration.Contracts.Cryptography;
|
||||||
using SafeExamBrowser.I18n.Contracts;
|
using SafeExamBrowser.I18n.Contracts;
|
||||||
using SafeExamBrowser.Logging.Contracts;
|
using SafeExamBrowser.Logging.Contracts;
|
||||||
using SafeExamBrowser.Settings.Browser;
|
using SafeExamBrowser.Settings.Browser;
|
||||||
|
@ -29,6 +30,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
|
||||||
{
|
{
|
||||||
private AppConfig appConfig;
|
private AppConfig appConfig;
|
||||||
private Mock<IRequestFilter> filter;
|
private Mock<IRequestFilter> filter;
|
||||||
|
private Mock<IKeyGenerator> keyGenerator;
|
||||||
private Mock<ILogger> logger;
|
private Mock<ILogger> logger;
|
||||||
private BrowserSettings settings;
|
private BrowserSettings settings;
|
||||||
private WindowSettings windowSettings;
|
private WindowSettings windowSettings;
|
||||||
|
@ -41,11 +43,12 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
|
||||||
{
|
{
|
||||||
appConfig = new AppConfig();
|
appConfig = new AppConfig();
|
||||||
filter = new Mock<IRequestFilter>();
|
filter = new Mock<IRequestFilter>();
|
||||||
|
keyGenerator = new Mock<IKeyGenerator>();
|
||||||
logger = new Mock<ILogger>();
|
logger = new Mock<ILogger>();
|
||||||
settings = new BrowserSettings();
|
settings = new BrowserSettings();
|
||||||
windowSettings = new WindowSettings();
|
windowSettings = new WindowSettings();
|
||||||
text = new Mock<IText>();
|
text = new Mock<IText>();
|
||||||
resourceHandler = new ResourceHandler(appConfig, filter.Object, logger.Object, settings, windowSettings, text.Object);
|
resourceHandler = new ResourceHandler(appConfig, filter.Object, keyGenerator.Object, logger.Object, settings, windowSettings, text.Object);
|
||||||
|
|
||||||
sut = new TestableRequestHandler(appConfig, filter.Object, logger.Object, resourceHandler, settings, windowSettings, text.Object);
|
sut = new TestableRequestHandler(appConfig, filter.Object, logger.Object, resourceHandler, settings, windowSettings, text.Object);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using Moq;
|
using Moq;
|
||||||
using SafeExamBrowser.Browser.Contracts.Filters;
|
using SafeExamBrowser.Browser.Contracts.Filters;
|
||||||
using SafeExamBrowser.Configuration.Contracts;
|
using SafeExamBrowser.Configuration.Contracts;
|
||||||
|
using SafeExamBrowser.Configuration.Contracts.Cryptography;
|
||||||
using SafeExamBrowser.I18n.Contracts;
|
using SafeExamBrowser.I18n.Contracts;
|
||||||
using SafeExamBrowser.Logging.Contracts;
|
using SafeExamBrowser.Logging.Contracts;
|
||||||
using SafeExamBrowser.Settings.Browser;
|
using SafeExamBrowser.Settings.Browser;
|
||||||
|
@ -30,6 +31,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
|
||||||
{
|
{
|
||||||
private AppConfig appConfig;
|
private AppConfig appConfig;
|
||||||
private Mock<IRequestFilter> filter;
|
private Mock<IRequestFilter> filter;
|
||||||
|
private Mock<IKeyGenerator> keyGenerator;
|
||||||
private Mock<ILogger> logger;
|
private Mock<ILogger> logger;
|
||||||
private BrowserSettings settings;
|
private BrowserSettings settings;
|
||||||
private WindowSettings windowSettings;
|
private WindowSettings windowSettings;
|
||||||
|
@ -41,12 +43,13 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
|
||||||
{
|
{
|
||||||
appConfig = new AppConfig();
|
appConfig = new AppConfig();
|
||||||
filter = new Mock<IRequestFilter>();
|
filter = new Mock<IRequestFilter>();
|
||||||
|
keyGenerator = new Mock<IKeyGenerator>();
|
||||||
logger = new Mock<ILogger>();
|
logger = new Mock<ILogger>();
|
||||||
settings = new BrowserSettings();
|
settings = new BrowserSettings();
|
||||||
windowSettings = new WindowSettings();
|
windowSettings = new WindowSettings();
|
||||||
text = new Mock<IText>();
|
text = new Mock<IText>();
|
||||||
|
|
||||||
sut = new TestableResourceHandler(appConfig, filter.Object, logger.Object, settings, windowSettings, text.Object);
|
sut = new TestableResourceHandler(appConfig, filter.Object, keyGenerator.Object, logger.Object, settings, windowSettings, text.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
@ -57,11 +60,13 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
|
||||||
var request = new Mock<IRequest>();
|
var request = new Mock<IRequest>();
|
||||||
|
|
||||||
browser.SetupGet(b => b.Address).Returns("http://www.host.org");
|
browser.SetupGet(b => b.Address).Returns("http://www.host.org");
|
||||||
|
keyGenerator.Setup(g => g.CalculateBrowserExamKeyHash(It.IsAny<string>())).Returns(new Random().Next().ToString());
|
||||||
|
keyGenerator.Setup(g => g.CalculateConfigurationKeyHash(It.IsAny<string>())).Returns(new Random().Next().ToString());
|
||||||
request.SetupGet(r => r.Headers).Returns(new NameValueCollection());
|
request.SetupGet(r => r.Headers).Returns(new NameValueCollection());
|
||||||
request.SetupGet(r => r.Url).Returns("http://www.host.org");
|
request.SetupGet(r => r.Url).Returns("http://www.host.org");
|
||||||
request.SetupSet(r => r.Headers = It.IsAny<NameValueCollection>()).Callback<NameValueCollection>((h) => headers = h);
|
request.SetupSet(r => r.Headers = It.IsAny<NameValueCollection>()).Callback<NameValueCollection>((h) => headers = h);
|
||||||
settings.SendConfigurationKey = true;
|
settings.SendConfigurationKey = true;
|
||||||
settings.SendExamKey = true;
|
settings.SendBrowserExamKey = true;
|
||||||
|
|
||||||
var result = sut.OnBeforeResourceLoad(browser.Object, Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, Mock.Of<IRequestCallback>());
|
var result = sut.OnBeforeResourceLoad(browser.Object, Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, Mock.Of<IRequestCallback>());
|
||||||
|
|
||||||
|
@ -85,7 +90,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
|
||||||
request.SetupGet(r => r.Url).Returns("http://www.host.org");
|
request.SetupGet(r => r.Url).Returns("http://www.host.org");
|
||||||
request.SetupSet(r => r.Headers = It.IsAny<NameValueCollection>()).Callback<NameValueCollection>((h) => headers = h);
|
request.SetupSet(r => r.Headers = It.IsAny<NameValueCollection>()).Callback<NameValueCollection>((h) => headers = h);
|
||||||
settings.SendConfigurationKey = true;
|
settings.SendConfigurationKey = true;
|
||||||
settings.SendExamKey = true;
|
settings.SendBrowserExamKey = true;
|
||||||
|
|
||||||
var result = sut.OnBeforeResourceLoad(browser.Object, Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, Mock.Of<IRequestCallback>());
|
var result = sut.OnBeforeResourceLoad(browser.Object, Mock.Of<IBrowser>(), Mock.Of<IFrame>(), request.Object, Mock.Of<IRequestCallback>());
|
||||||
|
|
||||||
|
@ -291,10 +296,11 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
|
||||||
internal TestableResourceHandler(
|
internal TestableResourceHandler(
|
||||||
AppConfig appConfig,
|
AppConfig appConfig,
|
||||||
IRequestFilter filter,
|
IRequestFilter filter,
|
||||||
|
IKeyGenerator keyGenerator,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
BrowserSettings settings,
|
BrowserSettings settings,
|
||||||
WindowSettings windowSettings,
|
WindowSettings windowSettings,
|
||||||
IText text) : base(appConfig, filter, logger, settings, windowSettings, text)
|
IText text) : base(appConfig, filter, keyGenerator, logger, settings, windowSettings, text)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,16 +38,17 @@ namespace SafeExamBrowser.Browser
|
||||||
{
|
{
|
||||||
private int instanceIdCounter = default(int);
|
private int instanceIdCounter = default(int);
|
||||||
|
|
||||||
private AppConfig appConfig;
|
private readonly AppConfig appConfig;
|
||||||
private List<BrowserApplicationInstance> instances;
|
private readonly IFileSystemDialog fileSystemDialog;
|
||||||
private IFileSystemDialog fileSystemDialog;
|
private readonly IHashAlgorithm hashAlgorithm;
|
||||||
private IHashAlgorithm hashAlgorithm;
|
private readonly List<BrowserApplicationInstance> instances;
|
||||||
private INativeMethods nativeMethods;
|
private readonly IKeyGenerator keyGenerator;
|
||||||
private IMessageBox messageBox;
|
private readonly IModuleLogger logger;
|
||||||
private IModuleLogger logger;
|
private readonly IMessageBox messageBox;
|
||||||
private BrowserSettings settings;
|
private readonly INativeMethods nativeMethods;
|
||||||
private IText text;
|
private readonly BrowserSettings settings;
|
||||||
private IUserInterfaceFactory uiFactory;
|
private readonly IText text;
|
||||||
|
private readonly IUserInterfaceFactory uiFactory;
|
||||||
|
|
||||||
public bool AutoStart { get; private set; }
|
public bool AutoStart { get; private set; }
|
||||||
public IconResource Icon { get; private set; }
|
public IconResource Icon { get; private set; }
|
||||||
|
@ -65,6 +66,7 @@ namespace SafeExamBrowser.Browser
|
||||||
BrowserSettings settings,
|
BrowserSettings settings,
|
||||||
IFileSystemDialog fileSystemDialog,
|
IFileSystemDialog fileSystemDialog,
|
||||||
IHashAlgorithm hashAlgorithm,
|
IHashAlgorithm hashAlgorithm,
|
||||||
|
IKeyGenerator keyGenerator,
|
||||||
INativeMethods nativeMethods,
|
INativeMethods nativeMethods,
|
||||||
IMessageBox messageBox,
|
IMessageBox messageBox,
|
||||||
IModuleLogger logger,
|
IModuleLogger logger,
|
||||||
|
@ -74,10 +76,11 @@ namespace SafeExamBrowser.Browser
|
||||||
this.appConfig = appConfig;
|
this.appConfig = appConfig;
|
||||||
this.fileSystemDialog = fileSystemDialog;
|
this.fileSystemDialog = fileSystemDialog;
|
||||||
this.hashAlgorithm = hashAlgorithm;
|
this.hashAlgorithm = hashAlgorithm;
|
||||||
this.nativeMethods = nativeMethods;
|
|
||||||
this.instances = new List<BrowserApplicationInstance>();
|
this.instances = new List<BrowserApplicationInstance>();
|
||||||
|
this.keyGenerator = keyGenerator;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.messageBox = messageBox;
|
this.messageBox = messageBox;
|
||||||
|
this.nativeMethods = nativeMethods;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.uiFactory = uiFactory;
|
this.uiFactory = uiFactory;
|
||||||
|
@ -172,7 +175,19 @@ namespace SafeExamBrowser.Browser
|
||||||
var isMainInstance = instances.Count == 0;
|
var isMainInstance = instances.Count == 0;
|
||||||
var instanceLogger = logger.CloneFor($"Browser Instance #{id}");
|
var instanceLogger = logger.CloneFor($"Browser Instance #{id}");
|
||||||
var startUrl = url ?? GenerateStartUrl();
|
var startUrl = url ?? GenerateStartUrl();
|
||||||
var instance = new BrowserApplicationInstance(appConfig, settings, id, isMainInstance, fileSystemDialog, hashAlgorithm, messageBox, instanceLogger, text, uiFactory, startUrl);
|
var instance = new BrowserApplicationInstance(
|
||||||
|
appConfig,
|
||||||
|
settings,
|
||||||
|
id,
|
||||||
|
isMainInstance,
|
||||||
|
fileSystemDialog,
|
||||||
|
hashAlgorithm,
|
||||||
|
keyGenerator,
|
||||||
|
messageBox,
|
||||||
|
instanceLogger,
|
||||||
|
text,
|
||||||
|
uiFactory,
|
||||||
|
startUrl);
|
||||||
|
|
||||||
instance.ConfigurationDownloadRequested += (fileName, args) => ConfigurationDownloadRequested?.Invoke(fileName, args);
|
instance.ConfigurationDownloadRequested += (fileName, args) => ConfigurationDownloadRequested?.Invoke(fileName, args);
|
||||||
instance.PopupRequested += Instance_PopupRequested;
|
instance.PopupRequested += Instance_PopupRequested;
|
||||||
|
|
|
@ -41,19 +41,21 @@ namespace SafeExamBrowser.Browser
|
||||||
{
|
{
|
||||||
private const double ZOOM_FACTOR = 0.2;
|
private const double ZOOM_FACTOR = 0.2;
|
||||||
|
|
||||||
private AppConfig appConfig;
|
private readonly AppConfig appConfig;
|
||||||
|
private readonly IFileSystemDialog fileSystemDialog;
|
||||||
|
private readonly IHashAlgorithm hashAlgorithm;
|
||||||
|
private readonly HttpClient httpClient;
|
||||||
|
private readonly IKeyGenerator keyGenerator;
|
||||||
|
private readonly IModuleLogger logger;
|
||||||
|
private readonly IMessageBox messageBox;
|
||||||
|
private readonly IText text;
|
||||||
|
private readonly IUserInterfaceFactory uiFactory;
|
||||||
|
|
||||||
private IBrowserControl control;
|
private IBrowserControl control;
|
||||||
private IBrowserWindow window;
|
private IBrowserWindow window;
|
||||||
private HttpClient httpClient;
|
|
||||||
private bool isMainInstance;
|
private bool isMainInstance;
|
||||||
private IFileSystemDialog fileSystemDialog;
|
|
||||||
private IHashAlgorithm hashAlgorithm;
|
|
||||||
private IMessageBox messageBox;
|
|
||||||
private IModuleLogger logger;
|
|
||||||
private BrowserSettings settings;
|
private BrowserSettings settings;
|
||||||
private string startUrl;
|
private string startUrl;
|
||||||
private IText text;
|
|
||||||
private IUserInterfaceFactory uiFactory;
|
|
||||||
private double zoomLevel;
|
private double zoomLevel;
|
||||||
|
|
||||||
private WindowSettings WindowSettings
|
private WindowSettings WindowSettings
|
||||||
|
@ -84,6 +86,7 @@ namespace SafeExamBrowser.Browser
|
||||||
bool isMainInstance,
|
bool isMainInstance,
|
||||||
IFileSystemDialog fileSystemDialog,
|
IFileSystemDialog fileSystemDialog,
|
||||||
IHashAlgorithm hashAlgorithm,
|
IHashAlgorithm hashAlgorithm,
|
||||||
|
IKeyGenerator keyGenerator,
|
||||||
IMessageBox messageBox,
|
IMessageBox messageBox,
|
||||||
IModuleLogger logger,
|
IModuleLogger logger,
|
||||||
IText text,
|
IText text,
|
||||||
|
@ -96,6 +99,7 @@ namespace SafeExamBrowser.Browser
|
||||||
this.isMainInstance = isMainInstance;
|
this.isMainInstance = isMainInstance;
|
||||||
this.fileSystemDialog = fileSystemDialog;
|
this.fileSystemDialog = fileSystemDialog;
|
||||||
this.hashAlgorithm = hashAlgorithm;
|
this.hashAlgorithm = hashAlgorithm;
|
||||||
|
this.keyGenerator = keyGenerator;
|
||||||
this.messageBox = messageBox;
|
this.messageBox = messageBox;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
|
@ -130,9 +134,11 @@ namespace SafeExamBrowser.Browser
|
||||||
var downloadHandler = new DownloadHandler(appConfig, downloadLogger, settings, WindowSettings);
|
var downloadHandler = new DownloadHandler(appConfig, downloadLogger, settings, WindowSettings);
|
||||||
var keyboardHandler = new KeyboardHandler();
|
var keyboardHandler = new KeyboardHandler();
|
||||||
var lifeSpanHandler = new LifeSpanHandler();
|
var lifeSpanHandler = new LifeSpanHandler();
|
||||||
|
var renderProcessMessageLogger = logger.CloneFor($"{nameof(RenderProcessMessageHandler)} #{Id}");
|
||||||
|
var renderProcessMessageHandler = new RenderProcessMessageHandler(appConfig, renderProcessMessageLogger, keyGenerator, text);
|
||||||
var requestFilter = new RequestFilter();
|
var requestFilter = new RequestFilter();
|
||||||
var requestLogger = logger.CloneFor($"{nameof(RequestHandler)} #{Id}");
|
var requestLogger = logger.CloneFor($"{nameof(RequestHandler)} #{Id}");
|
||||||
var resourceHandler = new ResourceHandler(appConfig, requestFilter, logger, settings, WindowSettings, text);
|
var resourceHandler = new ResourceHandler(appConfig, requestFilter, keyGenerator, logger, settings, WindowSettings, text);
|
||||||
var requestHandler = new RequestHandler(appConfig, requestFilter, requestLogger, resourceHandler, settings, WindowSettings, text);
|
var requestHandler = new RequestHandler(appConfig, requestFilter, requestLogger, resourceHandler, settings, WindowSettings, text);
|
||||||
|
|
||||||
Icon = new BrowserIconResource();
|
Icon = new BrowserIconResource();
|
||||||
|
@ -162,6 +168,7 @@ namespace SafeExamBrowser.Browser
|
||||||
downloadHandler,
|
downloadHandler,
|
||||||
keyboardHandler,
|
keyboardHandler,
|
||||||
lifeSpanHandler,
|
lifeSpanHandler,
|
||||||
|
renderProcessMessageHandler,
|
||||||
requestHandler,
|
requestHandler,
|
||||||
startUrl);
|
startUrl);
|
||||||
control.AddressChanged += Control_AddressChanged;
|
control.AddressChanged += Control_AddressChanged;
|
||||||
|
|
|
@ -16,13 +16,14 @@ namespace SafeExamBrowser.Browser
|
||||||
{
|
{
|
||||||
internal class BrowserControl : ChromiumWebBrowser, IBrowserControl
|
internal class BrowserControl : ChromiumWebBrowser, IBrowserControl
|
||||||
{
|
{
|
||||||
private IContextMenuHandler contextMenuHandler;
|
private readonly IContextMenuHandler contextMenuHandler;
|
||||||
private IDialogHandler dialogHandler;
|
private readonly IDialogHandler dialogHandler;
|
||||||
private IDisplayHandler displayHandler;
|
private readonly IDisplayHandler displayHandler;
|
||||||
private IDownloadHandler downloadHandler;
|
private readonly IDownloadHandler downloadHandler;
|
||||||
private IKeyboardHandler keyboardHandler;
|
private readonly IKeyboardHandler keyboardHandler;
|
||||||
private ILifeSpanHandler lifeSpanHandler;
|
private readonly ILifeSpanHandler lifeSpanHandler;
|
||||||
private IRequestHandler requestHandler;
|
private readonly IRenderProcessMessageHandler renderProcessMessageHandler;
|
||||||
|
private readonly IRequestHandler requestHandler;
|
||||||
|
|
||||||
private AddressChangedEventHandler addressChanged;
|
private AddressChangedEventHandler addressChanged;
|
||||||
private LoadFailedEventHandler loadFailed;
|
private LoadFailedEventHandler loadFailed;
|
||||||
|
@ -63,6 +64,7 @@ namespace SafeExamBrowser.Browser
|
||||||
IDownloadHandler downloadHandler,
|
IDownloadHandler downloadHandler,
|
||||||
IKeyboardHandler keyboardHandler,
|
IKeyboardHandler keyboardHandler,
|
||||||
ILifeSpanHandler lifeSpanHandler,
|
ILifeSpanHandler lifeSpanHandler,
|
||||||
|
IRenderProcessMessageHandler renderProcessMessageHandler,
|
||||||
IRequestHandler requestHandler,
|
IRequestHandler requestHandler,
|
||||||
string url) : base(url)
|
string url) : base(url)
|
||||||
{
|
{
|
||||||
|
@ -72,6 +74,7 @@ namespace SafeExamBrowser.Browser
|
||||||
this.downloadHandler = downloadHandler;
|
this.downloadHandler = downloadHandler;
|
||||||
this.keyboardHandler = keyboardHandler;
|
this.keyboardHandler = keyboardHandler;
|
||||||
this.lifeSpanHandler = lifeSpanHandler;
|
this.lifeSpanHandler = lifeSpanHandler;
|
||||||
|
this.renderProcessMessageHandler = renderProcessMessageHandler;
|
||||||
this.requestHandler = requestHandler;
|
this.requestHandler = requestHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +100,7 @@ namespace SafeExamBrowser.Browser
|
||||||
KeyboardHandler = keyboardHandler;
|
KeyboardHandler = keyboardHandler;
|
||||||
LifeSpanHandler = lifeSpanHandler;
|
LifeSpanHandler = lifeSpanHandler;
|
||||||
MenuHandler = contextMenuHandler;
|
MenuHandler = contextMenuHandler;
|
||||||
|
RenderProcessMessageHandler = renderProcessMessageHandler;
|
||||||
RequestHandler = requestHandler;
|
RequestHandler = requestHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
8
SafeExamBrowser.Browser/Content/Api.js
Normal file
8
SafeExamBrowser.Browser/Content/Api.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
SafeExamBrowser = {
|
||||||
|
version: 'SEB_Windows_%%_VERSION_%%',
|
||||||
|
security: {
|
||||||
|
browserExamKey: '%%_BEK_%%',
|
||||||
|
configKey: '%%_CK_%%',
|
||||||
|
updateKeys: (callback) => callback()
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,21 +10,45 @@ using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using SafeExamBrowser.I18n.Contracts;
|
using SafeExamBrowser.I18n.Contracts;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Browser.Pages
|
namespace SafeExamBrowser.Browser.Content
|
||||||
{
|
{
|
||||||
internal class HtmlLoader
|
internal class ContentLoader
|
||||||
{
|
{
|
||||||
|
private string api;
|
||||||
private IText text;
|
private IText text;
|
||||||
|
|
||||||
internal HtmlLoader(IText text)
|
internal ContentLoader(IText text)
|
||||||
{
|
{
|
||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal string LoadApi(string browserExamKey, string configurationKey, string version)
|
||||||
|
{
|
||||||
|
if (api == default(string))
|
||||||
|
{
|
||||||
|
var assembly = Assembly.GetAssembly(typeof(ContentLoader));
|
||||||
|
var path = $"{typeof(ContentLoader).Namespace}.Api.js";
|
||||||
|
|
||||||
|
using (var stream = assembly.GetManifestResourceStream(path))
|
||||||
|
using (var reader = new StreamReader(stream))
|
||||||
|
{
|
||||||
|
api = reader.ReadToEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var js = api;
|
||||||
|
|
||||||
|
js = js.Replace("%%_BEK_%%", browserExamKey);
|
||||||
|
js = js.Replace("%%_CK_%%", configurationKey);
|
||||||
|
js = js.Replace("%%_VERSION_%%", version);
|
||||||
|
|
||||||
|
return js;
|
||||||
|
}
|
||||||
|
|
||||||
internal string LoadBlockedContent()
|
internal string LoadBlockedContent()
|
||||||
{
|
{
|
||||||
var assembly = Assembly.GetAssembly(typeof(HtmlLoader));
|
var assembly = Assembly.GetAssembly(typeof(ContentLoader));
|
||||||
var path = $"{typeof(HtmlLoader).Namespace}.BlockedContent.html";
|
var path = $"{typeof(ContentLoader).Namespace}.BlockedContent.html";
|
||||||
|
|
||||||
using (var stream = assembly.GetManifestResourceStream(path))
|
using (var stream = assembly.GetManifestResourceStream(path))
|
||||||
using (var reader = new StreamReader(stream))
|
using (var reader = new StreamReader(stream))
|
||||||
|
@ -39,8 +63,8 @@ namespace SafeExamBrowser.Browser.Pages
|
||||||
|
|
||||||
internal string LoadBlockedPage()
|
internal string LoadBlockedPage()
|
||||||
{
|
{
|
||||||
var assembly = Assembly.GetAssembly(typeof(HtmlLoader));
|
var assembly = Assembly.GetAssembly(typeof(ContentLoader));
|
||||||
var path = $"{typeof(HtmlLoader).Namespace}.BlockedPage.html";
|
var path = $"{typeof(ContentLoader).Namespace}.BlockedPage.html";
|
||||||
|
|
||||||
using (var stream = assembly.GetManifestResourceStream(path))
|
using (var stream = assembly.GetManifestResourceStream(path))
|
||||||
using (var reader = new StreamReader(stream))
|
using (var reader = new StreamReader(stream))
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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 CefSharp;
|
||||||
|
using SafeExamBrowser.Browser.Content;
|
||||||
|
using SafeExamBrowser.Configuration.Contracts;
|
||||||
|
using SafeExamBrowser.Configuration.Contracts.Cryptography;
|
||||||
|
using SafeExamBrowser.I18n.Contracts;
|
||||||
|
using SafeExamBrowser.Logging.Contracts;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Browser.Handlers
|
||||||
|
{
|
||||||
|
internal class RenderProcessMessageHandler : IRenderProcessMessageHandler
|
||||||
|
{
|
||||||
|
private readonly AppConfig appConfig;
|
||||||
|
private readonly ContentLoader contentLoader;
|
||||||
|
private readonly ILogger logger;
|
||||||
|
private readonly IKeyGenerator generator;
|
||||||
|
|
||||||
|
internal RenderProcessMessageHandler(AppConfig appConfig, ILogger logger, IKeyGenerator generator, IText text)
|
||||||
|
{
|
||||||
|
this.appConfig = appConfig;
|
||||||
|
this.contentLoader = new ContentLoader(text);
|
||||||
|
this.logger = logger;
|
||||||
|
this.generator = generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnContextCreated(IWebBrowser webBrowser, IBrowser browser, IFrame frame)
|
||||||
|
{
|
||||||
|
var browserExamKey = generator.CalculateBrowserExamKeyHash(webBrowser.Address);
|
||||||
|
var configurationKey = generator.CalculateConfigurationKeyHash(webBrowser.Address);
|
||||||
|
var api = contentLoader.LoadApi(browserExamKey, configurationKey, appConfig.ProgramBuildVersion);
|
||||||
|
|
||||||
|
frame.ExecuteJavaScriptAsync(api);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnContextReleased(IWebBrowser webBrowser, IBrowser browser, IFrame frame)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnFocusedNodeChanged(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IDomNode node)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnUncaughtException(IWebBrowser webBrowser, IBrowser browser, IFrame frame, JavascriptException exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,16 +12,15 @@ using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Mime;
|
using System.Net.Mime;
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CefSharp;
|
using CefSharp;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using SafeExamBrowser.Browser.Content;
|
||||||
using SafeExamBrowser.Browser.Contracts.Events;
|
using SafeExamBrowser.Browser.Contracts.Events;
|
||||||
using SafeExamBrowser.Browser.Contracts.Filters;
|
using SafeExamBrowser.Browser.Contracts.Filters;
|
||||||
using SafeExamBrowser.Browser.Pages;
|
|
||||||
using SafeExamBrowser.Configuration.Contracts;
|
using SafeExamBrowser.Configuration.Contracts;
|
||||||
|
using SafeExamBrowser.Configuration.Contracts.Cryptography;
|
||||||
using SafeExamBrowser.I18n.Contracts;
|
using SafeExamBrowser.I18n.Contracts;
|
||||||
using SafeExamBrowser.Logging.Contracts;
|
using SafeExamBrowser.Logging.Contracts;
|
||||||
using SafeExamBrowser.Settings.Browser;
|
using SafeExamBrowser.Settings.Browser;
|
||||||
|
@ -33,33 +32,34 @@ namespace SafeExamBrowser.Browser.Handlers
|
||||||
{
|
{
|
||||||
internal class ResourceHandler : CefSharp.Handler.ResourceRequestHandler
|
internal class ResourceHandler : CefSharp.Handler.ResourceRequestHandler
|
||||||
{
|
{
|
||||||
private SHA256Managed algorithm;
|
private readonly AppConfig appConfig;
|
||||||
private AppConfig appConfig;
|
private readonly ContentLoader contentLoader;
|
||||||
private string browserExamKey;
|
private readonly IRequestFilter filter;
|
||||||
|
private readonly IKeyGenerator keyGenerator;
|
||||||
|
private readonly ILogger logger;
|
||||||
|
private readonly BrowserSettings settings;
|
||||||
|
private readonly IText text;
|
||||||
|
private readonly WindowSettings windowSettings;
|
||||||
|
|
||||||
private IResourceHandler contentHandler;
|
private IResourceHandler contentHandler;
|
||||||
private IRequestFilter filter;
|
|
||||||
private HtmlLoader htmlLoader;
|
|
||||||
private ILogger logger;
|
|
||||||
private IResourceHandler pageHandler;
|
private IResourceHandler pageHandler;
|
||||||
private string sessionIdentifier;
|
private string sessionIdentifier;
|
||||||
private BrowserSettings settings;
|
|
||||||
private WindowSettings windowSettings;
|
|
||||||
private IText text;
|
|
||||||
|
|
||||||
internal event SessionIdentifierDetectedEventHandler SessionIdentifierDetected;
|
internal event SessionIdentifierDetectedEventHandler SessionIdentifierDetected;
|
||||||
|
|
||||||
internal ResourceHandler(
|
internal ResourceHandler(
|
||||||
AppConfig appConfig,
|
AppConfig appConfig,
|
||||||
IRequestFilter filter,
|
IRequestFilter filter,
|
||||||
|
IKeyGenerator keyGenerator,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
BrowserSettings settings,
|
BrowserSettings settings,
|
||||||
WindowSettings windowSettings,
|
WindowSettings windowSettings,
|
||||||
IText text)
|
IText text)
|
||||||
{
|
{
|
||||||
this.appConfig = appConfig;
|
this.appConfig = appConfig;
|
||||||
this.algorithm = new SHA256Managed();
|
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.htmlLoader = new HtmlLoader(text);
|
this.contentLoader = new ContentLoader(text);
|
||||||
|
this.keyGenerator = keyGenerator;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
this.windowSettings = windowSettings;
|
this.windowSettings = windowSettings;
|
||||||
|
@ -123,22 +123,15 @@ namespace SafeExamBrowser.Browser.Handlers
|
||||||
if (pageUrl?.Host?.Equals(requestUrl?.Host) == true)
|
if (pageUrl?.Host?.Equals(requestUrl?.Host) == true)
|
||||||
{
|
{
|
||||||
var headers = new NameValueCollection(request.Headers);
|
var headers = new NameValueCollection(request.Headers);
|
||||||
var urlWithoutFragment = request.Url.Split('#')[0];
|
|
||||||
|
|
||||||
if (settings.SendConfigurationKey)
|
if (settings.SendConfigurationKey)
|
||||||
{
|
{
|
||||||
var hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(urlWithoutFragment + settings.ConfigurationKey));
|
headers["X-SafeExamBrowser-ConfigKeyHash"] = keyGenerator.CalculateConfigurationKeyHash(request.Url);
|
||||||
var key = BitConverter.ToString(hash).ToLower().Replace("-", string.Empty);
|
|
||||||
|
|
||||||
headers["X-SafeExamBrowser-ConfigKeyHash"] = key;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.SendExamKey)
|
if (settings.SendBrowserExamKey)
|
||||||
{
|
{
|
||||||
var hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(urlWithoutFragment + (browserExamKey ?? ComputeBrowserExamKey())));
|
headers["X-SafeExamBrowser-RequestHash"] = keyGenerator.CalculateBrowserExamKeyHash(request.Url);
|
||||||
var key = BitConverter.ToString(hash).ToLower().Replace("-", string.Empty);
|
|
||||||
|
|
||||||
headers["X-SafeExamBrowser-RequestHash"] = key;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
request.Headers = headers;
|
request.Headers = headers;
|
||||||
|
@ -169,27 +162,6 @@ namespace SafeExamBrowser.Browser.Handlers
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ComputeBrowserExamKey()
|
|
||||||
{
|
|
||||||
var salt = settings.ExamKeySalt;
|
|
||||||
|
|
||||||
if (salt == default(byte[]))
|
|
||||||
{
|
|
||||||
salt = new byte[0];
|
|
||||||
logger.Warn("The current configuration does not contain a salt value for the browser exam key!");
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var algorithm = new HMACSHA256(salt))
|
|
||||||
{
|
|
||||||
var hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(appConfig.CodeSignatureHash + appConfig.ProgramBuildVersion + settings.ConfigurationKey));
|
|
||||||
var key = BitConverter.ToString(hash).ToLower().Replace("-", string.Empty);
|
|
||||||
|
|
||||||
browserExamKey = key;
|
|
||||||
|
|
||||||
return browserExamKey;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsMailtoUrl(string url)
|
private bool IsMailtoUrl(string url)
|
||||||
{
|
{
|
||||||
return url.StartsWith(Uri.UriSchemeMailto);
|
return url.StartsWith(Uri.UriSchemeMailto);
|
||||||
|
@ -234,12 +206,12 @@ namespace SafeExamBrowser.Browser.Handlers
|
||||||
{
|
{
|
||||||
if (contentHandler == default(IResourceHandler))
|
if (contentHandler == default(IResourceHandler))
|
||||||
{
|
{
|
||||||
contentHandler = CefSharp.ResourceHandler.FromString(htmlLoader.LoadBlockedContent());
|
contentHandler = CefSharp.ResourceHandler.FromString(contentLoader.LoadBlockedContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pageHandler == default(IResourceHandler))
|
if (pageHandler == default(IResourceHandler))
|
||||||
{
|
{
|
||||||
pageHandler = CefSharp.ResourceHandler.FromString(htmlLoader.LoadBlockedPage());
|
pageHandler = CefSharp.ResourceHandler.FromString(contentLoader.LoadBlockedPage());
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (resourceType)
|
switch (resourceType)
|
||||||
|
|
|
@ -104,9 +104,10 @@
|
||||||
<Compile Include="Handlers\DownloadHandler.cs" />
|
<Compile Include="Handlers\DownloadHandler.cs" />
|
||||||
<Compile Include="Handlers\KeyboardHandler.cs" />
|
<Compile Include="Handlers\KeyboardHandler.cs" />
|
||||||
<Compile Include="Handlers\LifeSpanHandler.cs" />
|
<Compile Include="Handlers\LifeSpanHandler.cs" />
|
||||||
|
<Compile Include="Handlers\RenderProcessMessageHandler.cs" />
|
||||||
<Compile Include="Handlers\RequestHandler.cs" />
|
<Compile Include="Handlers\RequestHandler.cs" />
|
||||||
<Compile Include="Handlers\ResourceHandler.cs" />
|
<Compile Include="Handlers\ResourceHandler.cs" />
|
||||||
<Compile Include="Pages\HtmlLoader.cs" />
|
<Compile Include="Content\ContentLoader.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -148,8 +149,8 @@
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Pages\BlockedContent.html" />
|
<EmbeddedResource Include="Content\BlockedContent.html" />
|
||||||
<EmbeddedResource Include="Pages\BlockedPage.html" />
|
<EmbeddedResource Include="Content\BlockedPage.html" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="app.config" />
|
<None Include="app.config" />
|
||||||
|
@ -157,6 +158,9 @@
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Content\Api.js" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
|
|
|
@ -209,8 +209,19 @@ namespace SafeExamBrowser.Client
|
||||||
private IOperation BuildBrowserOperation()
|
private IOperation BuildBrowserOperation()
|
||||||
{
|
{
|
||||||
var fileSystemDialog = BuildFileSystemDialog();
|
var fileSystemDialog = BuildFileSystemDialog();
|
||||||
|
var keyGenerator = new KeyGenerator(context.AppConfig, ModuleLogger(nameof(KeyGenerator)), context.Settings);
|
||||||
var moduleLogger = ModuleLogger(nameof(BrowserApplication));
|
var moduleLogger = ModuleLogger(nameof(BrowserApplication));
|
||||||
var browser = new BrowserApplication(context.AppConfig, context.Settings.Browser, fileSystemDialog, new HashAlgorithm(), nativeMethods, messageBox, moduleLogger, text, uiFactory);
|
var browser = new BrowserApplication(
|
||||||
|
context.AppConfig,
|
||||||
|
context.Settings.Browser,
|
||||||
|
fileSystemDialog,
|
||||||
|
new HashAlgorithm(),
|
||||||
|
keyGenerator,
|
||||||
|
nativeMethods,
|
||||||
|
messageBox,
|
||||||
|
moduleLogger,
|
||||||
|
text,
|
||||||
|
uiFactory);
|
||||||
var operation = new BrowserOperation(actionCenter, context, logger, taskbar, taskview, uiFactory);
|
var operation = new BrowserOperation(actionCenter, context, logger, taskbar, taskview, uiFactory);
|
||||||
|
|
||||||
context.Browser = browser;
|
context.Browser = browser;
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Configuration.Contracts.Cryptography
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides funcionality to calculate keys for integrity checks.
|
||||||
|
/// </summary>
|
||||||
|
public interface IKeyGenerator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the hash value of the browser exam key (BEK) for the given URL.
|
||||||
|
/// </summary>
|
||||||
|
string CalculateBrowserExamKeyHash(string url);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the hash value of the configuration key (CK) for the given URL.
|
||||||
|
/// </summary>
|
||||||
|
string CalculateConfigurationKeyHash(string url);
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,6 +59,7 @@
|
||||||
<Compile Include="Cryptography\EncryptionParameters.cs" />
|
<Compile Include="Cryptography\EncryptionParameters.cs" />
|
||||||
<Compile Include="Cryptography\ICertificateStore.cs" />
|
<Compile Include="Cryptography\ICertificateStore.cs" />
|
||||||
<Compile Include="Cryptography\IHashAlgorithm.cs" />
|
<Compile Include="Cryptography\IHashAlgorithm.cs" />
|
||||||
|
<Compile Include="Cryptography\IKeyGenerator.cs" />
|
||||||
<Compile Include="Cryptography\IPasswordEncryption.cs" />
|
<Compile Include="Cryptography\IPasswordEncryption.cs" />
|
||||||
<Compile Include="Cryptography\IPublicKeyEncryption.cs" />
|
<Compile Include="Cryptography\IPublicKeyEncryption.cs" />
|
||||||
<Compile Include="Cryptography\PasswordParameters.cs" />
|
<Compile Include="Cryptography\PasswordParameters.cs" />
|
||||||
|
|
|
@ -346,7 +346,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping
|
||||||
{
|
{
|
||||||
if (value is byte[] salt)
|
if (value is byte[] salt)
|
||||||
{
|
{
|
||||||
settings.Browser.ExamKeySalt = salt;
|
settings.Browser.BrowserExamKeySalt = salt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,7 +487,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping
|
||||||
if (value is bool send)
|
if (value is bool send)
|
||||||
{
|
{
|
||||||
settings.Browser.SendConfigurationKey = send;
|
settings.Browser.SendConfigurationKey = send;
|
||||||
settings.Browser.SendExamKey = send;
|
settings.Browser.SendBrowserExamKey = send;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
75
SafeExamBrowser.Configuration/Cryptography/KeyGenerator.cs
Normal file
75
SafeExamBrowser.Configuration/Cryptography/KeyGenerator.cs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using SafeExamBrowser.Configuration.Contracts;
|
||||||
|
using SafeExamBrowser.Configuration.Contracts.Cryptography;
|
||||||
|
using SafeExamBrowser.Logging.Contracts;
|
||||||
|
using SafeExamBrowser.Settings;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Configuration.Cryptography
|
||||||
|
{
|
||||||
|
public class KeyGenerator : IKeyGenerator
|
||||||
|
{
|
||||||
|
private readonly SHA256Managed algorithm;
|
||||||
|
private readonly AppConfig appConfig;
|
||||||
|
private readonly ILogger logger;
|
||||||
|
private readonly AppSettings settings;
|
||||||
|
|
||||||
|
private string browserExamKey;
|
||||||
|
|
||||||
|
public KeyGenerator(AppConfig appConfig, ILogger logger, AppSettings settings)
|
||||||
|
{
|
||||||
|
this.algorithm = new SHA256Managed();
|
||||||
|
this.appConfig = appConfig;
|
||||||
|
this.logger = logger;
|
||||||
|
this.settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CalculateBrowserExamKeyHash(string url)
|
||||||
|
{
|
||||||
|
var urlWithoutFragment = url.Split('#')[0];
|
||||||
|
var hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(urlWithoutFragment + (browserExamKey ?? ComputeBrowserExamKey())));
|
||||||
|
var key = BitConverter.ToString(hash).ToLower().Replace("-", string.Empty);
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CalculateConfigurationKeyHash(string url)
|
||||||
|
{
|
||||||
|
var urlWithoutFragment = url.Split('#')[0];
|
||||||
|
var hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(urlWithoutFragment + settings.Browser.ConfigurationKey));
|
||||||
|
var key = BitConverter.ToString(hash).ToLower().Replace("-", string.Empty);
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ComputeBrowserExamKey()
|
||||||
|
{
|
||||||
|
var salt = settings.Browser.BrowserExamKeySalt;
|
||||||
|
|
||||||
|
if (salt == default(byte[]))
|
||||||
|
{
|
||||||
|
salt = new byte[0];
|
||||||
|
logger.Warn("The current configuration does not contain a salt value for the browser exam key!");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var algorithm = new HMACSHA256(salt))
|
||||||
|
{
|
||||||
|
var hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(appConfig.CodeSignatureHash + appConfig.ProgramBuildVersion + settings.Browser.ConfigurationKey));
|
||||||
|
var key = BitConverter.ToString(hash).ToLower().Replace("-", string.Empty);
|
||||||
|
|
||||||
|
browserExamKey = key;
|
||||||
|
|
||||||
|
return browserExamKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -74,6 +74,7 @@
|
||||||
<Compile Include="ConfigurationData\Keys.cs" />
|
<Compile Include="ConfigurationData\Keys.cs" />
|
||||||
<Compile Include="ConfigurationData\DataValues.cs" />
|
<Compile Include="ConfigurationData\DataValues.cs" />
|
||||||
<Compile Include="Cryptography\CertificateStore.cs" />
|
<Compile Include="Cryptography\CertificateStore.cs" />
|
||||||
|
<Compile Include="Cryptography\KeyGenerator.cs" />
|
||||||
<Compile Include="DataCompression\GZipCompressor.cs" />
|
<Compile Include="DataCompression\GZipCompressor.cs" />
|
||||||
<Compile Include="Cryptography\PasswordEncryption.cs" />
|
<Compile Include="Cryptography\PasswordEncryption.cs" />
|
||||||
<Compile Include="Cryptography\PublicKeyEncryption.cs" />
|
<Compile Include="Cryptography\PublicKeyEncryption.cs" />
|
||||||
|
|
|
@ -66,6 +66,11 @@ namespace SafeExamBrowser.Settings.Browser
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AllowUploads { get; set; }
|
public bool AllowUploads { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The salt value for the calculation of the browser exam key which is used for integrity checks with server applications (see also <see cref="SendBrowserExamKey"/>).
|
||||||
|
/// </summary>
|
||||||
|
public byte[] BrowserExamKeySalt { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The configuration key used for integrity checks with server applications (see also <see cref="SendConfigurationKey"/>).
|
/// The configuration key used for integrity checks with server applications (see also <see cref="SendConfigurationKey"/>).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -108,11 +113,6 @@ namespace SafeExamBrowser.Settings.Browser
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableBrowser { get; set; }
|
public bool EnableBrowser { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The salt value for the calculation of the exam key which is used for integrity checks with server applications (see also <see cref="SendExamKey"/>).
|
|
||||||
/// </summary>
|
|
||||||
public byte[] ExamKeySalt { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The settings to be used for the browser request filter.
|
/// The settings to be used for the browser request filter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -169,9 +169,9 @@ namespace SafeExamBrowser.Settings.Browser
|
||||||
public bool SendConfigurationKey { get; set; }
|
public bool SendConfigurationKey { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether the exam key header is sent with every HTTP request (see also <see cref="ExamKeySalt"/>).
|
/// Determines whether the browser exam key header is sent with every HTTP request (see also <see cref="BrowserExamKeySalt"/>).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool SendExamKey { get; set; }
|
public bool SendBrowserExamKey { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The URL with which the main browser window will be loaded.
|
/// The URL with which the main browser window will be loaded.
|
||||||
|
|
Loading…
Reference in a new issue