diff --git a/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs b/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs
index bafa5a09..368608b1 100644
--- a/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs
+++ b/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs
@@ -106,12 +106,16 @@ namespace SafeExamBrowser.Browser.Handlers
{
var headers = new NameValueCollection(request.Headers);
var urlWithoutFragment = request.Url.Split('#')[0];
- var hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(urlWithoutFragment + settings.HashValue));
- var configurationKey = BitConverter.ToString(hash).ToLower().Replace("-", string.Empty);
+ var configurationBytes = algorithm.ComputeHash(Encoding.UTF8.GetBytes(urlWithoutFragment + settings.HashValue));
+ var configurationKey = BitConverter.ToString(configurationBytes).ToLower().Replace("-", string.Empty);
+ var browserExamBytes = algorithm.ComputeHash(Encoding.UTF8.GetBytes(appConfig.CodeSignatureHash + appConfig.ProgramBuildVersion + configurationKey));
+ var browserExamKey = BitConverter.ToString(browserExamBytes).ToLower().Replace("-", string.Empty);
+ var requestHashBytes = algorithm.ComputeHash(Encoding.UTF8.GetBytes(urlWithoutFragment + browserExamKey));
+ var requestHashKey = BitConverter.ToString(requestHashBytes).ToLower().Replace("-", string.Empty);
- // TODO: Implement Browser Exam Key calculation.
- // headers["X-SafeExamBrowser-RequestHash"] = ...;
headers["X-SafeExamBrowser-ConfigKeyHash"] = configurationKey;
+ headers["X-SafeExamBrowser-RequestHash"] = requestHashKey;
+
request.Headers = headers;
}
diff --git a/SafeExamBrowser.Configuration.Contracts/AppConfig.cs b/SafeExamBrowser.Configuration.Contracts/AppConfig.cs
index 322527f8..f7d68a57 100644
--- a/SafeExamBrowser.Configuration.Contracts/AppConfig.cs
+++ b/SafeExamBrowser.Configuration.Contracts/AppConfig.cs
@@ -86,6 +86,11 @@ namespace SafeExamBrowser.Configuration.Contracts
///
public string ClientLogFilePath { get; set; }
+ ///
+ /// The hash value of the certificate used to sign the application binaries, or null if the binaries are unsigned.
+ ///
+ public string CodeSignatureHash { get; set; }
+
///
/// The file extension of configuration files for the application (including the period).
///
diff --git a/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs b/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs
index 4fe3e5c1..96283c33 100644
--- a/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs
+++ b/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs
@@ -39,8 +39,6 @@ namespace SafeExamBrowser.Configuration.UnitTests
[TestInitialize]
public void Initialize()
{
- var executablePath = Assembly.GetExecutingAssembly().Location;
-
binaryParser = new Mock();
binarySerializer = new Mock();
certificateStore = new Mock();
@@ -56,7 +54,7 @@ namespace SafeExamBrowser.Configuration.UnitTests
fileSaver.Setup(f => f.CanSave(It.IsAny())).Returns(u => u.IsFile);
networkLoader.Setup(n => n.CanLoad(It.IsAny())).Returns(u => u.Scheme.Equals("http") || u.Scheme.Equals("seb"));
- sut = new ConfigurationRepository(certificateStore.Object, hashAlgorithm.Object, logger.Object, executablePath, string.Empty, string.Empty, string.Empty, string.Empty);
+ sut = new ConfigurationRepository(certificateStore.Object, hashAlgorithm.Object, logger.Object);
sut.InitializeAppConfig();
}
diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs
index 07a3227d..6d878422 100644
--- a/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs
+++ b/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs
@@ -7,7 +7,10 @@
*/
using System;
+using System.Diagnostics;
using System.IO;
+using System.Linq;
+using System.Reflection;
using SafeExamBrowser.Configuration.Contracts;
using SafeExamBrowser.Settings;
using SafeExamBrowser.Settings.Browser;
@@ -22,27 +25,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
internal class DataValues
{
private const string DEFAULT_CONFIGURATION_NAME = "SebClientSettings.seb";
-
private AppConfig appConfig;
- private string executablePath;
- private string programBuild;
- private string programCopyright;
- private string programTitle;
- private string programVersion;
-
- internal DataValues(
- string executablePath,
- string programBuild,
- string programCopyright,
- string programTitle,
- string programVersion)
- {
- this.executablePath = executablePath ?? string.Empty;
- this.programBuild = programBuild ?? string.Empty;
- this.programCopyright = programCopyright ?? string.Empty;
- this.programTitle = programTitle ?? string.Empty;
- this.programVersion = programVersion ?? string.Empty;
- }
internal string GetAppDataFilePath()
{
@@ -51,6 +34,12 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
internal AppConfig InitializeAppConfig()
{
+ var executable = Assembly.GetExecutingAssembly();
+ var certificate = executable.Modules.First().GetSignerCertificate();
+ var programBuild = FileVersionInfo.GetVersionInfo(executable.Location).FileVersion;
+ var programCopyright = executable.GetCustomAttribute().Copyright;
+ var programTitle = executable.GetCustomAttribute().Title;
+ var programVersion = executable.GetCustomAttribute().InformationalVersion;
var appDataLocalFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), nameof(SafeExamBrowser));
var appDataRoamingFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(SafeExamBrowser));
var programDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), nameof(SafeExamBrowser));
@@ -65,8 +54,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
appConfig.BrowserLogFilePath = Path.Combine(logFolder, $"{logFilePrefix}_Browser.log");
appConfig.ClientId = Guid.NewGuid();
appConfig.ClientAddress = $"{AppConfig.BASE_ADDRESS}/client/{Guid.NewGuid()}";
- appConfig.ClientExecutablePath = Path.Combine(Path.GetDirectoryName(executablePath), $"{nameof(SafeExamBrowser)}.Client.exe");
+ appConfig.ClientExecutablePath = Path.Combine(Path.GetDirectoryName(executable.Location), $"{nameof(SafeExamBrowser)}.Client.exe");
appConfig.ClientLogFilePath = Path.Combine(logFolder, $"{logFilePrefix}_Client.log");
+ appConfig.CodeSignatureHash = certificate?.GetCertHashString();
appConfig.ConfigurationFileExtension = ".seb";
appConfig.ConfigurationFileMimeType = "application/seb";
appConfig.ProgramBuildVersion = programBuild;
diff --git a/SafeExamBrowser.Configuration/ConfigurationRepository.cs b/SafeExamBrowser.Configuration/ConfigurationRepository.cs
index 7a6e31a6..f12f7659 100644
--- a/SafeExamBrowser.Configuration/ConfigurationRepository.cs
+++ b/SafeExamBrowser.Configuration/ConfigurationRepository.cs
@@ -33,15 +33,7 @@ namespace SafeExamBrowser.Configuration
private IList resourceLoaders;
private IList resourceSavers;
- public ConfigurationRepository(
- ICertificateStore certificateStore,
- IHashAlgorithm hashAlgorithm,
- IModuleLogger logger,
- string executablePath,
- string programBuild,
- string programCopyright,
- string programTitle,
- string programVersion)
+ public ConfigurationRepository(ICertificateStore certificateStore, IHashAlgorithm hashAlgorithm, IModuleLogger logger)
{
this.certificateStore = certificateStore;
this.hashAlgorithm = hashAlgorithm;
@@ -51,7 +43,7 @@ namespace SafeExamBrowser.Configuration
dataSerializers = new List();
dataMapper = new DataMapper();
dataProcessor = new DataProcessor();
- dataValues = new DataValues(executablePath, programBuild, programCopyright, programTitle, programVersion);
+ dataValues = new DataValues();
resourceLoaders = new List();
resourceSavers = new List();
}
diff --git a/SafeExamBrowser.Runtime/CompositionRoot.cs b/SafeExamBrowser.Runtime/CompositionRoot.cs
index aa432ca4..7a1be963 100644
--- a/SafeExamBrowser.Runtime/CompositionRoot.cs
+++ b/SafeExamBrowser.Runtime/CompositionRoot.cs
@@ -8,7 +8,6 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.IO;
using System.Reflection;
using SafeExamBrowser.Communication.Contracts;
@@ -129,12 +128,6 @@ namespace SafeExamBrowser.Runtime
private void InitializeConfiguration()
{
- var executable = Assembly.GetExecutingAssembly();
- var programBuild = FileVersionInfo.GetVersionInfo(executable.Location).FileVersion;
- var programCopyright = executable.GetCustomAttribute().Copyright;
- var programTitle = executable.GetCustomAttribute().Title;
- var programVersion = executable.GetCustomAttribute().InformationalVersion;
-
var certificateStore = new CertificateStore(ModuleLogger(nameof(CertificateStore)));
var compressor = new GZipCompressor(ModuleLogger(nameof(GZipCompressor)));
var passwordEncryption = new PasswordEncryption(ModuleLogger(nameof(PasswordEncryption)));
@@ -144,15 +137,7 @@ namespace SafeExamBrowser.Runtime
var xmlParser = new XmlParser(compressor, ModuleLogger(nameof(XmlParser)));
var xmlSerializer = new XmlSerializer(ModuleLogger(nameof(XmlSerializer)));
- configuration = new ConfigurationRepository(
- certificateStore,
- new HashAlgorithm(),
- repositoryLogger,
- executable.Location,
- programBuild,
- programCopyright,
- programTitle,
- programVersion);
+ configuration = new ConfigurationRepository(certificateStore, new HashAlgorithm(), repositoryLogger);
appConfig = configuration.InitializeAppConfig();
configuration.Register(new BinaryParser(