Restore SEBPatch

This commit is contained in:
2025-06-01 11:44:20 +02:00
commit 8c656e3137
1297 changed files with 142172 additions and 0 deletions

View File

@@ -0,0 +1,166 @@
/*
* Copyright (c) 2024 ETH Zürich, IT Services
*
* 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.Collections.Generic;
using SafeExamBrowser.Core.Contracts.OperationModel;
using SafeExamBrowser.Lockdown.Contracts;
using SafeExamBrowser.Logging.Contracts;
namespace SafeExamBrowser.Service.Operations
{
internal class LockdownOperation : SessionOperation
{
private readonly IFeatureConfigurationBackup backup;
private readonly IFeatureConfigurationFactory factory;
private readonly IFeatureConfigurationMonitor monitor;
private readonly ILogger logger;
private Guid groupId;
public LockdownOperation(
IFeatureConfigurationBackup backup,
IFeatureConfigurationFactory factory,
IFeatureConfigurationMonitor monitor,
ILogger logger,
SessionContext sessionContext) : base(sessionContext)
{
this.backup = backup;
this.factory = factory;
this.monitor = monitor;
this.logger = logger;
}
public override OperationResult Perform()
{
groupId = Guid.NewGuid();
var success = true;
var sid = Context.Configuration.UserSid;
var userName = Context.Configuration.UserName;
var configurations = new List<(IFeatureConfiguration, bool)>
{
(factory.CreateChangePasswordConfiguration(groupId, sid, userName), Context.Configuration.Settings.Service.DisablePasswordChange),
(factory.CreateChromeNotificationConfiguration(groupId, sid, userName), Context.Configuration.Settings.Service.DisableChromeNotifications),
(factory.CreateEaseOfAccessConfiguration(groupId), Context.Configuration.Settings.Service.DisableEaseOfAccessOptions),
(factory.CreateFindPrinterConfiguration(groupId, sid, userName), Context.Configuration.Settings.Service.DisableFindPrinter),
(factory.CreateLockWorkstationConfiguration(groupId, sid, userName), Context.Configuration.Settings.Service.DisableUserLock),
(factory.CreateMachinePowerOptionsConfiguration(groupId), Context.Configuration.Settings.Service.DisablePowerOptions),
(factory.CreateNetworkOptionsConfiguration(groupId), Context.Configuration.Settings.Service.DisableNetworkOptions),
(factory.CreateRemoteConnectionConfiguration(groupId), Context.Configuration.Settings.Service.DisableRemoteConnections),
(factory.CreateSignoutConfiguration(groupId, sid, userName), Context.Configuration.Settings.Service.DisableSignout),
(factory.CreateSwitchUserConfiguration(groupId), Context.Configuration.Settings.Service.DisableUserSwitch),
(factory.CreateTaskManagerConfiguration(groupId, sid, userName), Context.Configuration.Settings.Service.DisableTaskManager),
(factory.CreateUserPowerOptionsConfiguration(groupId, sid, userName), Context.Configuration.Settings.Service.DisablePowerOptions),
(factory.CreateWindowsUpdateConfiguration(groupId), Context.Configuration.Settings.Service.DisableWindowsUpdate)
};
if (Context.Configuration.Settings.Service.SetVmwareConfiguration)
{
configurations.Add((factory.CreateVmwareOverlayConfiguration(groupId, sid, userName), Context.Configuration.Settings.Service.DisableVmwareOverlay));
}
logger.Info($"Attempting to perform lockdown (feature configuration group: {groupId})...");
foreach (var (configuration, disable) in configurations)
{
success &= TrySet(configuration, disable);
if (!success)
{
break;
}
}
if (success)
{
monitor.Start();
logger.Info("Lockdown successful.");
}
else
{
logger.Error("Lockdown was not successful!");
}
return success ? OperationResult.Success : OperationResult.Failed;
}
public override OperationResult Revert()
{
logger.Info($"Attempting to revert lockdown (feature configuration group: {groupId})...");
var configurations = backup.GetBy(groupId);
var success = true;
monitor.Reset();
foreach (var configuration in configurations)
{
success &= TryRestore(configuration);
}
if (success)
{
logger.Info("Lockdown reversion successful.");
}
else
{
logger.Warn("Lockdown reversion was not successful!");
}
return success ? OperationResult.Success : OperationResult.Failed;
}
private bool TryRestore(IFeatureConfiguration configuration)
{
var success = configuration.Restore();
if (success)
{
backup.Delete(configuration);
}
else
{
logger.Error($"Failed to restore {configuration}!");
}
return success;
}
private bool TrySet(IFeatureConfiguration configuration, bool disable)
{
var success = false;
var status = FeatureConfigurationStatus.Undefined;
configuration.Initialize();
backup.Save(configuration);
if (disable)
{
success = configuration.DisableFeature();
status = FeatureConfigurationStatus.Disabled;
}
else
{
success = configuration.EnableFeature();
status = FeatureConfigurationStatus.Enabled;
}
if (success)
{
monitor.Observe(configuration, status);
}
else
{
logger.Error($"Failed to configure {configuration}!");
}
return success;
}
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2024 ETH Zürich, IT Services
*
* 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 SafeExamBrowser.Core.Contracts.OperationModel;
using SafeExamBrowser.Core.Contracts.OperationModel.Events;
using SafeExamBrowser.Lockdown.Contracts;
using SafeExamBrowser.Logging.Contracts;
namespace SafeExamBrowser.Service.Operations
{
internal class RestoreOperation : IOperation
{
private readonly IFeatureConfigurationBackup backup;
private ILogger logger;
private readonly SessionContext sessionContext;
public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
public event StatusChangedEventHandler StatusChanged { add { } remove { } }
public RestoreOperation(IFeatureConfigurationBackup backup, ILogger logger, SessionContext sessionContext)
{
this.backup = backup;
this.logger = logger;
this.sessionContext = sessionContext;
}
public OperationResult Perform()
{
logger.Info("Starting auto-restore mechanism...");
sessionContext.AutoRestoreMechanism.Start();
return OperationResult.Success;
}
public OperationResult Revert()
{
logger.Info("Stopping auto-restore mechanism...");
sessionContext.AutoRestoreMechanism.Stop();
return OperationResult.Success;
}
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2024 ETH Zürich, IT Services
*
* 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 SafeExamBrowser.Core.Contracts.OperationModel;
using SafeExamBrowser.Core.Contracts.OperationModel.Events;
using SafeExamBrowser.Logging.Contracts;
namespace SafeExamBrowser.Service.Operations
{
internal class ServiceEventCleanupOperation : IOperation
{
private ILogger logger;
private SessionContext sessionContext;
public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
public event StatusChangedEventHandler StatusChanged { add { } remove { } }
public ServiceEventCleanupOperation(ILogger logger, SessionContext sessionContext)
{
this.logger = logger;
this.sessionContext = sessionContext;
}
public OperationResult Perform()
{
return OperationResult.Success;
}
public OperationResult Revert()
{
if (sessionContext.ServiceEvent != null)
{
logger.Info("Closing service event...");
sessionContext.ServiceEvent.Close();
logger.Info("Service event successfully closed.");
}
return OperationResult.Success;
}
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2024 ETH Zürich, IT Services
*
* 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 SafeExamBrowser.Core.Contracts.OperationModel;
using SafeExamBrowser.Logging.Contracts;
namespace SafeExamBrowser.Service.Operations
{
internal class SessionActivationOperation : SessionOperation
{
private ILogger logger;
public SessionActivationOperation(ILogger logger, SessionContext sessionContext) : base(sessionContext)
{
this.logger = logger;
}
public override OperationResult Perform()
{
var success = Context.ServiceEvent.Set();
if (success)
{
logger.Info("Successfully informed runtime about new session activation.");
}
else
{
logger.Error("Failed to inform runtime about new session activation!");
}
Context.IsRunning = success;
return success ? OperationResult.Success : OperationResult.Failed;
}
public override OperationResult Revert()
{
return OperationResult.Success;
}
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 2024 ETH Zürich, IT Services
*
* 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.Threading;
using SafeExamBrowser.Core.Contracts.OperationModel;
using SafeExamBrowser.Logging.Contracts;
namespace SafeExamBrowser.Service.Operations
{
internal class SessionInitializationOperation : SessionOperation
{
private ILogger logger;
private Func<string, EventWaitHandle> serviceEventFactory;
public SessionInitializationOperation(ILogger logger, Func<string, EventWaitHandle> serviceEventFactory, SessionContext sessionContext) : base(sessionContext)
{
this.logger = logger;
this.serviceEventFactory = serviceEventFactory;
}
public override OperationResult Perform()
{
logger.Info("Initializing new session...");
logger.Info($" -> Client-ID: {Context.Configuration.AppConfig.ClientId}");
logger.Info($" -> Runtime-ID: {Context.Configuration.AppConfig.RuntimeId}");
logger.Info($" -> Session-ID: {Context.Configuration.SessionId}");
logger.Info("Stopping auto-restore mechanism...");
Context.AutoRestoreMechanism.Stop();
InitializeServiceEvent();
return OperationResult.Success;
}
public override OperationResult Revert()
{
var success = true;
var wasRunning = Context.IsRunning;
logger.Info("Starting auto-restore mechanism...");
Context.AutoRestoreMechanism.Start();
logger.Info("Clearing session data...");
Context.Configuration = null;
Context.IsRunning = false;
if (Context.ServiceEvent != null && wasRunning)
{
success = Context.ServiceEvent.Set();
if (success)
{
logger.Info("Successfully informed runtime about session termination.");
}
else
{
logger.Error("Failed to inform runtime about session termination!");
}
}
return success ? OperationResult.Success : OperationResult.Failed;
}
private void InitializeServiceEvent()
{
if (Context.ServiceEvent != null)
{
logger.Info("Closing service event from previous session...");
Context.ServiceEvent.Close();
logger.Info("Service event successfully closed.");
}
logger.Info("Attempting to create new service event...");
Context.ServiceEvent = serviceEventFactory.Invoke(Context.Configuration.AppConfig.ServiceEventName);
logger.Info("Service event successfully created.");
}
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2024 ETH Zürich, IT Services
*
* 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 SafeExamBrowser.Core.Contracts.OperationModel;
using SafeExamBrowser.Core.Contracts.OperationModel.Events;
namespace SafeExamBrowser.Service.Operations
{
/// <summary>
/// The base implementation to be used for all operations in the session operation sequence.
/// </summary>
internal abstract class SessionOperation : IOperation
{
protected SessionContext Context { get; private set; }
public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
public event StatusChangedEventHandler StatusChanged { add { } remove { } }
public SessionOperation(SessionContext sessionContext)
{
Context = sessionContext;
}
public abstract OperationResult Perform();
public abstract OperationResult Revert();
}
}