insight/src/Agent/Insight.Agent/Network/Handlers/UserHandler.cs

192 lines
No EOL
6.8 KiB
C#

using Insight.Domain.Interfaces;
using Insight.Domain.Network;
using Insight.Domain.Network.Agent.Messages;
using System.Management;
using System.Runtime.Versioning;
namespace Insight.Agent.Network.Handlers;
[SupportedOSPlatform("windows")]
public class UserHandler : IMessageHandler<AgentSession>
{
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
{
switch (message)
{
case InventoryRequest:
{
var result = new Collection<User>();
result.AddRange(GetUsers());
await sender.SendAsync(result, cancellationToken);
break;
}
}
}
private static List<User> GetUsers()
{
var users = QueryUsers();
var groups = GetGroups();
var usergrouping = QueryUserGroupMaps();
foreach (var u in users)
{
u.Groups = [];
foreach (var ug in usergrouping.Where(ug => ug.UserDomain == u.Domain && ug.UserName == u.Name))
{
var grps = groups.Where(g => g.Domain == ug.GroupDomain && g.Name == ug.GroupName);
if (grps is not null)
{
u.Groups.AddRange(grps);
}
}
}
return users;
}
private static List<Group> GetGroups()
{
using var searcher = new ManagementObjectSearcher
{
Scope = new ManagementScope(@"root\cimv2"),
Query = new ObjectQuery("select sid, domain, name, description, localaccount from win32_group")
};
if (searcher.TryGet(out var collection) is false)
{
searcher.Query = new ObjectQuery("select * from win32_group");
if (searcher.TryGet(out collection) is false) throw new InvalidOperationException("WMI Collection NULL");
}
var groups = new List<Group>();
using (collection)
{
foreach (ManagementObject @object in collection.Cast<ManagementObject>())
{
var group = new Group();
var properties = @object.GetPropertyHashes();
group.Sid = @object.GetValue<string>(properties, "sid")?.Trim();
group.Domain = @object.GetValue<string>(properties, "domain")?.Trim();
group.Name = @object.GetValue<string>(properties, "name")?.Trim();
group.Description = @object.GetValue<string>(properties, "description")?.Trim();
group.LocalAccount = @object.GetValue<bool>(properties, "localaccount");
groups.Add(group);
}
}
return [.. groups.OrderBy(x => x.Name)];
}
private static List<User> QueryUsers()
{
using var searcher = new ManagementObjectSearcher
{
Scope = new ManagementScope(@"root\cimv2"),
Query = new ObjectQuery("select sid, name, fullname, description, domain, localaccount, disabled, lockout, status, passwordchangeable, passwordexpires, passwordrequired from win32_useraccount")
};
if (searcher.TryGet(out var collection) is false)
{
searcher.Query = new ObjectQuery("select * from win32_useraccount");
if (searcher.TryGet(out collection) is false) throw new InvalidOperationException("WMI Collection NULL");
}
var users = new List<User>();
using (collection)
{
foreach (ManagementObject @object in collection.Cast<ManagementObject>())
{
var user = new User();
var properties = @object.GetPropertyHashes();
user.Sid = @object.GetValue<string>(properties, "sid")?.Trim();
user.Name = @object.GetValue<string>(properties, "name")?.Trim();
user.FullName = @object.GetValue<string>(properties, "fullname")?.Trim();
user.Description = @object.GetValue<string>(properties, "description")?.Trim();
user.Domain = @object.GetValue<string>(properties, "domain")?.Trim();
user.LocalAccount = @object.GetValue<bool>(properties, "localaccount");
user.Disabled = @object.GetValue<bool>(properties, "disabled");
user.Lockout = @object.GetValue<bool>(properties, "lockout");
user.Status = @object.GetValue<string>(properties, "status")?.Trim();
user.PasswordChangeable = @object.GetValue<bool>(properties, "passwordchangeable");
user.PasswordExpires = @object.GetValue<bool>(properties, "passwordexpires");
user.PasswordRequired = @object.GetValue<bool>(properties, "passwordrequired");
users.Add(user);
}
}
return users;
}
private static List<UserGroupMap> QueryUserGroupMaps()
{
using var searcher = new ManagementObjectSearcher
{
Scope = new ManagementScope(@"root\cimv2"),
Query = new ObjectQuery("select groupcomponent, partcomponent from win32_groupuser")
};
if (searcher.TryGet(out var collection) is false)
{
searcher.Query = new ObjectQuery("select * from win32_groupuser");
if (searcher.TryGet(out collection) is false) throw new InvalidOperationException("WMI Collection NULL");
}
var usergroups = new List<UserGroupMap>();
using (collection)
{
foreach (ManagementObject @object in collection.Cast<ManagementObject>())
{
var usergroup = new UserGroupMap();
var properties = @object.GetPropertyHashes();
var raw = @object.GetValue<string>(properties, "groupcomponent");
var split = raw?.Split(".Domain=")[1]?.Split(",Name=");
if (split is not null && split.Length > 1)
{
usergroup.GroupDomain = split[0].TrimStart('"').TrimEnd('"');
usergroup.GroupName = split[1].TrimStart('"').TrimEnd('"');
}
raw = @object.GetValue<string>(properties, "partcomponent");
split = raw?.Split(".Domain=")[1]?.Split(",Name=");
if (split is not null && split.Length > 1)
{
usergroup.UserDomain = split[0].TrimStart('"').TrimEnd('"');
usergroup.UserName = split[1].TrimStart('"').TrimEnd('"');
}
usergroups.Add(usergroup);
}
}
return usergroups;
}
private class UserGroupMap
{
public string? GroupDomain { get; set; }
public string? GroupName { get; set; }
public string? UserDomain { get; set; }
public string? UserName { get; set; }
}
}