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>
|
||||
void Initialize();
|
||||
|
||||
/// <summary>
|
||||
/// Resets the feature to its default configuration. Returns <c>true</c> if successful, otherwise <c>false</c>.
|
||||
/// </summary>
|
||||
bool Reset();
|
||||
|
||||
/// <summary>
|
||||
/// 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>.
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.Lockdown
|
||||
{
|
||||
|
@ -15,6 +16,11 @@ namespace SafeExamBrowser.Contracts.Lockdown
|
|||
/// </summary>
|
||||
public interface IFeatureConfigurationFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates all feature configurations.
|
||||
/// </summary>
|
||||
IList<IFeatureConfiguration> CreateAll(Guid groupId, string sid, string userName);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IFeatureConfiguration"/> to control the option to change the password of a user account via the security screen.
|
||||
/// </summary>
|
||||
|
|
|
@ -22,5 +22,10 @@ namespace SafeExamBrowser.Contracts.SystemComponents
|
|||
/// Retrieves the security identifier of the currently logged in user.
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
|
||||
public bool Reset()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Restore()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SafeExamBrowser.Contracts.Lockdown;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.MachineHive;
|
||||
|
@ -24,6 +25,25 @@ namespace SafeExamBrowser.Lockdown
|
|||
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)
|
||||
{
|
||||
return new ChangePasswordConfiguration(groupId, logger.CloneFor(nameof(ChangePasswordConfiguration)), sid, userName);
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations
|
|||
public abstract bool EnableFeature();
|
||||
public abstract FeatureConfigurationStatus GetStatus();
|
||||
public abstract void Initialize();
|
||||
public abstract bool Reset();
|
||||
public abstract bool Restore();
|
||||
|
||||
public override string ToString()
|
||||
|
|
|
@ -23,5 +23,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.
|
|||
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 override bool Reset()
|
||||
{
|
||||
return DeleteConfiguration();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,5 +23,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.
|
|||
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
|
||||
{
|
||||
/// <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]
|
||||
internal class RemoteConnectionConfiguration : MachineHiveConfiguration
|
||||
{
|
||||
|
@ -23,5 +30,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations.
|
|||
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 override bool Reset()
|
||||
{
|
||||
return DeleteConfiguration();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations
|
|||
itemsToRestore = new List<RegistryDataItem>();
|
||||
}
|
||||
|
||||
protected abstract bool IsHiveAvailable(RegistryDataItem item);
|
||||
|
||||
public override bool DisableFeature()
|
||||
{
|
||||
var success = true;
|
||||
|
@ -66,7 +68,7 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations
|
|||
}
|
||||
else
|
||||
{
|
||||
logger.Warn("Failed to enabled feature!");
|
||||
logger.Warn("Failed to enable feature!");
|
||||
}
|
||||
|
||||
return success;
|
||||
|
@ -148,7 +150,26 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.RegistryConfigurations
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -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 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!
|
||||
///
|
||||
/// See https://www.chromium.org/administrators/policy-list-3#DefaultNotificationsSetting:
|
||||
/// • 1 = Allow sites 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
|
||||
/// • 1 = Allow sites 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.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
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 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 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 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 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 override bool Reset()
|
||||
{
|
||||
return EnableFeature();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,5 +23,10 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.ServiceConfigurations
|
|||
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.Logging;
|
||||
using SafeExamBrowser.ResetUtility.Procedure;
|
||||
using SafeExamBrowser.SystemComponents;
|
||||
|
||||
namespace SafeExamBrowser.ResetUtility
|
||||
{
|
||||
internal class CompositionRoot
|
||||
{
|
||||
private ProcedureContext context;
|
||||
private ILogger logger;
|
||||
|
||||
internal ProcedureStep InitialStep { get; private set; }
|
||||
|
@ -26,14 +28,8 @@ namespace SafeExamBrowser.ResetUtility
|
|||
|
||||
internal void BuildObjectGraph()
|
||||
{
|
||||
var context = new ProcedureContext();
|
||||
|
||||
InitializeLogging();
|
||||
|
||||
context.CreateBackup = CreateBackup;
|
||||
context.Logger = logger;
|
||||
context.MainMenu = BuildMainMenu(context);
|
||||
context.Update = new SystemConfigurationUpdate(new ModuleLogger(logger, nameof(SystemConfigurationUpdate)));
|
||||
InitializeContext();
|
||||
|
||||
InitialStep = new Initialization(context);
|
||||
NativeMethods = new NativeMethods();
|
||||
|
@ -68,6 +64,17 @@ namespace SafeExamBrowser.ResetUtility
|
|||
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()
|
||||
{
|
||||
var appDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), nameof(SafeExamBrowser));
|
||||
|
|
|
@ -10,14 +10,17 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using SafeExamBrowser.Contracts.Lockdown;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
|
||||
namespace SafeExamBrowser.ResetUtility.Procedure
|
||||
{
|
||||
internal class ProcedureContext
|
||||
{
|
||||
internal IFeatureConfigurationFactory ConfigurationFactory { get; set; }
|
||||
internal Func<string, IFeatureConfigurationBackup> CreateBackup { get; set; }
|
||||
internal ILogger Logger { get; set; }
|
||||
internal IList<MainMenuOption> MainMenu { get; set; }
|
||||
internal ISystemConfigurationUpdate Update { get; set; }
|
||||
internal IUserInfo UserInfo { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,25 @@ namespace SafeExamBrowser.ResetUtility.Procedure
|
|||
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)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
* 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
|
||||
{
|
||||
internal class Reset : ProcedureStep
|
||||
|
@ -16,6 +21,15 @@ namespace SafeExamBrowser.ResetUtility.Procedure
|
|||
|
||||
internal override ProcedureStepResult Execute()
|
||||
{
|
||||
InitializeConsole();
|
||||
|
||||
var success = TryGetUserInfo(out var userName, out var sid);
|
||||
|
||||
if (success)
|
||||
{
|
||||
ResetAll(userName, sid);
|
||||
}
|
||||
|
||||
return ProcedureStepResult.Continue;
|
||||
}
|
||||
|
||||
|
@ -23,5 +37,120 @@ namespace SafeExamBrowser.ResetUtility.Procedure
|
|||
{
|
||||
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/.
|
||||
*/
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
@ -104,13 +103,11 @@ namespace SafeExamBrowser.ResetUtility.Procedure
|
|||
|
||||
private void PerformUpdate()
|
||||
{
|
||||
Logger.Info("Starting system configuration update...");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Performing system configuration update, please wait...");
|
||||
StartProgressAnimation();
|
||||
Context.Update.Execute();
|
||||
StopProgressAnimation();
|
||||
Logger.Info("Update completed.");
|
||||
Console.WriteLine("Update completed.");
|
||||
}
|
||||
|
||||
|
@ -160,7 +157,7 @@ namespace SafeExamBrowser.ResetUtility.Procedure
|
|||
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>
|
||||
<Name>SafeExamBrowser.Logging</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.SystemComponents\SafeExamBrowser.SystemComponents.csproj">
|
||||
<Project>{acee2ef1-14d2-4b52-8994-5c053055bb51}</Project>
|
||||
<Name>SafeExamBrowser.SystemComponents</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<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 sessionContext = new SessionContext();
|
||||
var uiFactory = new UserInterfaceFactory(text);
|
||||
var userInfo = new UserInfo();
|
||||
var userInfo = new UserInfo(ModuleLogger(nameof(UserInfo)));
|
||||
|
||||
var bootstrapOperations = new Queue<IOperation>();
|
||||
var sessionOperations = new Queue<IRepeatableOperation>();
|
||||
|
|
|
@ -7,13 +7,25 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Principal;
|
||||
using System.Text.RegularExpressions;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
|
||||
namespace SafeExamBrowser.SystemComponents
|
||||
{
|
||||
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()
|
||||
{
|
||||
return Environment.UserName;
|
||||
|
@ -23,5 +35,77 @@ namespace SafeExamBrowser.SystemComponents
|
|||
{
|
||||
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