SEBWIN-608: Finished app signature key implementation.
This commit is contained in:
parent
6c31ce0833
commit
e743d4a564
14 changed files with 136 additions and 65 deletions
|
@ -60,8 +60,8 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
|
|||
var request = new Mock<IRequest>();
|
||||
|
||||
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());
|
||||
keyGenerator.Setup(g => g.CalculateBrowserExamKeyHash(It.IsAny<string>(), It.IsAny<byte[]>(), It.IsAny<string>())).Returns(new Random().Next().ToString());
|
||||
keyGenerator.Setup(g => g.CalculateConfigurationKeyHash(It.IsAny<string>(), It.IsAny<string>())).Returns(new Random().Next().ToString());
|
||||
request.SetupGet(r => r.Headers).Returns(new NameValueCollection());
|
||||
request.SetupGet(r => r.Url).Returns("http://www.host.org");
|
||||
request.SetupSet(r => r.Headers = It.IsAny<NameValueCollection>()).Callback<NameValueCollection>((h) => headers = h);
|
||||
|
|
|
@ -34,8 +34,8 @@ namespace SafeExamBrowser.Browser.Handlers
|
|||
|
||||
public void OnContextCreated(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame)
|
||||
{
|
||||
var browserExamKey = keyGenerator.CalculateBrowserExamKeyHash(frame.Url);
|
||||
var configurationKey = keyGenerator.CalculateConfigurationKeyHash(frame.Url);
|
||||
var browserExamKey = keyGenerator.CalculateBrowserExamKeyHash(settings.ConfigurationKey, settings.BrowserExamKeySalt, frame.Url);
|
||||
var configurationKey = keyGenerator.CalculateConfigurationKeyHash(settings.ConfigurationKey, frame.Url);
|
||||
var api = contentLoader.LoadApi(browserExamKey, configurationKey, appConfig.ProgramBuildVersion);
|
||||
|
||||
frame.ExecuteJavaScriptAsync(api);
|
||||
|
|
|
@ -124,12 +124,12 @@ namespace SafeExamBrowser.Browser.Handlers
|
|||
|
||||
if (settings.SendConfigurationKey)
|
||||
{
|
||||
headers["X-SafeExamBrowser-ConfigKeyHash"] = keyGenerator.CalculateConfigurationKeyHash(request.Url);
|
||||
headers["X-SafeExamBrowser-ConfigKeyHash"] = keyGenerator.CalculateConfigurationKeyHash(settings.ConfigurationKey, request.Url);
|
||||
}
|
||||
|
||||
if (settings.SendBrowserExamKey)
|
||||
{
|
||||
headers["X-SafeExamBrowser-RequestHash"] = keyGenerator.CalculateBrowserExamKeyHash(request.Url);
|
||||
headers["X-SafeExamBrowser-RequestHash"] = keyGenerator.CalculateBrowserExamKeyHash(settings.ConfigurationKey, settings.BrowserExamKeySalt, request.Url);
|
||||
}
|
||||
|
||||
request.Headers = headers;
|
||||
|
|
|
@ -223,7 +223,7 @@ namespace SafeExamBrowser.Client
|
|||
private IOperation BuildBrowserOperation()
|
||||
{
|
||||
var fileSystemDialog = BuildFileSystemDialog();
|
||||
var keyGenerator = new KeyGenerator(context.AppConfig, context.IntegrityModule, ModuleLogger(nameof(KeyGenerator)), context.Settings);
|
||||
var keyGenerator = new KeyGenerator(context.AppConfig, context.IntegrityModule, ModuleLogger(nameof(KeyGenerator)));
|
||||
var moduleLogger = ModuleLogger(nameof(BrowserApplication));
|
||||
var browser = new BrowserApplication(
|
||||
context.AppConfig,
|
||||
|
@ -287,7 +287,8 @@ namespace SafeExamBrowser.Client
|
|||
|
||||
private IOperation BuildServerOperation()
|
||||
{
|
||||
var server = new ServerProxy(context.AppConfig, ModuleLogger(nameof(ServerProxy)), systemInfo, userInfo, powerSupply, networkAdapter);
|
||||
var keyGenerator = new KeyGenerator(context.AppConfig, context.IntegrityModule, ModuleLogger(nameof(KeyGenerator)));
|
||||
var server = new ServerProxy(context.AppConfig, keyGenerator, ModuleLogger(nameof(ServerProxy)), systemInfo, userInfo, powerSupply, networkAdapter);
|
||||
var operation = new ServerOperation(context, logger, server);
|
||||
|
||||
context.Server = server;
|
||||
|
|
|
@ -13,14 +13,19 @@ namespace SafeExamBrowser.Configuration.Contracts.Cryptography
|
|||
/// </summary>
|
||||
public interface IKeyGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Calculates the encrypted value of the app signature key.
|
||||
/// </summary>
|
||||
string CalculateAppSignatureKey(string connectionToken, string salt);
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the hash value of the browser exam key (BEK) for the given URL.
|
||||
/// </summary>
|
||||
string CalculateBrowserExamKeyHash(string url);
|
||||
string CalculateBrowserExamKeyHash(string configurationKey, byte[] salt, string url);
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the hash value of the configuration key (CK) for the given URL.
|
||||
/// </summary>
|
||||
string CalculateConfigurationKeyHash(string url);
|
||||
string CalculateConfigurationKeyHash(string configurationKey, string url);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,11 @@ namespace SafeExamBrowser.Configuration.Contracts.Integrity
|
|||
/// </summary>
|
||||
void ClearSession(string configurationKey, string startUrl);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to calculate the app signature key.
|
||||
/// </summary>
|
||||
bool TryCalculateAppSignatureKey(string connectionToken, string salt, out string appSignatureKey);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to calculate the browser exam key.
|
||||
/// </summary>
|
||||
|
|
|
@ -13,7 +13,6 @@ using SafeExamBrowser.Configuration.Contracts;
|
|||
using SafeExamBrowser.Configuration.Contracts.Cryptography;
|
||||
using SafeExamBrowser.Configuration.Contracts.Integrity;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Settings;
|
||||
|
||||
namespace SafeExamBrowser.Configuration.Cryptography
|
||||
{
|
||||
|
@ -25,42 +24,51 @@ namespace SafeExamBrowser.Configuration.Cryptography
|
|||
private readonly AppConfig appConfig;
|
||||
private readonly IIntegrityModule integrityModule;
|
||||
private readonly ILogger logger;
|
||||
private readonly AppSettings settings;
|
||||
|
||||
private string browserExamKey;
|
||||
|
||||
public KeyGenerator(AppConfig appConfig, IIntegrityModule integrityModule, ILogger logger, AppSettings settings)
|
||||
public KeyGenerator(AppConfig appConfig, IIntegrityModule integrityModule, ILogger logger)
|
||||
{
|
||||
this.algorithm = new SHA256Managed();
|
||||
this.appConfig = appConfig;
|
||||
this.integrityModule = integrityModule;
|
||||
this.logger = logger;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public string CalculateBrowserExamKeyHash(string url)
|
||||
public string CalculateAppSignatureKey(string connectionToken, string salt)
|
||||
{
|
||||
if (integrityModule.TryCalculateAppSignatureKey(connectionToken, salt, out var appSignatureKey))
|
||||
{
|
||||
logger.Debug("Successfully calculated app signature key using integrity module.");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Error("Failed to calculate app signature key using integrity module!");
|
||||
}
|
||||
|
||||
return appSignatureKey;
|
||||
}
|
||||
|
||||
public string CalculateBrowserExamKeyHash(string configurationKey, byte[] salt, string url)
|
||||
{
|
||||
var urlWithoutFragment = url.Split('#')[0];
|
||||
var hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(urlWithoutFragment + (browserExamKey ?? ComputeBrowserExamKey())));
|
||||
var hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(urlWithoutFragment + (browserExamKey ?? ComputeBrowserExamKey(configurationKey, salt))));
|
||||
var key = ToString(hash);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
public string CalculateConfigurationKeyHash(string url)
|
||||
public string CalculateConfigurationKeyHash(string configurationKey, string url)
|
||||
{
|
||||
var urlWithoutFragment = url.Split('#')[0];
|
||||
var hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(urlWithoutFragment + settings.Browser.ConfigurationKey));
|
||||
var hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(urlWithoutFragment + configurationKey));
|
||||
var key = ToString(hash);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
private string ComputeBrowserExamKey()
|
||||
private string ComputeBrowserExamKey(string configurationKey, byte[] salt)
|
||||
{
|
||||
var configurationKey = settings.Browser.ConfigurationKey;
|
||||
var salt = settings.Browser.BrowserExamKeySalt;
|
||||
|
||||
lock (@lock)
|
||||
{
|
||||
if (browserExamKey == default)
|
||||
|
@ -81,11 +89,11 @@ namespace SafeExamBrowser.Configuration.Cryptography
|
|||
|
||||
if (integrityModule.TryCalculateBrowserExamKey(configurationKey, ToString(salt), out browserExamKey))
|
||||
{
|
||||
logger.Debug("Successfully calculated BEK using integrity module.");
|
||||
logger.Debug("Successfully calculated browser exam key using integrity module.");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn("Failed to calculate BEK using integrity module! Falling back to simplified calculation...");
|
||||
logger.Warn("Failed to calculate browser exam key using integrity module! Falling back to simplified calculation...");
|
||||
|
||||
using (var algorithm = new HMACSHA256(salt))
|
||||
{
|
||||
|
|
|
@ -74,6 +74,26 @@ namespace SafeExamBrowser.Configuration.Integrity
|
|||
}
|
||||
}
|
||||
|
||||
public bool TryCalculateAppSignatureKey(string connectionToken, string salt, out string appSignatureKey)
|
||||
{
|
||||
appSignatureKey = default;
|
||||
|
||||
try
|
||||
{
|
||||
appSignatureKey = CalculateAppSignatureKey(connectionToken, salt);
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
logger.Warn("Integrity module is not available!");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Error("Unexpected error while attempting to calculate app signature key!", e);
|
||||
}
|
||||
|
||||
return appSignatureKey != default;
|
||||
}
|
||||
|
||||
public bool TryCalculateBrowserExamKey(string configurationKey, string salt, out string browserExamKey)
|
||||
{
|
||||
browserExamKey = default;
|
||||
|
@ -214,6 +234,10 @@ namespace SafeExamBrowser.Configuration.Integrity
|
|||
return success;
|
||||
}
|
||||
|
||||
[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
private static extern string CalculateAppSignatureKey(string connectionToken, string salt);
|
||||
|
||||
[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
private static extern string CalculateBrowserExamKey(string configurationKey, string salt);
|
||||
|
|
|
@ -80,6 +80,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
server.Setup(s => s.Connect()).Returns(new ServerResponse(true)).Callback(() => connect = ++counter);
|
||||
server.Setup(s => s.Initialize(It.IsAny<ServerSettings>())).Callback(() => initialize = ++counter);
|
||||
server.Setup(s => s.GetConnectionInfo()).Returns(connection).Callback(() => getConnection = ++counter);
|
||||
server.Setup(s => s.SendSelectedExam(It.IsAny<Exam>())).Returns(new ServerResponse(true));
|
||||
server
|
||||
.Setup(s => s.GetAvailableExams(It.IsAny<string>()))
|
||||
.Returns(new ServerResponse<IEnumerable<Exam>>(true, default(IEnumerable<Exam>)))
|
||||
|
@ -106,6 +107,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
server.Verify(s => s.GetAvailableExams(It.IsAny<string>()), Times.Once);
|
||||
server.Verify(s => s.GetConfigurationFor(It.Is<Exam>(e => e == exam)), Times.Once);
|
||||
server.Verify(s => s.GetConnectionInfo(), Times.Once);
|
||||
server.Verify(s => s.SendSelectedExam(It.Is<Exam>(e => e == exam)), Times.Once);
|
||||
|
||||
Assert.AreEqual(1, initialize);
|
||||
Assert.AreEqual(2, connect);
|
||||
|
@ -274,6 +276,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
server.Setup(s => s.GetConnectionInfo()).Returns(connection);
|
||||
server.Setup(s => s.GetAvailableExams(It.IsAny<string>())).Returns(new ServerResponse<IEnumerable<Exam>>(true, new[] { exam }));
|
||||
server.Setup(s => s.GetConfigurationFor(It.IsAny<Exam>())).Returns(new ServerResponse<Uri>(true, new Uri("file:///configuration.seb")));
|
||||
server.Setup(s => s.SendSelectedExam(It.IsAny<Exam>())).Returns(new ServerResponse(true));
|
||||
sut.ActionRequired += (args) => Assert.Fail();
|
||||
|
||||
var result = sut.Perform();
|
||||
|
@ -284,6 +287,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
server.Verify(s => s.GetAvailableExams(It.IsAny<string>()), Times.Once);
|
||||
server.Verify(s => s.GetConfigurationFor(It.Is<Exam>(e => e == exam)), Times.Once);
|
||||
server.Verify(s => s.GetConnectionInfo(), Times.Once);
|
||||
server.Verify(s => s.SendSelectedExam(It.Is<Exam>(e => e == exam)), Times.Once);
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
}
|
||||
|
@ -332,6 +336,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
server.Setup(s => s.Connect()).Returns(new ServerResponse(true)).Callback(() => connect = ++counter);
|
||||
server.Setup(s => s.Initialize(It.IsAny<ServerSettings>())).Callback(() => initialize = ++counter);
|
||||
server.Setup(s => s.GetConnectionInfo()).Returns(connection).Callback(() => getConnection = ++counter);
|
||||
server.Setup(s => s.SendSelectedExam(It.IsAny<Exam>())).Returns(new ServerResponse(true));
|
||||
server
|
||||
.Setup(s => s.GetAvailableExams(It.IsAny<string>()))
|
||||
.Returns(new ServerResponse<IEnumerable<Exam>>(true, default(IEnumerable<Exam>)))
|
||||
|
@ -358,6 +363,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
server.Verify(s => s.GetAvailableExams(It.IsAny<string>()), Times.Once);
|
||||
server.Verify(s => s.GetConfigurationFor(It.Is<Exam>(e => e == exam)), Times.Once);
|
||||
server.Verify(s => s.GetConnectionInfo(), Times.Once);
|
||||
server.Verify(s => s.SendSelectedExam(It.Is<Exam>(e => e == exam)), Times.Once);
|
||||
|
||||
Assert.AreEqual(1, initialize);
|
||||
Assert.AreEqual(2, connect);
|
||||
|
@ -526,6 +532,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
server.Setup(s => s.GetConnectionInfo()).Returns(connection);
|
||||
server.Setup(s => s.GetAvailableExams(It.IsAny<string>())).Returns(new ServerResponse<IEnumerable<Exam>>(true, new[] { exam }));
|
||||
server.Setup(s => s.GetConfigurationFor(It.IsAny<Exam>())).Returns(new ServerResponse<Uri>(true, new Uri("file:///configuration.seb")));
|
||||
server.Setup(s => s.SendSelectedExam(It.IsAny<Exam>())).Returns(new ServerResponse(true));
|
||||
sut.ActionRequired += (args) => Assert.Fail();
|
||||
|
||||
var result = sut.Repeat();
|
||||
|
@ -536,6 +543,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
server.Verify(s => s.GetAvailableExams(It.IsAny<string>()), Times.Once);
|
||||
server.Verify(s => s.GetConfigurationFor(It.Is<Exam>(e => e == exam)), Times.Once);
|
||||
server.Verify(s => s.GetConnectionInfo(), Times.Once);
|
||||
server.Verify(s => s.SendSelectedExam(It.Is<Exam>(e => e == exam)), Times.Once);
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ namespace SafeExamBrowser.Runtime
|
|||
var displayMonitor = new DisplayMonitor(ModuleLogger(nameof(DisplayMonitor)), nativeMethods, systemInfo);
|
||||
var explorerShell = new ExplorerShell(ModuleLogger(nameof(ExplorerShell)), nativeMethods);
|
||||
var fileSystem = new FileSystem();
|
||||
var keyGenerator = new KeyGenerator(appConfig, integrityModule, ModuleLogger(nameof(KeyGenerator)));
|
||||
var messageBox = new MessageBoxFactory(text);
|
||||
var processFactory = new ProcessFactory(ModuleLogger(nameof(ProcessFactory)));
|
||||
var proxyFactory = new ProxyFactory(new ProxyObjectFactory(), ModuleLogger(nameof(ProxyFactory)));
|
||||
|
@ -78,7 +79,7 @@ namespace SafeExamBrowser.Runtime
|
|||
var remoteSessionDetector = new RemoteSessionDetector(ModuleLogger(nameof(RemoteSessionDetector)));
|
||||
var runtimeHost = new RuntimeHost(appConfig.RuntimeAddress, new HostObjectFactory(), ModuleLogger(nameof(RuntimeHost)), FIVE_SECONDS);
|
||||
var runtimeWindow = uiFactory.CreateRuntimeWindow(appConfig);
|
||||
var server = new ServerProxy(appConfig, ModuleLogger(nameof(ServerProxy)), systemInfo, userInfo);
|
||||
var server = new ServerProxy(appConfig, keyGenerator, ModuleLogger(nameof(ServerProxy)), systemInfo, userInfo);
|
||||
var serviceProxy = new ServiceProxy(appConfig.ServiceAddress, new ProxyObjectFactory(), ModuleLogger(nameof(ServiceProxy)), Interlocutor.Runtime);
|
||||
var sessionContext = new SessionContext();
|
||||
var splashScreen = uiFactory.CreateSplashScreen(appConfig);
|
||||
|
|
|
@ -24,9 +24,9 @@ namespace SafeExamBrowser.Server.Requests
|
|||
{
|
||||
}
|
||||
|
||||
internal bool TryExecute(out string message)
|
||||
internal bool TryExecute(string appSignatureKey, out string message)
|
||||
{
|
||||
var content = $"seb_signature_key={"WINDOWS-TEST-ASK-1234"}";
|
||||
var content = $"seb_signature_key={appSignatureKey}";
|
||||
var success = TryExecute(new HttpMethod("PATCH"), api.HandshakeEndpoint, out var response, content, ContentType.URL_ENCODED, Authorization, Token);
|
||||
|
||||
message = response.ToLogString();
|
||||
|
|
|
@ -13,6 +13,7 @@ using SafeExamBrowser.Logging.Contracts;
|
|||
using SafeExamBrowser.Server.Data;
|
||||
using SafeExamBrowser.Settings.Logging;
|
||||
using SafeExamBrowser.Settings.Server;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.Network;
|
||||
|
||||
namespace SafeExamBrowser.Server.Requests
|
||||
{
|
||||
|
@ -27,22 +28,24 @@ namespace SafeExamBrowser.Server.Requests
|
|||
{
|
||||
}
|
||||
|
||||
internal bool TryExecute(string text, int? value = default)
|
||||
internal bool TryExecute(IWirelessNetwork network, out string message)
|
||||
{
|
||||
var json = new JObject
|
||||
{
|
||||
["text"] = text,
|
||||
["text"] = network != default ? $"<wlan> {network.Name}: {network.Status}, {network.SignalStrength}%" : "<wlan> not connected",
|
||||
["timestamp"] = DateTime.Now.ToUnixTimestamp(),
|
||||
["type"] = LogLevel.Info.ToLogType()
|
||||
};
|
||||
|
||||
if (value != default)
|
||||
if (network != default)
|
||||
{
|
||||
json["numericValue"] = value.Value;
|
||||
json["numericValue"] = network.SignalStrength;
|
||||
}
|
||||
|
||||
var success = TryExecute(HttpMethod.Post, api.LogEndpoint, out var response, json.ToString(), ContentType.JSON, Authorization, Token);
|
||||
|
||||
message = response.ToLogString();
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ using SafeExamBrowser.Logging.Contracts;
|
|||
using SafeExamBrowser.Server.Data;
|
||||
using SafeExamBrowser.Settings.Logging;
|
||||
using SafeExamBrowser.Settings.Server;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
|
||||
|
||||
namespace SafeExamBrowser.Server.Requests
|
||||
{
|
||||
|
@ -27,8 +28,24 @@ namespace SafeExamBrowser.Server.Requests
|
|||
{
|
||||
}
|
||||
|
||||
internal bool TryExecute(string text, int value)
|
||||
internal bool TryExecute(IPowerSupplyStatus status, bool previouslyConnected, int previousValue, out string message)
|
||||
{
|
||||
var connected = status.IsOnline;
|
||||
var text = default(string);
|
||||
var value = Convert.ToInt32(status.BatteryCharge * 100);
|
||||
|
||||
if (value != previousValue)
|
||||
{
|
||||
var chargeInfo = $"{status.BatteryChargeStatus} at {value}%";
|
||||
var gridInfo = $"{(connected ? "connected to" : "disconnected from")} the power grid";
|
||||
|
||||
text = $"<battery> {chargeInfo}, {status.BatteryTimeRemaining} remaining, {gridInfo}";
|
||||
}
|
||||
else if (connected != previouslyConnected)
|
||||
{
|
||||
text = $"<battery> Device has been {(connected ? "connected to" : "disconnected from")} power grid";
|
||||
}
|
||||
|
||||
var json = new JObject
|
||||
{
|
||||
["numericValue"] = value,
|
||||
|
@ -37,7 +54,9 @@ namespace SafeExamBrowser.Server.Requests
|
|||
["type"] = LogLevel.Info.ToLogType()
|
||||
};
|
||||
|
||||
var success = TryExecute(HttpMethod.Post, api.LogEndpoint, out _, json.ToString(), ContentType.JSON, Authorization, Token);
|
||||
var success = TryExecute(HttpMethod.Post, api.LogEndpoint, out var response, json.ToString(), ContentType.JSON, Authorization, Token);
|
||||
|
||||
message = response.ToLogString();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ using System.Threading.Tasks;
|
|||
using System.Timers;
|
||||
using Newtonsoft.Json;
|
||||
using SafeExamBrowser.Configuration.Contracts;
|
||||
using SafeExamBrowser.Configuration.Contracts.Cryptography;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Server.Contracts;
|
||||
using SafeExamBrowser.Server.Contracts.Data;
|
||||
|
@ -34,6 +35,7 @@ namespace SafeExamBrowser.Server
|
|||
private readonly AppConfig appConfig;
|
||||
private readonly FileSystem fileSystem;
|
||||
private readonly ConcurrentQueue<string> instructionConfirmations;
|
||||
private readonly IKeyGenerator keyGenerator;
|
||||
private readonly ILogger logger;
|
||||
private readonly ConcurrentQueue<ILogContent> logContent;
|
||||
private readonly Timer logTimer;
|
||||
|
@ -45,16 +47,16 @@ namespace SafeExamBrowser.Server
|
|||
private readonly INetworkAdapter networkAdapter;
|
||||
|
||||
private ApiVersion1 api;
|
||||
private bool connectedToPowergrid;
|
||||
private int currentHandId;
|
||||
private int currentLockScreenId;
|
||||
private int currentPowerSupplyValue;
|
||||
private int currentWlanValue;
|
||||
private string examId;
|
||||
private HttpClient httpClient;
|
||||
private int notificationId;
|
||||
private int pingNumber;
|
||||
private bool powerSupplyConnected;
|
||||
private int powerSupplyValue;
|
||||
private ServerSettings settings;
|
||||
private int wirelessNetworkValue;
|
||||
|
||||
public event ServerEventHandler HandConfirmed;
|
||||
public event ServerEventHandler LockScreenConfirmed;
|
||||
|
@ -65,6 +67,7 @@ namespace SafeExamBrowser.Server
|
|||
|
||||
public ServerProxy(
|
||||
AppConfig appConfig,
|
||||
IKeyGenerator keyGenerator,
|
||||
ILogger logger,
|
||||
ISystemInfo systemInfo,
|
||||
IUserInfo userInfo,
|
||||
|
@ -73,6 +76,7 @@ namespace SafeExamBrowser.Server
|
|||
{
|
||||
this.api = new ApiVersion1();
|
||||
this.appConfig = appConfig;
|
||||
this.keyGenerator = keyGenerator;
|
||||
this.fileSystem = new FileSystem(appConfig, logger);
|
||||
this.instructionConfirmations = new ConcurrentQueue<string>();
|
||||
this.logger = logger;
|
||||
|
@ -291,7 +295,7 @@ namespace SafeExamBrowser.Server
|
|||
if (success && salt != default)
|
||||
{
|
||||
logger.Info("App signature key salt detected, performing key exchange...");
|
||||
success = TrySendAppSignatureKey(out message);
|
||||
success = TrySendAppSignatureKey(salt, out message);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -425,23 +429,22 @@ namespace SafeExamBrowser.Server
|
|||
{
|
||||
var connected = status.IsOnline;
|
||||
var value = Convert.ToInt32(status.BatteryCharge * 100);
|
||||
var text = default(string);
|
||||
|
||||
if (value != currentPowerSupplyValue)
|
||||
if (powerSupplyConnected != connected || powerSupplyValue != value)
|
||||
{
|
||||
var chargeInfo = $"{status.BatteryChargeStatus} at {value}%";
|
||||
var gridInfo = $"{(status.IsOnline ? "connected to" : "disconnected from")} the power grid";
|
||||
var request = new PowerSupplyRequest(api, httpClient, logger, parser, settings);
|
||||
var success = request.TryExecute(status, powerSupplyConnected, powerSupplyValue, out var message);
|
||||
|
||||
currentPowerSupplyValue = value;
|
||||
text = $"<battery> {chargeInfo}, {status.BatteryTimeRemaining} remaining, {gridInfo}";
|
||||
if (success)
|
||||
{
|
||||
powerSupplyConnected = connected;
|
||||
powerSupplyValue = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn($"Failed to send power supply status! {message}");
|
||||
}
|
||||
}
|
||||
else if (connected != connectedToPowergrid)
|
||||
{
|
||||
connectedToPowergrid = connected;
|
||||
text = $"<battery> Device has been {(connected ? "connected to" : "disconnected from")} power grid";
|
||||
}
|
||||
|
||||
new PowerSupplyRequest(api, httpClient, logger, parser, settings).TryExecute(text, value);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -457,23 +460,19 @@ namespace SafeExamBrowser.Server
|
|||
{
|
||||
var network = networkAdapter.GetWirelessNetworks().FirstOrDefault(n => n.Status == ConnectionStatus.Connected);
|
||||
|
||||
if (network?.SignalStrength != currentWlanValue)
|
||||
if (network?.SignalStrength != wirelessNetworkValue)
|
||||
{
|
||||
var text = default(string);
|
||||
var value = default(int?);
|
||||
var request = new NetworkAdapterRequest(api, httpClient, logger, parser, settings);
|
||||
var success = request.TryExecute(network, out var message);
|
||||
|
||||
if (network != default(IWirelessNetwork))
|
||||
if (success)
|
||||
{
|
||||
text = $"<wlan> {network.Name}: {network.Status}, {network.SignalStrength}%";
|
||||
value = network.SignalStrength;
|
||||
wirelessNetworkValue = network?.SignalStrength ?? NOT_CONNECTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
text = "<wlan> not connected";
|
||||
logger.Warn($"Failed to send wireless status! {message}");
|
||||
}
|
||||
|
||||
new NetworkAdapterRequest(api, httpClient, logger, parser, settings).TryExecute(text, value);
|
||||
currentWlanValue = network?.SignalStrength ?? NOT_CONNECTED;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -507,13 +506,11 @@ namespace SafeExamBrowser.Server
|
|||
}
|
||||
}
|
||||
|
||||
private bool TrySendAppSignatureKey(out string message)
|
||||
private bool TrySendAppSignatureKey(string salt, out string message)
|
||||
{
|
||||
// TODO:
|
||||
// keyGenerator.CalculateAppSignatureKey(configurationKey, server.AppSignatureKeySalt)
|
||||
|
||||
var appSignatureKey = keyGenerator.CalculateAppSignatureKey(BaseRequest.ConnectionToken, salt);
|
||||
var request = new AppSignatureKeyRequest(api, httpClient, logger, parser, settings);
|
||||
var success = request.TryExecute(out message);
|
||||
var success = request.TryExecute(appSignatureKey, out message);
|
||||
|
||||
if (success)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue