2019-06-21 15:05:31 +02:00
|
|
|
|
/*
|
2024-03-05 18:37:42 +01:00
|
|
|
|
* Copyright (c) 2024 ETH Zürich, IT Services
|
2019-06-21 15:05:31 +02:00
|
|
|
|
*
|
|
|
|
|
* 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;
|
2019-07-19 10:07:45 +02:00
|
|
|
|
using System.Diagnostics;
|
2019-06-21 15:05:31 +02:00
|
|
|
|
using System.Security.Principal;
|
2019-07-19 10:07:45 +02:00
|
|
|
|
using System.Text.RegularExpressions;
|
2019-08-30 09:55:26 +02:00
|
|
|
|
using SafeExamBrowser.Logging.Contracts;
|
|
|
|
|
using SafeExamBrowser.SystemComponents.Contracts;
|
2019-06-21 15:05:31 +02:00
|
|
|
|
|
|
|
|
|
namespace SafeExamBrowser.SystemComponents
|
|
|
|
|
{
|
|
|
|
|
public class UserInfo : IUserInfo
|
|
|
|
|
{
|
2019-07-19 10:07:45 +02:00
|
|
|
|
private const string SID_REGEX_PATTERN = @"S-\d(-\d+)+";
|
|
|
|
|
|
|
|
|
|
private ILogger logger;
|
|
|
|
|
|
|
|
|
|
public UserInfo(ILogger logger)
|
|
|
|
|
{
|
|
|
|
|
this.logger = logger;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-21 15:05:31 +02:00
|
|
|
|
public string GetUserName()
|
|
|
|
|
{
|
|
|
|
|
return Environment.UserName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string GetUserSid()
|
|
|
|
|
{
|
|
|
|
|
return WindowsIdentity.GetCurrent().User.Value;
|
|
|
|
|
}
|
2019-07-19 10:07:45 +02:00
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
2020-03-02 10:46:42 +01:00
|
|
|
|
process.StartInfo.Arguments = $"/c \"wmic useraccount where name='{userName}' get sid\"";
|
2019-07-19 10:07:45 +02:00
|
|
|
|
process.StartInfo.CreateNoWindow = true;
|
2020-02-28 18:59:46 +01:00
|
|
|
|
process.StartInfo.FileName = "cmd.exe";
|
|
|
|
|
process.StartInfo.RedirectStandardOutput = true;
|
|
|
|
|
process.StartInfo.UseShellExecute = false;
|
|
|
|
|
process.StartInfo.WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Windows);
|
2019-07-19 10:07:45 +02:00
|
|
|
|
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}$");
|
|
|
|
|
}
|
2019-06-21 15:05:31 +02:00
|
|
|
|
}
|
|
|
|
|
}
|