SEBWIN-320: Implemented configuration reset functionality for reset utility.
This commit is contained in:
parent
2754cdcc56
commit
68d487dd46
27 changed files with 390 additions and 17 deletions
|
@ -45,6 +45,11 @@ namespace SafeExamBrowser.Contracts.Lockdown
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Initialize();
|
void Initialize();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resets the feature to its default configuration. Returns <c>true</c> if successful, otherwise <c>false</c>.
|
||||||
|
/// </summary>
|
||||||
|
bool Reset();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Restores the feature to its previous configuration (i.e. before it was enabled or disabled). Returns <c>true</c> if successful,
|
/// Restores the feature to its previous configuration (i.e. before it was enabled or disabled). Returns <c>true</c> if successful,
|
||||||
/// otherwise <c>false</c>.
|
/// otherwise <c>false</c>.
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Contracts.Lockdown
|
namespace SafeExamBrowser.Contracts.Lockdown
|
||||||
{
|
{
|
||||||
|
@ -15,6 +16,11 @@ namespace SafeExamBrowser.Contracts.Lockdown
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IFeatureConfigurationFactory
|
public interface IFeatureConfigurationFactory
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates all feature configurations.
|
||||||
|
/// </summary>
|
||||||
|
IList<IFeatureConfiguration> CreateAll(Guid groupId, string sid, string userName);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates an <see cref="IFeatureConfiguration"/> to control the option to change the password of a user account via the security screen.
|
/// Creates an <see cref="IFeatureConfiguration"/> to control the option to change the password of a user account via the security screen.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -22,5 +22,10 @@ namespace SafeExamBrowser.Contracts.SystemComponents
|
||||||
/// Retrieves the security identifier of the currently logged in user.
|
/// Retrieves the security identifier of the currently logged in user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string GetUserSid();
|
string GetUserSid();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to retrieve the security identifier for the specified user name. Returns <c>true</c> if successful, otherwise <c>false</c>.
|
||||||
|
/// </summary>
|
||||||
|
bool TryGetSidForUser(string userName, out string sid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,11 @@ namespace SafeExamBrowser.Lockdown.UnitTests
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Reset()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
public bool Restore()
|
public bool Restore()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using SafeExamBrowser.Contracts.Lockdown;
|
using SafeExamBrowser.Contracts.Lockdown;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
using SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.MachineHive;
|
using SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.MachineHive;
|
||||||
|
@ -24,6 +25,25 @@ namespace SafeExamBrowser.Lockdown
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IList<IFeatureConfiguration> CreateAll(Guid groupId, string sid, string userName)
|
||||||
|
{
|
||||||
|
return new List<IFeatureConfiguration>
|
||||||
|
{
|
||||||
|
CreateChangePasswordConfiguration(groupId, sid, userName),
|
||||||
|
CreateChromeNotificationConfiguration(groupId, sid, userName),
|
||||||
|
CreateEaseOfAccessConfiguration(groupId),
|
||||||
|
CreateLockWorkstationConfiguration(groupId, sid, userName),
|
||||||
|
CreateNetworkOptionsConfiguration(groupId),
|
||||||
|
CreatePowerOptionsConfiguration(groupId),
|
||||||
|
CreateRemoteConnectionConfiguration(groupId),
|
||||||
|
CreateSignoutConfiguration(groupId, sid, userName),
|
||||||
|
CreateSwitchUserConfiguration(groupId),
|
||||||
|
CreateTaskManagerConfiguration(groupId, sid, userName),
|
||||||
|
CreateVmwareOverlayConfiguration(groupId, sid, userName),
|
||||||
|
CreateWindowsUpdateConfiguration(groupId)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public IFeatureConfiguration CreateChangePasswordConfiguration(Guid groupId, string sid, string userName)
|
public IFeatureConfiguration CreateChangePasswordConfiguration(Guid groupId, string sid, string userName)
|
||||||
{
|
{
|
||||||
return new ChangePasswordConfiguration(groupId, logger.CloneFor(nameof(ChangePasswordConfiguration)), sid, userName);
|
return new ChangePasswordConfiguration(groupId, logger.CloneFor(nameof(ChangePasswordConfiguration)), sid, userName);
|
||||||
|
|
|
@ -33,6 +33,7 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations
|
||||||
public abstract bool EnableFeature();
|
public abstract bool EnableFeature();
|
||||||
public abstract FeatureConfigurationStatus GetStatus();
|
public abstract FeatureConfigurationStatus GetStatus();
|
||||||
public abstract void Initialize();
|
public abstract void Initialize();
|
||||||
|
public abstract bool Reset();
|
||||||
public abstract bool Restore();
|
public abstract bool Restore();
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|
|
@ -23,5 +23,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.
|
||||||
public EaseOfAccessConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
|
public EaseOfAccessConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Reset()
|
||||||
|
{
|
||||||
|
return DeleteConfiguration();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,5 +23,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.
|
||||||
public NetworkOptionsConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
|
public NetworkOptionsConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Reset()
|
||||||
|
{
|
||||||
|
return DeleteConfiguration();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,5 +23,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.
|
||||||
public PowerOptionsConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
|
public PowerOptionsConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Reset()
|
||||||
|
{
|
||||||
|
return DeleteConfiguration();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,13 @@ using SafeExamBrowser.Contracts.Logging;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.MachineHive
|
namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.MachineHive
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies whether Remote Desktop connections are enabled.
|
||||||
|
///
|
||||||
|
/// See https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-terminalservices-localsessionmanager-fdenytsconnections:
|
||||||
|
/// • 0 = Specifies that remote desktop connections are enabled.
|
||||||
|
/// • 1 = Specifies that remote desktop connections are denied. This is the default value.
|
||||||
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
internal class RemoteConnectionConfiguration : MachineHiveConfiguration
|
internal class RemoteConnectionConfiguration : MachineHiveConfiguration
|
||||||
{
|
{
|
||||||
|
@ -23,5 +30,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.
|
||||||
public RemoteConnectionConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
|
public RemoteConnectionConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Reset()
|
||||||
|
{
|
||||||
|
return DisableFeature();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,5 +23,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.
|
||||||
public SwitchUserConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
|
public SwitchUserConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Reset()
|
||||||
|
{
|
||||||
|
return DeleteConfiguration();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations
|
||||||
itemsToRestore = new List<RegistryDataItem>();
|
itemsToRestore = new List<RegistryDataItem>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract bool IsHiveAvailable(RegistryDataItem item);
|
||||||
|
|
||||||
public override bool DisableFeature()
|
public override bool DisableFeature()
|
||||||
{
|
{
|
||||||
var success = true;
|
var success = true;
|
||||||
|
@ -66,7 +68,7 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.Warn("Failed to enabled feature!");
|
logger.Warn("Failed to enable feature!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
@ -148,7 +150,26 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract bool IsHiveAvailable(RegistryDataItem item);
|
protected bool DeleteConfiguration()
|
||||||
|
{
|
||||||
|
var success = true;
|
||||||
|
|
||||||
|
foreach (var item in Items)
|
||||||
|
{
|
||||||
|
success &= TryDelete(new RegistryDataItem { Key = item.Key, Value = item.Value });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
logger.Info("Successfully deleted feature configuration.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.Warn("Failed to delete feature configuration!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
private RegistryDataItem ReadItem(string key, string value)
|
private RegistryDataItem ReadItem(string key, string value)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,5 +23,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.
|
||||||
public ChangePasswordConfiguration(Guid groupId, ILogger logger, string sid, string userName) : base(groupId, logger, sid, userName)
|
public ChangePasswordConfiguration(Guid groupId, ILogger logger, string sid, string userName) : base(groupId, logger, sid, userName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Reset()
|
||||||
|
{
|
||||||
|
return DeleteConfiguration();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,9 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.
|
||||||
/// IMPORTANT: This registry configuration only has an effect after Chrome is restarted!
|
/// IMPORTANT: This registry configuration only has an effect after Chrome is restarted!
|
||||||
///
|
///
|
||||||
/// See https://www.chromium.org/administrators/policy-list-3#DefaultNotificationsSetting:
|
/// See https://www.chromium.org/administrators/policy-list-3#DefaultNotificationsSetting:
|
||||||
/// • 1 = Allow sites to show desktop notifications
|
/// • 1 = Allow sites to show desktop notifications.
|
||||||
/// • 2 = Do not allow any site to show desktop notifications
|
/// • 2 = Do not allow any site to show desktop notifications.
|
||||||
/// • 3 = Ask every time a site wants to show desktop notifications
|
/// • 3 = Ask every time a site wants to show desktop notifications.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
internal class ChromeNotificationConfiguration : UserHiveConfiguration
|
internal class ChromeNotificationConfiguration : UserHiveConfiguration
|
||||||
|
@ -31,5 +31,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.
|
||||||
public ChromeNotificationConfiguration(Guid groupId, ILogger logger, string sid, string userName) : base(groupId, logger, sid, userName)
|
public ChromeNotificationConfiguration(Guid groupId, ILogger logger, string sid, string userName) : base(groupId, logger, sid, userName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Reset()
|
||||||
|
{
|
||||||
|
return DeleteConfiguration();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,5 +23,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.
|
||||||
public LockWorkstationConfiguration(Guid groupId, ILogger logger, string sid, string userName) : base(groupId, logger, sid, userName)
|
public LockWorkstationConfiguration(Guid groupId, ILogger logger, string sid, string userName) : base(groupId, logger, sid, userName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Reset()
|
||||||
|
{
|
||||||
|
return DeleteConfiguration();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,5 +23,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.
|
||||||
public SignoutConfiguration(Guid groupId, ILogger logger, string sid, string userName) : base(groupId, logger, sid, userName)
|
public SignoutConfiguration(Guid groupId, ILogger logger, string sid, string userName) : base(groupId, logger, sid, userName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Reset()
|
||||||
|
{
|
||||||
|
return DeleteConfiguration();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,5 +23,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.
|
||||||
public TaskManagerConfiguration(Guid groupId, ILogger logger, string sid, string userName) : base(groupId, logger, sid, userName)
|
public TaskManagerConfiguration(Guid groupId, ILogger logger, string sid, string userName) : base(groupId, logger, sid, userName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Reset()
|
||||||
|
{
|
||||||
|
return DeleteConfiguration();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,5 +24,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.
|
||||||
public VmwareOverlayConfiguration(Guid groupId, ILogger logger, string sid, string userName) : base(groupId, logger, sid, userName)
|
public VmwareOverlayConfiguration(Guid groupId, ILogger logger, string sid, string userName) : base(groupId, logger, sid, userName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Reset()
|
||||||
|
{
|
||||||
|
return EnableFeature();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,5 +23,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.ServiceConfigurations
|
||||||
public WindowsUpdateConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
|
public WindowsUpdateConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Reset()
|
||||||
|
{
|
||||||
|
return EnableFeature();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,13 @@ using SafeExamBrowser.Contracts.Logging;
|
||||||
using SafeExamBrowser.Lockdown;
|
using SafeExamBrowser.Lockdown;
|
||||||
using SafeExamBrowser.Logging;
|
using SafeExamBrowser.Logging;
|
||||||
using SafeExamBrowser.ResetUtility.Procedure;
|
using SafeExamBrowser.ResetUtility.Procedure;
|
||||||
|
using SafeExamBrowser.SystemComponents;
|
||||||
|
|
||||||
namespace SafeExamBrowser.ResetUtility
|
namespace SafeExamBrowser.ResetUtility
|
||||||
{
|
{
|
||||||
internal class CompositionRoot
|
internal class CompositionRoot
|
||||||
{
|
{
|
||||||
|
private ProcedureContext context;
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
|
|
||||||
internal ProcedureStep InitialStep { get; private set; }
|
internal ProcedureStep InitialStep { get; private set; }
|
||||||
|
@ -26,14 +28,8 @@ namespace SafeExamBrowser.ResetUtility
|
||||||
|
|
||||||
internal void BuildObjectGraph()
|
internal void BuildObjectGraph()
|
||||||
{
|
{
|
||||||
var context = new ProcedureContext();
|
|
||||||
|
|
||||||
InitializeLogging();
|
InitializeLogging();
|
||||||
|
InitializeContext();
|
||||||
context.CreateBackup = CreateBackup;
|
|
||||||
context.Logger = logger;
|
|
||||||
context.MainMenu = BuildMainMenu(context);
|
|
||||||
context.Update = new SystemConfigurationUpdate(new ModuleLogger(logger, nameof(SystemConfigurationUpdate)));
|
|
||||||
|
|
||||||
InitialStep = new Initialization(context);
|
InitialStep = new Initialization(context);
|
||||||
NativeMethods = new NativeMethods();
|
NativeMethods = new NativeMethods();
|
||||||
|
@ -68,6 +64,17 @@ namespace SafeExamBrowser.ResetUtility
|
||||||
return new FeatureConfigurationBackup(filePath, new ModuleLogger(logger, nameof(FeatureConfigurationBackup)));
|
return new FeatureConfigurationBackup(filePath, new ModuleLogger(logger, nameof(FeatureConfigurationBackup)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitializeContext()
|
||||||
|
{
|
||||||
|
context = new ProcedureContext();
|
||||||
|
context.ConfigurationFactory = new FeatureConfigurationFactory(new ModuleLogger(logger, nameof(FeatureConfigurationFactory)));
|
||||||
|
context.CreateBackup = CreateBackup;
|
||||||
|
context.Logger = logger;
|
||||||
|
context.MainMenu = BuildMainMenu(context);
|
||||||
|
context.Update = new SystemConfigurationUpdate(new ModuleLogger(logger, nameof(SystemConfigurationUpdate)));
|
||||||
|
context.UserInfo = new UserInfo(new ModuleLogger(logger, nameof(UserInfo)));
|
||||||
|
}
|
||||||
|
|
||||||
private void InitializeLogging()
|
private void InitializeLogging()
|
||||||
{
|
{
|
||||||
var appDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), nameof(SafeExamBrowser));
|
var appDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), nameof(SafeExamBrowser));
|
||||||
|
|
|
@ -10,14 +10,17 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using SafeExamBrowser.Contracts.Lockdown;
|
using SafeExamBrowser.Contracts.Lockdown;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
using SafeExamBrowser.Contracts.SystemComponents;
|
||||||
|
|
||||||
namespace SafeExamBrowser.ResetUtility.Procedure
|
namespace SafeExamBrowser.ResetUtility.Procedure
|
||||||
{
|
{
|
||||||
internal class ProcedureContext
|
internal class ProcedureContext
|
||||||
{
|
{
|
||||||
|
internal IFeatureConfigurationFactory ConfigurationFactory { get; set; }
|
||||||
internal Func<string, IFeatureConfigurationBackup> CreateBackup { get; set; }
|
internal Func<string, IFeatureConfigurationBackup> CreateBackup { get; set; }
|
||||||
internal ILogger Logger { get; set; }
|
internal ILogger Logger { get; set; }
|
||||||
internal IList<MainMenuOption> MainMenu { get; set; }
|
internal IList<MainMenuOption> MainMenu { get; set; }
|
||||||
internal ISystemConfigurationUpdate Update { get; set; }
|
internal ISystemConfigurationUpdate Update { get; set; }
|
||||||
|
internal IUserInfo UserInfo { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,25 @@ namespace SafeExamBrowser.ResetUtility.Procedure
|
||||||
Console.CursorVisible = false;
|
Console.CursorVisible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void ClearLine(int top)
|
||||||
|
{
|
||||||
|
Console.SetCursorPosition(0, top);
|
||||||
|
Console.WriteLine(new String(' ', Console.BufferWidth));
|
||||||
|
Console.SetCursorPosition(0, top);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string ReadLine()
|
||||||
|
{
|
||||||
|
Console.Write("> ");
|
||||||
|
Console.CursorVisible = true;
|
||||||
|
|
||||||
|
var input = Console.ReadLine();
|
||||||
|
|
||||||
|
Console.CursorVisible = false;
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
protected void ShowError(string message)
|
protected void ShowError(string message)
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
|
|
@ -6,6 +6,11 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using SafeExamBrowser.Contracts.Lockdown;
|
||||||
|
|
||||||
namespace SafeExamBrowser.ResetUtility.Procedure
|
namespace SafeExamBrowser.ResetUtility.Procedure
|
||||||
{
|
{
|
||||||
internal class Reset : ProcedureStep
|
internal class Reset : ProcedureStep
|
||||||
|
@ -16,6 +21,15 @@ namespace SafeExamBrowser.ResetUtility.Procedure
|
||||||
|
|
||||||
internal override ProcedureStepResult Execute()
|
internal override ProcedureStepResult Execute()
|
||||||
{
|
{
|
||||||
|
InitializeConsole();
|
||||||
|
|
||||||
|
var success = TryGetUserInfo(out var userName, out var sid);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
ResetAll(userName, sid);
|
||||||
|
}
|
||||||
|
|
||||||
return ProcedureStepResult.Continue;
|
return ProcedureStepResult.Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,5 +37,120 @@ namespace SafeExamBrowser.ResetUtility.Procedure
|
||||||
{
|
{
|
||||||
return new MainMenu(Context);
|
return new MainMenu(Context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TryGetUserInfo(out string userName, out string sid)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||||
|
Console.WriteLine("IMPORTANT: Some configuration values are user specific. In order to reset these values, the user specified below needs to be logged in!");
|
||||||
|
Console.ForegroundColor = ForegroundColor;
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("Please enter the name of the user for which to reset all configuration values:");
|
||||||
|
|
||||||
|
userName = ReadLine();
|
||||||
|
|
||||||
|
StartProgressAnimation();
|
||||||
|
var success = Context.UserInfo.TryGetSidForUser(userName, out sid);
|
||||||
|
StopProgressAnimation();
|
||||||
|
|
||||||
|
while (!success)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.WriteLine($"Could not find user '{userName}'!");
|
||||||
|
Console.ForegroundColor = ForegroundColor;
|
||||||
|
|
||||||
|
var tryAgain = new MenuOption { IsSelected = true, Text = "Try again" };
|
||||||
|
var mainMenu = new MenuOption { Text = "Return to main menu" };
|
||||||
|
|
||||||
|
ShowMenu(new List<MenuOption> { tryAgain, mainMenu });
|
||||||
|
|
||||||
|
if (mainMenu.IsSelected)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearLine(Console.CursorTop - 1);
|
||||||
|
ClearLine(Console.CursorTop - 1);
|
||||||
|
ClearLine(Console.CursorTop - 1);
|
||||||
|
ClearLine(Console.CursorTop - 1);
|
||||||
|
|
||||||
|
userName = ReadLine();
|
||||||
|
success = Context.UserInfo.TryGetSidForUser(userName, out sid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetAll(string userName, string sid)
|
||||||
|
{
|
||||||
|
var configurations = Context.ConfigurationFactory.CreateAll(Guid.NewGuid(), sid, userName);
|
||||||
|
var failed = new List<IFeatureConfiguration>();
|
||||||
|
|
||||||
|
Logger.Info($"Attempting to reset all configuration values for user '{userName}' with SID '{sid}'...");
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("Initiating reset procedure...");
|
||||||
|
|
||||||
|
foreach (var configuration in configurations)
|
||||||
|
{
|
||||||
|
var success = configuration.Reset();
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
failed.Add(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowProgress(configurations.IndexOf(configuration) + 1, configurations.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
PerformUpdate();
|
||||||
|
|
||||||
|
if (failed.Any())
|
||||||
|
{
|
||||||
|
HandleFailure(failed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HandleSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("Press any key to return to the main menu.");
|
||||||
|
Console.ReadKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PerformUpdate()
|
||||||
|
{
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("Performing system configuration update, please wait...");
|
||||||
|
StartProgressAnimation();
|
||||||
|
Context.Update.Execute();
|
||||||
|
StopProgressAnimation();
|
||||||
|
Console.WriteLine("Update completed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleFailure(IList<IFeatureConfiguration> configurations)
|
||||||
|
{
|
||||||
|
Logger.Warn($"Failed to reset {configurations.Count} items!");
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.WriteLine($"Failed to reset {configurations.Count} items!");
|
||||||
|
|
||||||
|
foreach (var configuration in configurations)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" - {configuration.GetType().Name}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.ForegroundColor = ForegroundColor;
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("Please consult the application log for more information.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleSuccess()
|
||||||
|
{
|
||||||
|
Logger.Info("Successfully reset all changes!");
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.ForegroundColor = ConsoleColor.DarkGreen;
|
||||||
|
Console.WriteLine("Successfully reset all changes!");
|
||||||
|
Console.ForegroundColor = ForegroundColor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -104,13 +103,11 @@ namespace SafeExamBrowser.ResetUtility.Procedure
|
||||||
|
|
||||||
private void PerformUpdate()
|
private void PerformUpdate()
|
||||||
{
|
{
|
||||||
Logger.Info("Starting system configuration update...");
|
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.WriteLine("Performing system configuration update, please wait...");
|
Console.WriteLine("Performing system configuration update, please wait...");
|
||||||
StartProgressAnimation();
|
StartProgressAnimation();
|
||||||
Context.Update.Execute();
|
Context.Update.Execute();
|
||||||
StopProgressAnimation();
|
StopProgressAnimation();
|
||||||
Logger.Info("Update completed.");
|
|
||||||
Console.WriteLine("Update completed.");
|
Console.WriteLine("Update completed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +157,7 @@ namespace SafeExamBrowser.ResetUtility.Procedure
|
||||||
next = new Reset(Context);
|
next = new Reset(Context);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Info($"The user chose {(yes.IsSelected ? "" : "not ")}to perform a reset for now.");
|
Logger.Info($"The user chose {(yes.IsSelected ? "" : "not ")}to perform a reset.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,10 @@
|
||||||
<Project>{e107026c-2011-4552-a7d8-3a0d37881df6}</Project>
|
<Project>{e107026c-2011-4552-a7d8-3a0d37881df6}</Project>
|
||||||
<Name>SafeExamBrowser.Logging</Name>
|
<Name>SafeExamBrowser.Logging</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\SafeExamBrowser.SystemComponents\SafeExamBrowser.SystemComponents.csproj">
|
||||||
|
<Project>{acee2ef1-14d2-4b52-8994-5c053055bb51}</Project>
|
||||||
|
<Name>SafeExamBrowser.SystemComponents</Name>
|
||||||
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="SafeExamBrowser.ico" />
|
<Content Include="SafeExamBrowser.ico" />
|
||||||
|
|
|
@ -71,7 +71,7 @@ namespace SafeExamBrowser.Runtime
|
||||||
var serviceProxy = new ServiceProxy(appConfig.ServiceAddress, new ProxyObjectFactory(), ModuleLogger(nameof(ServiceProxy)), Interlocutor.Runtime);
|
var serviceProxy = new ServiceProxy(appConfig.ServiceAddress, new ProxyObjectFactory(), ModuleLogger(nameof(ServiceProxy)), Interlocutor.Runtime);
|
||||||
var sessionContext = new SessionContext();
|
var sessionContext = new SessionContext();
|
||||||
var uiFactory = new UserInterfaceFactory(text);
|
var uiFactory = new UserInterfaceFactory(text);
|
||||||
var userInfo = new UserInfo();
|
var userInfo = new UserInfo(ModuleLogger(nameof(UserInfo)));
|
||||||
|
|
||||||
var bootstrapOperations = new Queue<IOperation>();
|
var bootstrapOperations = new Queue<IOperation>();
|
||||||
var sessionOperations = new Queue<IRepeatableOperation>();
|
var sessionOperations = new Queue<IRepeatableOperation>();
|
||||||
|
|
|
@ -7,13 +7,25 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
using SafeExamBrowser.Contracts.SystemComponents;
|
using SafeExamBrowser.Contracts.SystemComponents;
|
||||||
|
|
||||||
namespace SafeExamBrowser.SystemComponents
|
namespace SafeExamBrowser.SystemComponents
|
||||||
{
|
{
|
||||||
public class UserInfo : IUserInfo
|
public class UserInfo : IUserInfo
|
||||||
{
|
{
|
||||||
|
private const string SID_REGEX_PATTERN = @"S-\d(-\d+)+";
|
||||||
|
|
||||||
|
private ILogger logger;
|
||||||
|
|
||||||
|
public UserInfo(ILogger logger)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
public string GetUserName()
|
public string GetUserName()
|
||||||
{
|
{
|
||||||
return Environment.UserName;
|
return Environment.UserName;
|
||||||
|
@ -23,5 +35,77 @@ namespace SafeExamBrowser.SystemComponents
|
||||||
{
|
{
|
||||||
return WindowsIdentity.GetCurrent().User.Value;
|
return WindowsIdentity.GetCurrent().User.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryGetSidForUser(string userName, out string sid)
|
||||||
|
{
|
||||||
|
var strategies = new Func<string, string>[] { NtAccount, Wmi };
|
||||||
|
var success = false;
|
||||||
|
|
||||||
|
sid = default(string);
|
||||||
|
|
||||||
|
foreach (var strategy in strategies)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sid = strategy.Invoke(userName);
|
||||||
|
|
||||||
|
if (IsValid(sid))
|
||||||
|
{
|
||||||
|
logger.Info($"Found SID '{sid}' via '{strategy.Method.Name}' for user name '{userName}'!");
|
||||||
|
success = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Warn($"Retrieved invalid SID '{sid}' via '{strategy.Method.Name}' for user name '{userName}'!");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.Error($"Failed to get SID via '{strategy.Method.Name}' for user name '{userName}'!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
logger.Error($"All attempts to retrieve SID for user name '{userName}' failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string NtAccount(string userName)
|
||||||
|
{
|
||||||
|
var account = new NTAccount(userName);
|
||||||
|
|
||||||
|
if (account.IsValidTargetType(typeof(SecurityIdentifier)))
|
||||||
|
{
|
||||||
|
return account.Translate(typeof(SecurityIdentifier)).Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Wmi(string userName)
|
||||||
|
{
|
||||||
|
var process = new Process();
|
||||||
|
|
||||||
|
process.StartInfo.FileName = "cmd.exe";
|
||||||
|
process.StartInfo.Arguments = string.Format("/c \"wmic useraccount where name='{0}' get sid\"", userName);
|
||||||
|
process.StartInfo.UseShellExecute = false;
|
||||||
|
process.StartInfo.RedirectStandardOutput = true;
|
||||||
|
process.StartInfo.CreateNoWindow = true;
|
||||||
|
process.Start();
|
||||||
|
process.WaitForExit(5000);
|
||||||
|
|
||||||
|
var output = process.StandardOutput.ReadToEnd();
|
||||||
|
var match = Regex.Match(output, SID_REGEX_PATTERN);
|
||||||
|
|
||||||
|
return match.Success ? match.Value : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsValid(string sid)
|
||||||
|
{
|
||||||
|
return !String.IsNullOrWhiteSpace(sid) && Regex.IsMatch(sid, $"^{SID_REGEX_PATTERN}$");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue